Skip to content

[RFC] ListItem improvement #26442

Closed
@siriwatknp

Description

@siriwatknp

Problem

Regarding to #13597

The implementation of ListItem is complex to understand and does too many things that developers does not expect.

  • render ListItemSecondaryAction inside ListItem 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 of ListItem, 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 by a or Link from router library. Developer needs to know to wrap with li

    <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 and ListItemButton 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

Metadata

Metadata

Assignees

No one assigned

    Labels

    component: listThis is the name of the generic UI component, not the React module!discussion

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions