How to Add Filtering, Subheader, and Styling to the Material-UI List Component

The Material-UI List component is handy because it has lots of out-of-the-box functionality. Take a look at the following API’s the List examples in the docs hook into:

However, finding example beyond the docs, or simply understanding clearly how to use some of the customizations, can be challenging. In this demo we use the Checkbox List example in the docs and add filtering, a subheader, and tons of styling.

Here’s what we will build:

The Code Sandbox with full React code is in the Resources section.

Material-UI List and Related Components

In case you are not familiar with the List component, it is a wrapper that is intended to (usually) contain a set of ListItem components that are rendered by looping through a list of data. There are other components like ListSubheader and ListItemText that contain helpful APIs for nicely presenting this data.

The List and related components are similar to Card components. In fact, instead of using the subcomponents (ListItemText and so on), similar presentation could be accomplished with a List wrapper containing an array of ListItems, each of which could contain a card component. Or, potentially even skip the ListItem component in this hierarchy.

Regardless of presentation choice, MUI provided an impressive amount of customization in these components. In the following code, I did not use Cards but instead stuck to ListItems like the original MUI example I forked. Here’s how to custom style Card components if you do choose to use them.

Material-UI List Filter

Filtering a list of items can be made simple with a third party library to handle the UI and a few functions to handle the actual filtering logic.

I like the library material-ui-search-bar. It’s small and the props are well named and work great. See the JSX below for how I configured our List app demo:

<SearchBar
  value={searched}
  onChange={(searchVal) => requestSearch(searchVal)}
  onCancelSearch={() => cancelSearch()}
  placeholder="filter"
/>

Here’s another great material-ui-search-bar example.

All we need for the filter logic are a few functions to handle change and cancel.

First, our unfiltered data:

const originalItems = [
  "Dill Pickles",
  "Sweet Pickles",
  "Bananas",
  "Burger",
  "Hot Dog"
];

Then, the functions:

const [items, setItems] = useState(originalItems);
const [searched, setSearched] = useState("");

const requestSearch = (searchedVal) => {
  const filteredItems = originalItems.filter((item) => {
    return item.toLowerCase().includes(searchedVal.toLowerCase());
  });
  setItems(filteredItems);
};

const cancelSearch = () => {
  setSearched("");
  requestSearch(searched);
};

In this case, our ‘search bar’ is really acting like a filter. Searching and filtering are really different approaches to how data is queried and when it is reduced. In this example, we already have the data and are filtering down based on user input.

Material-UI List Subheader

The list subheader is actually a separate component in Material-UI.

<List
  className={classes.listRoot}
  subheader={
    <ListSubheader
      color={"primary"}
      inset
      className={classes.subheader}
    >
      Grocery List!
    </ListSubheader>
  }
>

Think you’re a JavaScript expert? Test yourself on these 50 difficult JavaScript questions.


The List component’s subheader prop can take any kind of node, but ListSubheader was created by MUI team specifically to be passed in as a node for Lists. It has several props for formatting. In this case, I used inset which bumps the text to the right significantly. The ListSubheader is also sticky and has gutters (padding) by default, but these can be disabled.

Styling can be applied to a ListSubheader based on what props are set. For example, I targeted the global class MuiListSubheader-inset which is only applied because I set the inset prop on the component.

subheader: {
  backgroundColor: "rgba(0,0,0,0.1)",
  fontSize: 24,
  "&.MuiListSubheader-inset": { marginBottom: 12 }
},

No global class needed to be targeted to set subheader background color or font size. These are simply in the class directly applied to the ListSubheader component.

Material-UI List Styling

We will add the following stylings:

  • list background color
  • list item hover color
  • list item font size/text size
  • list item divider width

(Here’s how to custom style checkbox components)

All of the styling above can be accomplished through knowledge of the DOM and Material-UI’s global classes API.

listRoot: {
  width: "100%",
  backgroundColor: "rgba(0,0,0,0.1)",
  marginTop: 12,
  "& .MuiListItem-root": {
    "&:hover": {
      color: "orange"
    },
    "&.MuiListItem-divider": {
      borderBottom: "2px solid rgba(0,0,0,0.1)"
    }
  }
},
listItemText: {
  "& .MuiListItemText-primary": {
    fontSize: "1.2rem"
  }
}

We’ll discuss these stylings in a moment, but we also need to look at the JSX:

<ListItem
  key={item}
  role={undefined}
  dense
  button
  onClick={handleToggle(index)}
  divider
>
//Skipping a few lines of JSX
  <ListItemText
    id={labelId}
    primary={item}
    className={classes.listItemText}
  />
</ListItem>

Notice that the ListItemText has a class directly applied to it. Also, ListItem has the divider prop applied (this is different than the Divider component). These affect the global class API and what selectors we can use.

I’ll go down the line discussing stylings, articulating them in ‘plain English’:

  • List background color – Simply apply a class to the List component and set the background color. To set background color on List Items, target that component directly.
  • List Item hover color – My selector targets elements with MuiListItem-root class applied that are children of elements with listRoot class applied. Then it selects these items only when the hover pseudo class is applied.
  • List Item font size/text size – My selector targets elements with MuiListItemText-primary class applied that are children of elements with listItemTextclass applied.
  • List Item divider width – My selector targets elements with MuiListItem-root AND MuiListItem-divider class applied that are children of elements with listRoot class applied (complicated!). The divider class is only applied when divider prop is enabled. The ‘divider’ is really just a border bottom, so override this with whatever style you want.

Resources

Here’s how to use the List component to construct a nav list.

Code Sandbox:

List API Docs

List Item API Docs

List Subheader API Docs

Share this post:

Leave a Comment

This site uses Akismet to reduce spam. Learn how your comment data is processed.