Search code examples
reactjsemotion

how to pass multiple classNames to inner children with emotion js


I want to split the components into baseUI one and styled one:

eg. MyComponent.jsx

export default class MyComponent extends React.Component {
  ...
  ...
  render() {
    const { wrapperClassName, className, childClassName } = this.props;
    return (
      <div className={wrapperClassName>
        <div className={className />
        <div className={childClassName} />
      </div>
    )
  }
}

StyledMyComponent.jsx

import styled from 'react-emotion'

const StyledMyComponent = styled(MyComponent)(
  ...
  ...
)

export default StyledMyComponent

however anything I put to the styled function's argument they will go to the className only, is there a way I specify which props goes to which className?

also can I do something like sass/less with children selector? hypothetically something like this:

const classes = css`
  color: red;
  span { // this works
    color: black;
  }
  .childClassName { // this doesn't work
    color: green;
  }

`
<MyComponent className={classes} />

Solution

  • No you can't.

    What you can do, is create specific components for the underlying div. This is how I make my components:

    const MyComponentStyle = styled('div')....;
    const MySecondComponentStyle = styled('div')...;
    const MyThirdStyle = styled('div')...;
    
    const MyComponent = ({ wrapperClassName, childClassName, className }) =>
          <MyComponentStyle className={wrapperClassName}>
            <MySecondComponentStyle className={className} />
            <MyThirdStyle className={childClassName} />
          </MyComponentStyle>
        )
      }
    }
    

    Conditionally styling the element and its children based on class names

    You can conditionally change the styling of stuff below the main component based on its classes.

    Taking your example:

    const Something = () => (
      <MyComponent className={classes}>
        <div className="childClassName">child</div>
        <div className="otherChildClassName">child</div>
      </MyComponent>
    

    You can style the children like so:

    const classes = css`
      color: red;
      span {
        color: black;
      }
      & .childClassName {
        color: green;
      }
    `
    

    note the & character. It essentially means "this class". So & .childClassName means "childrens of this element with class childClassName.

    You could also use &.someClassName (note the lack of space), which would mean: "this element when it also has a class named someClassName.