How to Add Multiple Classes in Material UI Using the Classes Props

How to add multiple classes in Material UI using the classes props?

you can use string interpolation:

<div className={`${this.props.classes.container} ${this.props.classes.spacious}`}>

How to use multiple CSS classes with MUI 5 SX prop?

You can try to use classnames as its commonly used library, or you can just make string from these styles that you pass into sx sx={styles.baseBoxStyle+' '+styles.customBoxFontStyle}

How do you conditionally apply multiple classes to a single Material UI classes prop

material-ui comes with a handy package clsx that makes easier to add classes based on specific conditions. You can pass several class arguments, or also objects that will display the class key if the given value is truthy:

import clsx from 'clsx';

<Drawer
classes={{
paper: {clsx(classes.paperStyle, {[classes.specialPaperStyle]: isSpecial})},
}}
>
Contents of drawer
</Drawer>

docs about clsx on material-ui

How to add multiple classes to a ReactJS Component?

I use classnames when there is a fair amount of logic required for deciding the classes to (not) use. An overly simple example:

...
var liClasses = classNames({
'main-class': true,
'activeClass': self.state.focused === index
});

return (<li className={liClasses}>{data.name}</li>);
...

That said, if you don't want to include a dependency then there are better answers below.

How to type classes when passing them as a prop in material ui

I've been playing with this and there are many possible setups. You can style a material-ui component by passing a single string className and you can also pass an object of classes which correspond to the different selectors available for that component. The primary selector for most (but not all) Material components is root. A Button accepts classes root, label, text, and many others.

When you call makeStyles what you create is an object where the keys are the selectors, basically the same keys as your input, and the values are the string class names for the generated classes. You can import this type as ClassNameMap from @material-ui/styles. It is essentially Record<string, string>, but with an optional generic that lets you restrict the keys.

export type ClassNameMap<ClassKey extends string = string> = Record<ClassKey, string>;

The first argument that you pass to makeStyles or withStyles is your keyed object of styles properties. It can be simplified to Record<string, CSSProperties> or you can import the complex type from material-ui which includes support for functions, etc. The type Styles<Theme, Props, ClassKey> takes three optional generics where Theme is the type of your theme, Props is the component's own props, and ClassKey is again the supported selectors. Theme and Props are mainly included so that you can map your styles as a function of theme or props.

If we want to provide styles to multiple components at once, a simplistic way would be to create a styles object with one key for each component. You can call them anything. We then pass each of those styles as the className to the component.

const MyStyled = withStyles({
button: {
border: "green",
background: "yellow"
},
checkbox: {
background: "red"
}
})(({ classes }: { classes: ClassNameMap }) => (
<Button className={classes.button}>
<Checkbox className={classes.checkbox} />
Text Here
</Button>
));

That setup allows for any number of components at any level of nesting.

I played a bit with making a higher-order component that can wrap your outer component. You can use this as a starting point and tweak it to your needs.

const withAncestralStyles = <Props extends { className?: string } = {}>(
Component: ComponentType<Props>,
style: Styles<DefaultTheme, Omit<Props, "children">, string>
) => {
const useStyles = makeStyles(style);

return (
props: Omit<Props, "children"> & {
children?: (styles: ClassNameMap) => ReactNode;
}
) => {
console.log(props);
const classes = useStyles(props);
const { children, className, ...rest } = props;
return (
<Component {...rest as Props} className={`${className} ${classes.root}`}>
{children ? children(classes) : undefined}
</Component>
);
};
};

Basically, the class classes.root will get automatically applied to the className of the parent while all styles are passed to the child as props (but not applied). I had trouble making React.cloneElement work, so I am requiring that the children of the component be a function which receives the classes object.

const StyledButton = withAncestralStyles(Button, {
root: {
border: "green",
background: "yellow"
},
checkbox: {
background: "red"
}
});

const MyComponent = () => (
<StyledButton onClick={() => alert('clicked')}>
{(classes) => <><Checkbox className={classes.checkbox}/>Some Text</>}
</StyledButton>
);

Code Sandbox

This approach did not work properly with your Tooltip example because Tooltip is one of the components that does not have a root selector and needs to be styled differently to target the popover.

Material UI - How to add multiple `actionIcons` to `ImageListItemBar`?

The actionIcon prop on the <ImageListItemBar> component is a node, so you can put any valid JSX in there, and in your case making a simple container with multiple <IconButtons> should work:

actionIcon={
<>
<IconButton
key="star"
sx={{ color: "white" }}
aria-label={`star ${item.title}`}
>
<StarBorderIcon />
</IconButton>
<IconButton
key="heart"
sx={{ color: "white" }}
aria-label={`favorite ${item.title}`}
>
<FavoriteBorderIcon />
</IconButton>
</>
}

For a working example you can refer to this Sandbox.



Related Topics



Leave a reply



Submit