Consider the following component structure of a side-bar navigation:
<ListItem button dense component={CustomNavLink} to="/dashboard">
<ListItemIcon>
<DashboardIcon />
</ListItemIcon>
<ListItemText primary="Dashboard" />
</ListItem>
The task is to change the ListItemIcon and ListItemText appearance on hover or when the CustomNavLink becomes active.
Note that
CustomNavLinkis an extended React Router'sNavLinkcomponent that gets anactiveclass applied to when it matches with the current route.
The following, somewhat hacky way achieves that (abridged and simplified for clarity) via classes property:
const styles = {
root: {
...
'&.active, &:hover, &.active:hover': {
'& path': {
fill: 'red'
},
'& span': {
color: 'red'
}
}
}
};
(classes are then applied to the ListItem component)
This seems like an extremely lousy way of going about it, as the structure of the nested components leaks into the parent's styling... which is akin to doing this in the "old" CSS:
div:hover > ul > li > a {
color: red;
}
What is the idiomatic Material-UI way of solving this?
For reference, this is how it would be done in
styled-components:const CustomNavLink = styled(NavLink)` ... &:hover { ${ListItemIcon} { path: { fill: red; } } ${ListItemText} { color: red; } } `;
Please Try following example for Change Material UI ListItem children on hover/active
const wrapperStyles = {
parent: {
backgroundColor: 'yellow',
'&:hover $child': {
color: 'red'
}
},
child: {
fontSize: '2em',
padding: 24
}
}
Expanding answer by @Patel Charul. In case you want to change the style of multiple children on hover.
const wrapperStyles = {
parent: {
backgroundColor: 'yellow',
'&:hover': {
'& $child1': {
color: 'red'
},
'& $child2': {
color: 'blue'
}
},
child1: {
fontSize: '2em',
padding: 24
},
child2: {
fontSize: '4em',
padding: 28
}
}
This is one way to do it in MUI v5, first import the following components:
import ListItem, { listItemClasses } from "@mui/material/ListItem";
import ListItemButton from "@mui/material/ListItemButton";
import ListItemIcon from "@mui/material/ListItemIcon";
import ListItemText from "@mui/material/ListItemText";
Then define the your custom NavLink, this NavLink will add the active className when it matches the current route:
function MyNavLink(props) {
return <NavLink {...props} activeClassName="active" />;
}
Then in the List component, add the following styles to style the ListItem in active and hover state:
<List
sx={{
[`& .active, & .${listItemClasses.root}:hover`]: {
color: "red",
fontWeight: "bold",
"& svg": {
fill: "red"
}
}
}}
>
<ListItem component={MyNavLink} to="/" exact>
<ListItemButton>
<ListItemIcon>
<InboxIcon />
</ListItemIcon>
<ListItemText primary="Home" />
</ListItemButton>
</ListItem>
{/* other NavLink component */}
</List>
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With