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

Caution: ReactJs reminds you that every child in a list must possess a distinct "key" prop

I'm currently working on a project for managing a contracting company, and part of the requirement is to display all receipts for each user in the company. However, I encountered the following error: Warning: Each child in a list should have a unique ...

Encasing extracted content in <p> tags

On my Wordpress Site, I have extracted images and text separately to use in different sections of my single.php file. Utilizing HTML within the Bootstrap 3 framework: <div class="row"> <div class="col-md-12"> <?php ...

After logging in successfully, the React app needs a hard refresh to update the

I'm encountering a debugging challenge and would appreciate any assistance from the community. I've been working on my first React app and successfully implemented a Login feature, but after a user logs in, they have to hard refresh their browser ...

Having difficulty kicking off a fresh React project on Windows

I've encountered an issue while setting up my React application on Windows OS. After running npm start, the application fails to load on localhost:3000, showing the error message Cannot GET /. Below is the project structure: - webpack.config.js - p ...

Tips for integrating a personalized tab indicator hue in Material-UI v1

Currently, my production site is operating smoothly with MUI v1 beta 32. It's time to upgrade to v1! Fortunately, the changes needed so far have been straightforward. Mainly just updating the import tags. However, I've encountered an issue with ...

Can Redux toolkit be integrated into the getStaticProps function in Next.js?

When I switch from using getStaticProps to useEffect, I am able to retrieve the data successfully. However, I encountered an issue with getStaticProps stating that hooks can only be used in functional components. import Head from 'next/head' impo ...

Preventing default CSS styles in ASP.NET: A step-by-step guide

When working with multiple CSS files for different themes, I noticed that the Login Page is calling one extra CSS file. However, during runtime, some classes from the default CSS are still being used. How can I resolve this issue? ...

Issue with the left margin of the background image

I am currently facing an issue with a series of background images that are supposed to fade in and out behind my content. These images are centered, wider than the content itself, and should not affect the width of the page. However, there is an unexpected ...

Placing a div with absolute positioning inside another div with absolute positioning raises the question of how it functions when the outer div is not set to position: relative

Trying to grasp the concept, I experimented with the following setup: <div id="Outer"> <div id="Inner"></div> </div> In this scenario, the outer div has a relative position and the inner div has an absolute position. This allo ...

Set the search input to occupy the full width of the container by utilizing Bootstrap's

I'm having trouble adjusting the width of my search input to 100% on screen resize (using @media (max-width: 1200px)). The issue: https://i.sstatic.net/EMr6W.jpg Here's how it should look (I can achieve this with a specific pixel width, but not ...

Easily generate a hierarchical layout in HTML with this straightforward method

I'm currently working on implementing a hierarchical tree structure for a website. I need to organize a user's projects, tasks, and sub-tasks in a visually appealing manner using HTML elements. Any suggestions or creative ideas are welcome! ...

Utilizing Material-UI: Implementing input properties with TextField

Looking to enhance the accessibility of my input fields (TextField) by adding aria-* attributes. This is what I've attempted: const props = { InputProps: { 'aria-label': 'myAriaLabel' } } // ... <TextField {...props} ...

Ways to attach an item using its lower point instead of its upper coordinate

I am currently working on a poker table project using React. As of now, I have player components that need to be strategically positioned around the table. One challenge I'm facing is that when the screen attribute changes, the position of the top tw ...

Adjusting Media Queries according to the browser window's zoom level

Is there a way to detect the browser width dynamically? For instance, can I adjust the CSS styling based on zoom adjustments like ctrl + or ctrl -? By "box," I am referring to a perfectly square shape. So, when the browser width is 100%, I want a layout wi ...

Top tips for setting up node_modules for a ReactJS application on Azure Linux Web App

My React web app, specifically built on NextJS, is currently running on a Linux Azure Web App Server. I have successfully deployed it using GitHub Actions, but now I am struggling to find the most efficient way to deploy the node_modules. This is what I h ...

Utilizing React Typescript to Dynamically Restrict Props Configuration Based on Data

I am new to TypeScript and I have a question regarding passing dynamic data to a React component while restricting props setting. I came across a simple component with the constraint of "RandomNumberProps", where the component can only accept either "isPo ...

Disable the 'Show All' button in the Mui Datagrid columns panel when all filters are selected

https://i.stack.imgur.com/eNlWH.png Is there a way to disable the "show all" button in the datagrid columns panel when all filters are checked? I've looked into the button classes for Mui-disabled in CSS but couldn't find a solution. How can I g ...

Creating a CSS key animation for resizing an image: What is the correct way to make an image expand and contract

Check out this CSS key animation example: http://jsfiddle.net/ryurage/Q2ELp/ I'm attempting to make an image grow and occupy most of the window when triggered by user interaction like hovering or click-and-hold. Subsequently, I want the image to shr ...

Concealing overflow for text content through CSS styling

I am currently working with an element that contains both an image and text. View the Fiddle here Note: To see the full grid, resize the preview accordingly. The CSS I have written is as follows: .gridster .gs-w .item{ position: relative; wi ...

Encountered an error: setUser function not found while attempting to log in or sign up

Hi there! Check out the code on codesandbox created using react hooks. I have been working on implementing a login and register functionality with Material UI. The idea is that when I try to register myself in the registration card, then click on login fr ...