3
votes

I'm using Material UI currently in my project. It's working well, but one thing that I can't figure out is how to style child and sibling components using JSS.

For example, Material UI's component renders out to something like this:

<div class="MuiFormControl-root-36 MuiFormControl-marginNormal-37">
   <label class="MuiFormLabel-root-45 MuiInputLabel-root-40 MuiInputLabel-formControl-41 MuiInputLabel-animated-44 MuiInputLabel-shrink-43" data-shrink="true">Field label</label>
   <div class="MuiInput-root-52 MuiInput- 
        formControl-53"><input aria-invalid="false" class="MuiInput-input-60" 
        name="fieldname" type="text" value=""></div>
</div>

From the Material UI documentation I know that is just a wrapper for some of the lower level components. I can target these individual components using createMuiTheme() like this:

MuiInput: {
        formControl: {
            'label + &': {
                marginTop: '30px'
            }
        },
        root: {
            '&$focused': {
                boxShadow: '0px 3px 8px rgba(108, 108, 108, 0.16)'
            },
            borderRadius: '40px',
            padding: '7px 16px',
            background: 'white',
            transition: 'box-shadow 0.2s',
        }
    }

What I don't understand is how to target children and/or siblings in these components - for example, in my createMuiTheme function, how can I target the MuiFormLabel component that is inside the MuiFormControl component? Or, how can I target the MuiInput component if the MuiFormLabel component has a certain class? I know I can target the element using normal CSS (e.g. '& label') but I don't know how to target the component/class since the class names are dynamic.

2
Could you provide a full example in codesandbox.io/s/new or the like ?Ricovitch

2 Answers

0
votes

You can style the MuiFormLabel component directly, why would you need to style it over MuiFormControl?

0
votes

You can wrap each component in its own withStyles HOC and style them directly. Keeping the styles at the component level rather than trying to style the nested components from their parent.

const styles = createStyles({
    root: {
        padding: 0
    },
    childRoot: {
        color: 'red'
    }
});

class MyComponent extends React.Component {
    
    render() {
        const { classes } = this.props;
        
        return (
            <ul className={classes.root}>
                <fooComponent>
                    Bar
                </fooComponent>
            </ul>
        );    
    }
}

const fooComponent = withStyles(styles)((props) => {

    return (
        <li className={classes.childRoot}>
            { props.children }
        </li>
    );
});

export default withStyles(styles)(MyComponent);

Update:

Alternatively if you want to use multiple components in the same file you can wrap them in their own HOC.

const renderFoo = withStyles(styles)((props) => {
  const { bar, classes } = props;
  
  return (
    <div classNames={classes[bar]}>
      Baz
    </div>
  )

}

const MyComponent = (props) => {
  return (
    <div>
      <renderFoo variant='bar' />
    </div>
}

export default MyComponent