-
-
Notifications
You must be signed in to change notification settings - Fork 32.3k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[List] Improve ListItemSecondaryAction handling #13597
Comments
@tregusti Your HTML5 semantic isn't valid in your example. It should be </ListItem>
+ <li>
<ListItem button component={NavLink} to="/dfgafdg">
<ListItemText primary="I do not have a li" />
</ListItem>
+ </li>
</List> We are using the following logic on Material-UI side to determine the existance of a secondary action: const children = React.Children.toArray(childrenProp);
const hasSecondaryAction =
children.length &&
isMuiElement(children[children.length - 1], ['ListItemSecondaryAction']); You can do the same. |
That is exactly my problem, hence the reason I opened the issue... If I loop a bunch of items that will contain the information that renders the links. Sometimes I should manually add the As I see it, It the following code, the generated markup will become non-semantic, since <nav>
<List>
{ items.map(item => (
<ListItem ...>
{/*
content based of `item`.
sometimes with and sometimes without secondary action
*/}
</ListItem>
))}
</List>
</nav> If what you suggest is how to do it, then I should take into account how internal code in material-ui looks/works instead of assuming it is consistent. So if this is not a bug, then I would either like a property available telling me if a So please reconsider closing this. Or at least let some mor eyes see it before closing it. |
TL;DR: I agree the code is bloated but that markup is weird in the first place. It equates to buttons inside buttons. I had the same issue when porting the context. It his very hard to reason about a component if that component changes the markup depending on the immediate children. It is very close to breaking component encapsulation and doesn't even handle cases where one would wrap That being said I find the component itself an example where we trade reasonable code for writing shorthand code that does not make sense semantically in the end. What should've happened is a separate PS: I'm totally aware that I might miss many use cases here and look at this from a very simplified perspective but I believe that I rather have a many one or two prop components than a 10 prop component that allows for nonsensical combinations of those. |
I'm raising the issue because your demo states that
There is an intrinsic complexity with nesting buttons and links. Of course. We could make the API more explicit as @eps1lon is suggesting but it won't solve your problem, you still have to code branch the two cases. The upside of @eps1lon's approach is that it's explicit. No surprises, this is great. I have spend hours into try to get the current button nesting logic "right". I understand your frustration, it's a pain to get it right! So, going forward:
|
First off, I really do appreciate all the time you put into the library! So, maybe my demo isn't as clear as I wanted it. I'm not advocating So, my real problem is when using I updated the demo with a new list in the end, clarifying the problem (I hope). https://codesandbox.io/s/20w105myyy For now however, I will go forward as you suggested in your comment. Note to self, do not copy/paste a demo for something else, start from scratch =) |
@tregusti When a You can specify this |
Thank you so much @ryancogswell. This was what I was after (next to a more consistent behaviour =) I will try this out! |
@tregusti Another option to get more consistent markup across your list items would be to always include Here's an example of this (via modifying a CodeSandbox from another ListItem issue): |
For me I was just trying to use the list item styling without being in a List The following will correctly render <ListItem component="div" disableGutters>
<ListItemAvatar>
<Avatar>{ avatarContent }</Avatar>
</ListItemAvatar>
<ListItemText
primary="ListItem is a div"
/>
</ListItem> As soon as I have a <ListItem component="div" disableGutters>
<ListItemAvatar>
<Avatar>1</Avatar>
</ListItemAvatar>
<ListItemText
primary="ListItem is a li"
/>
<ListItemSecondaryAction>
<IconButton edge="end">
<OpenInNewIcon />
</IconButton>
</ListItemSecondaryAction>
</ListItem> |
I think we need to revisit this for v5. The current situation with regards to navs is pretty bad (our "simple" demo is not how you'd mark up a navigation UI). It's too easy to get wrong e.g. <nav>
<List>
<ListItem button component={Link} href="/">
Foo
</ListItem>
</List>
</nav> creates invalid and wrong markup. <nav>
<List>
+ <li>
<ListItem button component={Link} href="/">
Foo
</ListItem>
+ </li>
</List>
</nav> is unintuitive ( It's probably best always add an <nav>
<List>
<ListItem>
<ListItemButton component={NavLink}>
Foo
</ListItemButton>
<ListItemSecondaryAction>
Bar
</ListItemSecondaryAction>
</ListItem>
</List>
</nav> This still has the button vs link problem but at least that's (for better or worse) well established in Material-UI. The upside is that this naturally creates the correct UI (nav > ul > li > a) and nested buttons are discouraged. |
Agree, I think that abstracting two DOM nodes in the initial design was too ambitious, in this context. |
I think Option 1
<ListItem>
<ListItemContent button component={NavLink}>
Foo
<ListItemSecondaryAction>
Bar
</ListItemSecondaryAction>
</ListItemContent>
</ListItem> Option 2
<ListItem button ButtonComponent={NavLink}>
Foo
<ListItemSecondaryAction>
Bar
</ListItemSecondaryAction>
</ListItem> |
This is highly problematic UI since you nest a button within a button. With a new API you shouldn't be able to create this kind of markup or rather it should be harder to do. What happens with |
In terms of accessibility, it's completely wrong. However, Material Design allows it. How can we make this UI harder to do and what to say to users migrating from v4?
Since |
That's the current behavior. Do you think that this is expected behavior by library users? |
The linked page does not include the secondary action in tab order. They probably expect that the author provides other affordances to activate secondary actions. Our demos nests buttons that are both in tab order expecting screen readers to patch broken markup. |
@m4theushw None of these two options seems to be ones we can follow, based on what Sebastian raised.
nav > button <List component="nav">
<ListItem button>
<ListItemText primary="Inbox" />
</ListItem>
</List> ul > li <List>
<ListItem>
<ListItemText primary="Photos" secondary="Jan 9, 2014" />
</ListItem>
</List> ul > li > a + button <List>
<ListItem>
<ListItemButton href="/a">
Foo
</ListItemButton>
<ListItemSecondaryAction>
Bar
</ListItemSecondaryAction>
</ListItem>
</List> |
@oliviertassinari I was thinking about not allowing With the <List>
<ListItem button>
<ListItemButton href="/a">
Foo
</ListItemButton>
<ListItemSecondaryAction>
Bar
</ListItemSecondaryAction>
</ListItem>
</List> |
@m4theushw Yeah, ok, sounds good. It seems that a more idiomatic structure would be: nav > ul> li > button. In this case,
<nav>
<List>
<ListItem>
<ListItemButton>
<ListItemText primary="Inbox" />
</ListItemButton>
</ListItem>
</List>
</nav>
<List>
<ListItem>
<ListItemText primary="Inbox" />
</ListItem>
</List>
<List>
<ListItem>
<ListItemButton href="/a">
Foo
</ListItemButton>
<ListItemSecondaryAction>
Bar
</ListItemSecondaryAction>
</ListItem>
</List>
@eps1lon what do you think? |
This looks good except two things:
|
@eps1lon Do you mean, something in this order? Sounds fair
What would be the underlying DOM structure of these components? Would it be List: |
Expected Behavior
ListItem should consistently either render a
<li>
or not render a<li>
Current Behavior
When adding a
ListItemSecondaryAction
into theListItem
a<li>
is automatically added. If I render a list where some items should have an icon and some do not, this element structure becomes inconsistent.Steps to Reproduce
Link: https://codesandbox.io/s/20w105myyy
<ul>
s.Context
I'm trying to make a generic
ListItemLink
helper that wraps the content inside aListItem
and aNavLink
like this:But since I use
component
property I override the default use of<li>
, however, when adding theListItemSecondaryAction
inside of it a<li>
is added. I assume that this is somehow related to #10452, but cannot understand how to fix it. Is this a bug? If not, how can I work aroun this issue when I do not know beforehand if the content will contain aListItemSecondaryAction
?Your Environment
The text was updated successfully, but these errors were encountered: