1

I am using a <Form/> component from a component library. The form has a child component for the submit button.

const loginForm = [
  {
    label: "Username",
    required: true,
    type: "text"
  },
  {
    label: "Password",
    required: true,
    type: "password"
  }
]

<LoginForm
  width={{ xs: 12, md: 4 }} 
  autoComplete={false}
  buttonDisabled={buttonDisabled}
  buttonLabel="LOGIN"
  fields={loginForm}
  onChange={this.onChange}
  onSubmit={data => login({ variables: data })}
/>

which generates this html:

enter image description here

I am wanting to target the button to style it. Was hoping to do something like this:

const LoginForm = styled(Form)`
  Button_StyledButton{
    outline: black solid 10px;
  }
`

Essentially targeting the form and then the child button component.

Can this be done with styled components?

Stretch0
  • 8,362
  • 13
  • 71
  • 133
  • May i know which component library you are using? – Arun Yokesh Jul 17 '18 at 09:53
  • Take a look on this : https://stackoverflow.com/questions/48713421/target-child-element-styled-components?rq=1 – Arun Yokesh Jul 17 '18 at 09:55
  • Unfortunately it's not a publicly available one – Stretch0 Jul 17 '18 at 09:56
  • @ArunYokesh I did see that post but that is a different use case. They are passing in the child component as a child. The difference here is the button element I am trying to target is generated by the parent form component. – Stretch0 Jul 17 '18 at 09:58
  • Have you tried writing `const LoginForm = styled(Form)\` > Button_StyledButton ...`? Also, does the `Form` element use the `className` prop given to it? – Tholle Jul 17 '18 at 10:20
  • @Tholle yes i have tried that, as I have it in my original post but to no avail. The button doesn't have a class `Button_StyledButton` but it does have that as a `data-id`. The class it is given is generated by styled components which is a random string of characters and changes on each build so can't rely on that. – Stretch0 Jul 17 '18 at 11:20

1 Answers1

2

Since it's not a public library you're using, make sure your library avail you to pass className prop.

The styled method works perfectly on all of your own or any third-party components as well, as long as they pass the className prop to their rendered sub-components, which should pass it too, and so on. Ultimately, the className must be passed down the line to an actual DOM node for the styling to take any effect.

If this condition is satisfied, you can take advantage of the styled(LoginForm) approach.

I don't know the DOM structure generated by your LoginForm, but you can effectively target the button by a normal css selector.

Let's assume the DOM structure is this:

<form>
  <label>...</label>
  <input .../>
  <label>...</label>
  <input .../>
  <button>...</button>
</form>

Then you can target this button in the styled-components's styled method like this:

const LoginForm = styled(Form)`
  button {
    outline: black solid 10px;
  }
`

The selector really depends on the DOM structure, you need to adjust that to your needs.

If the className prop is not passed down the component tree in library you're using, you need to provide a wrapper component:

const Wrapper = styled.div`
  button {
    outline: black solid 10px;
  }
`
<Wrapper>
  <LoginForm
    width={{ xs: 12, md: 4 }} 
    autoComplete={false}
    buttonDisabled={buttonDisabled}
    buttonLabel="LOGIN"
    fields={loginForm}
    onChange={this.onChange}
    onSubmit={data => login({ variables: data })}
  />
</Wrapper>

CodeSandbox example: https://codesandbox.io/s/2w3owyjy2n

Patrik Prevuznak
  • 2,181
  • 15
  • 14