Description
Problem
Regarding to #13597
The implementation of ListItem
is complex to understand and does too many things that developers does not expect.
-
render
ListItemSecondaryAction
insideListItem
cause the markup to change<ListItem> Some text </ListItem> // result // <div>Some text</div> <ListItem> Some text <ListItemSecondaryAction> action </ListItemSecondaryAction> </ListItem> // result // <div> // <div>Some text</div> // <button>action</div> // </div>
This cause a lot of confusion to developer. Moreover, the
ContainerProps
is added for customization which add more API for the developer to know. -
when
button
prop is true,ButtonBase
is used which change the default tag ofListItem
, again cause confusion and developer needs to know the implementation detail<ListItem> Some text </ListItem> // result => <li>Some text</li> <ListItem button> Some text </ListItem> // result => <div>Some text<div>
-
Frequently, the
ListItem
is override bya
orLink
from router library. Developer needs to know to wrap withli
<li> <ListItem button component={Link}> Some text </ListItem> </li>
Goal
List components tends to be used to create new component like nested menu, link item, and many more. So, material-ui should provide the list components that are styled with material design spec and simple to compose together without needing to know much about the implementation.
- no children checking
- no DOM changing between prop
- no
container
props
Solution I : One element, One DOM #26446
From comments and issues, one way to improved is to extract button
out of ListItem
so each component render only single markup
// v4
<ListItem button>...</ListItem>
// v5
<ListItem>
<ListItemButton>...</ListItemButton>
</ListItem>
Pros
- least API (no nested component API)
- types is straight forward
- replacing with routing library is similar to
Button
Cons
- Developer needs to know the markup before picking the component
- using
ListItem
andListItemButton
together require nested CSS & negative margin. (customise padding will require negative margin adjustment)
Solution II : Flat ListItemButton #26480
ListItemButton
always render 2 DOM, by default <li> <div>
// v4
<ListItem button>...</ListItem>
// v5
<ListItemButton>...</ListItemButton>
Pros
- no nested css specificity, custom styles is straight forward
Cons
- hard to manage types
- overriding via
componentsProps
Secondary Action
Both solutions will use the same API for handling secondary action. Regardless of the approach, ListItem
and ListItemButton
accept secondaryAction
prop.
<ListItem secondaryAction={...}>
<ListItemButton secondaryAction={...}>
This will remove the hidden logic to check if children has ListItemSecondaryAction
or not.
Breaking change?
Instead of making this as breaking change
, I prefer to adjust ListItem
and mark some prop like button
as deprecated and then remove them in next major version because I assume that most of the project use ListItem
in some way.
Further
from @eps1lon suggestion, it is nice to expose UnorderedList
and OrderedList
as a wrapper of ListItem
like Chakra-UI does.
cc @mui-org/core