[RFC] ListItem improvement
See original GitHub issueProblem
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.
Issue Analytics
- State:
- Created 2 years ago
- Reactions:4
- Comments:9 (9 by maintainers)
Top GitHub Comments
To push this forward, I suggest we go with solution 1 for v5 and keep an eyes for related API issues
I think people likely to pass props to
ListItemButton
so solution 1 looks cleanerDeveloper can compose by themselves if their feel too much boilerplate for solution 1.
Once v5 is stable and there are complaints about this, we can expose another component like
ListActionItem
above.I suggest to not spend too much time (it’s been over a week already) on this because both ways are far better than the
v4
approach. Let’s try and see the feedback from community.cc @oliviertassinari @mnajdova @michaldudak @eps1lon
Sounds good 👍