Tips for customizing the selected and hover color of ListItem in Material UI

Having trouble getting the 'selected' or 'hover' colors to work for the ListItem component. I've tried setting its classes like this:

<ListItem selected button key="home" classes={{ selected: classes.listItemSelected }}>
  <ListItemText primary="Hi"/>
</ListItem>

and then defining the style as follows:

const useStyles = makeStyles((theme) => ({
  listItemSelected:{
    backgroundColor: "#ff0000",
  },
}));

However, this approach doesn't seem to have any effect. The 'selected' property is documented in the ListItem component API available here.

Does anyone know how to successfully customize the color of both the selected and hover states for the ListItem?

Answer №1

Check out the snippet from the default ListItem styles specifically focusing on background color:

export const styles = (theme) => ({
  /* Styles applied to the `component` element, usually the root. May be enclosed by a `container`. */
  root: {
    '&$focusVisible': {
      backgroundColor: theme.palette.action.selected,
    },
    '&$selected, &$selected:hover': {
      backgroundColor: theme.palette.action.selected,
    },
    '&$disabled': {
      opacity: 0.5,
    },
  },
  /* Pseudo-class for `focusVisibleClassName` prop of the `component` when `button={true}`. */
  focusVisible: {},
  /* Styles applied to inner `component` if `button={true}`. */
  button: {
    transition: theme.transitions.create('background-color', {
      duration: theme.transitions.duration.shortest,
    }),
    '&:hover': {
      textDecoration: 'none',
      backgroundColor: theme.palette.action.hover,
      // Reset on touch devices, not adding specificity
      '@media (hover: none)': {
        backgroundColor: 'transparent',
      },
    },
  },
  /* Pseudo-class for root element when `selected={true}`. */
  selected: {},
});

Note that the selected styling utilizes two classes (root and selected), so overriding it with a single class won't have enough specificity.

Here's an example demonstrating how to override selected and hover states:

import React from "react";
import { makeStyles, withStyles } from "@material-ui/core/styles";
import List from "@material-ui/core/List";
import MuiListItem from "@material-ui/core/ListItem";
import ListItemIcon from "@material-ui/core/ListItemIcon";
import ListItemText from "@material-ui/core/ListItemText";
import Divider from "@material-ui/core/Divider";
import InboxIcon from "@material-ui/icons/Inbox";
import DraftsIcon from "@material-ui/icons/Drafts";

const useStyles = makeStyles((theme) => ({
  root: {
    width: "100%",
    maxWidth: 360,
    backgroundColor: theme.palette.background.paper
  }
}));

const ListItem = withStyles({
  root: {
    "&$selected": {
      backgroundColor: "red",
      color: "white",
      "& .MuiListItemIcon-root": {
        color: "white"
      }
    },
    "&$selected:hover": {
      backgroundColor: "purple",
      color: "white",
      "& .MuiListItemIcon-root": {
        color: "white"
      }
    },
    "&:hover": {
      backgroundColor: "blue",
      color: "white",
      "& .MuiListItemIcon-root": {
        color: "white"
      }
    }
  },
  selected: {}
})(MuiListItem);

export default function SelectedListItem() {
  const classes = useStyles();
  const [selectedIndex, setSelectedIndex] = React.useState(1);

  const handleListItemClick = (event, index) => {
    setSelectedIndex(index);
  };

  return (
    <div className={classes.root}>
      <List component="nav" aria-label="main mailbox folders">
        <ListItem
          button
          selected={selectedIndex === 0}
          onClick={(event) => handleListItemClick(event, 0)}
        >
          <ListItemIcon>
            <InboxIcon />
          </ListItemIcon>
          <ListItemText primary="Inbox" />
        </ListItem>
        <ListItem
          button
          selected={selectedIndex === 1}
          onClick={(event) => handleListItemClick(event, 1)}
        >
          <ListItemIcon>
            <DraftsIcon />
          </ListItemIcon>
          <ListItemText primary="Drafts" />
        </ListItem>
      </List>
      <Divider />
      <List component="nav" aria-label="secondary mailbox folder">
        <ListItem
          button
          selected={selectedIndex === 2}
          onClick={(event) => handleListItemClick(event, 2)}
        >
          <ListItemText primary="Trash" />
        </ListItem>
        <ListItem
          button
          selected={selectedIndex === 3}
          onClick={(event) => handleListItemClick(event, 3)}
        >
          <ListItemText primary="Spam" />
        </ListItem>
      </List>
    </div>
  );
}

https://codesandbox.io/s/listitem-selected-and-hover-3bp7r?fontsize=14&hidenavigation=1&theme=dark

Other relevant answers:

  • How to overried the selected classes in menuItem in material ui REACTjs?
  • How to change the styles of ListItem element with the "onclick" event?

Answer №2

You have the option to utilize the sx prop in MUI v5:

<List
  sx={{
    // selected and (selected + hover) states
    '&& .Mui-selected, && .Mui-selected:hover': {
      bgcolor: 'red',
      '&, & .MuiListItemIcon-root': {
        color: 'pink',
      },
    },
    // hover states
    '& .MuiListItemButton-root:hover': {
      bgcolor: 'orange',
      '&, & .MuiListItemIcon-root': {
        color: 'yellow',
      },
    },
  }}
>

Alternatively, you can use styled to craft a styled component that can be utilized multiple times:

import MuiList from '@mui/material/List';

const List = styled(MuiList)({
  // selected and (selected + hover) states
  '&& .Mui-selected, && .Mui-selected:hover': {
    backgroundColor: 'red',
    '&, & .MuiListItemIcon-root': {
      color: 'pink',
    },
  },
  // hover states
  '& .MuiListItemButton-root:hover': {
    backgroundColor: 'orange',
    '&, & .MuiListItemIcon-root': {
      color: 'yellow',
    },
  },
});

