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
CustomNavLink
is an extended React Router'sNavLink
component that gets anactive
class 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