I'm working on a list where users can click on a list item to perform an action but they can also click a button ( with text ) next to the list item to perform another action.
Given this code ( Reproduction Sandbox => https://stackblitz.com/edit/vitejs-vite-m6y3k8n8?file=src%2Froutes%2Findex.tsx )
import { PostAdd } from '@mui/icons-material';
import {
Button,
List,
ListItem,
ListItemButton,
ListItemText,
} from '@mui/material';
function Page() {
return (
<List>
<ListItem
secondaryAction={
<Button startIcon={<PostAdd />}>Right button</Button>
}
>
<ListItemButton>
<ListItemText primary={'Text'} />
</ListItemButton>
</ListItem>
</List>
);
}
It happens that the right button "merges" with the list item button. The right button is inside the list item button and not right next to it.
When I only use a IconButton
( with no text ) instead of the Button
everything works as expected. ( See https://stackblitz.com/edit/react-f8cswl8t?file=Demo.tsx ) But I want this button to have some Text so I need the Button
element.
My real-world usecase is even more complex since I need to wrap the Button
element inside a @tanstack/router Link
component like so ( https://stackblitz.com/edit/vitejs-vite-usjbw8tp?file=src%2Froutes%2Findex.tsx )
secondaryAction={
<Link to="/" style={{ textDecoration: 'none', color: 'inherit' }}>
<Button startIcon={<PostAdd />}>Secondary Action</Button>
</Link>
}
How do I solve this for the real-world usecase? Or is it only possible to use IconButton
for the secondary action slot?
To resolve your issue (the secondary action button merges with the list item), override Material-UI's default positioning using the sx
prop on the ListItem
:
The Fix: We need to tell Material-UI: "Hey, keep the main list item on the left, and the button on the right – don't squish them together!"
<ListItem
secondaryAction={
<Link to="/" style={{ textDecoration: 'none', color: 'inherit' }}>
<Button startIcon={<PostAdd />}>Secondary Action</Button>
</Link>
}
sx={{
'& .MuiListItemSecondaryAction-root': {
position: 'relative',
transform: 'none',
right: 'auto',
top: 'auto',
},
}}
>
<ListItemButton>
<ListItemText primary="Text" />
</ListItemButton>
</ListItem>
This should makes the secondary action button appear properly aligned next to the list item content.
What Changed:
sx
prop adds special styling rulesExtra Tip:
sx
is Material-UI's way of letting you write CSS styles directly in your componentMuiListItemSecondaryAction-root
is part of Material-UI's internal styling – we’re overriding its default behaviorNote: I HAVEN'T TESTED IT MUCH, SO BE CAREFULL