Check out the Live Demo

https://codesandbox.io/s/61486061-how-to-set-selected-and-hover-color-of-listitem-in-material-ui-ywdp9?file=/demo.tsx

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Looking to display all items once the page has finished loading

I am experiencing a minor issue. Every time I access my store page where all products are listed, I have to click on the size filter to load the products. This is not ideal as I want all products to be displayed automatically when the page loads. What modi ...

Nested paths are not supported by React-Router-DOM

Currently, I have a straightforward AppContainer component in which I'm utilizing the following packages to navigate throughout the entire app: "react-router-dom": "^4.3.1", "react-router-redux": "^4.0.8" However, I am facing an issue when attemptin ...

What is the best way to ensure input text fills the entire grid?

Take a look at this code snippet: <div class="form-group col-md-6"> <label class="col-md-4">Last Updated (Real Time)</label> <input class="form-control col-md-8" type="text" ng-model="status.lastUpdated" ng-readonly="true"/ ...

Using the OR Operator with a different function in React

Struggling with setting the day flexibility using disableDate(1,2,3,4,0) but it's not functioning as expected. Can you assist me in fixing this issue? Here is the function snippet: const disableDate = (date) => { const day = date.day(); retur ...

Implement a CSS style for all upcoming elements

I'm currently developing a Chrome extension tailored for my personal needs. I am looking to implement a CSS rule that will be applied to all elements within a certain class, even if they are dynamically generated after the execution of my extension&ap ...

Tips on aligning a v-btn alongside v-expansion-panels on the same row

Struggling with aligning my layout. Trying to get a single set of v-expansion-panels and a v-btn in the same row, both visually centered within a card. I managed to almost achieve it in this codepen: https://codepen.io/anzuj/pen/PoPPbdw with the following ...

Implementing a feature in ReactJS that enables users to select a minimum and maximum limit for checkboxes

I have developed a unique React application that incorporates JSON values into checkbox elements. The JSON data includes both minimum and maximum required values. I successfully implemented a function to set the checkboxes' maximum value based on the ...

Clicking on a flex card will trigger the opening of a new page where the parsed data will be displayed in a stylish manner using JavaScript

Currently, I am attempting to showcase the data retrieved from the following URL: . My objective is to format the parsed data with a specific style. However, I have encountered difficulties accomplishing this using `window.open()`. Any assistance in resolv ...

Encountering an error during the process of adding dependencies through yarn install

When attempting to set up material-ui locally with yarn install, I encountered an issue where the node modules were not being created. Instead, I received a series of error messages: │ @mui/monorepo: The override for '/@babel/core' includes a ...

Concealing an element in Material UI by clicking on it or when the checkbox is

Is there a way to hide an element when a button is clicked or a checkbox is checked? I've searched online for a solution but couldn't find one. Can anyone provide guidance on how to achieve this? I need to hide the first MenuItem that contains a ...

Tables lacking borders where rowspans are present

I'm currently using Firefox and have the following code snippet: html, body { width: 100%; height: 100%; } * { box-sizing: border-box; } body { padding-left: 20px; padding-right: 20px; } .visitentabelle { border: 2px solid black; ...

Trying to align two divs side by side with the first one floating left and the second one fixed in position? Unfortunately

Here is an example that I have: https://jsfiddle.net/2z2ksLy4/ HTML: <div class="one"> test </div> <div class="two"> test2 </div> CSS: .one{ width:400px; border:1px solid red; min-height: 200px; float:left; display: ...

Sliding Navigation Panel

Currently, I am attempting to implement a sidebar push navigation that mimics the one showcased here. My HTML structure includes content within a center element div. The code snippet is as follows: <div id="mySidenav" class="sidenav"> <a href="j ...

There is a vast expanse separating the header of the page and the navigation bar

Hello! I'm trying to figure out why there is a huge space between the top of the page and the navbar on this site: . I've included the CSS and HTML below. Any help would be greatly appreciated, thank you! HTML: <!DOCTYPE html> <html> ...

An error occurs when attempting to assign a value to a MUI file TextField

Struggling with setting the value of a MUI Textfield that has type="file" props, resulting in the following exception being thrown: Uncaught DOMException: An attempt was made to use an object that is not, or is no longer, usable Interest ...

Nesting maps in JavaScript is a powerful way to transform

I'm in the process of developing a budgeting app using React and JavaScript. At the moment, I have successfully generated a table displaying various costs. Name Budget Used $ Used % Available Food 300 300 100 0 Streaming services 600 600 100 ...

Extracting Tailwind color palette through API request

After conducting some research, I have not been able to find a definitive answer to my query. I possess a CMS API that supplies branding colors and other assets for a React application that can dynamically change its appearance using a combination of colo ...

Creating CSS-in-JS Components in React JS without External Stylesheet interference

import React, { Component } from "react"; import './navbar.css' class NavBar extends Component { render() { return ( <div> navbar content </div> ); } } export default NavBar; If I were to ...

The command "react-scripts" couldn't be located in the current environment

Currently enrolled in a Udemy course that involves using create-react-app. However, I encounter an error when attempting to run npm start and/or yarn start. You can find the course here: Complete React Developer in 2020 (w: Redux, Hooks, GraphQL) To init ...

Encountering a fragment error while utilizing create-react-library

Recently, I embarked on the journey of publishing a React component to npm that I had created. In my quest for knowledge, I stumbled upon create-react-library, which I decided to use for the first time. As I started testing my component from the test folde ...