Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Using props to set '&:hover' background-color

I'm wrapping MUI's Chip component so that I can pass in values other than "primary" and "secondary" for the colors prop. I also want to maintain the hover effect if the chip is clickable so that the chip transitions to a different color when the cursor is over it. The colors are passed in as props, so it's easy enough to set the backgroundColor and color:

<Chip
  style={{
    backgroundColor: props.backgroundColor,
    color: props.color
  }}
/> 

However, since I'd also like to pass in the hover color as a prop, I'd need to do something like this:

<Chip
  style={{
    backgroundColor: props.backgroundColor,
    color: props.color,
    '&:hover': {
      backgroundColor: props.hoverBackgroundColor,
      color: props.hoverColor
    }
  }}
/> 

However, the &:hover (as far as I know) can't be used inside of the style prop. Typically, the &:hover would be used inside of a styles object that is passed into withStyles, but I'm not able to access props from in there. Any suggestions?

like image 731
matwlev Avatar asked Mar 05 '19 17:03

matwlev


People also ask

Can we set props to state in React?

Where the props are used to set the initial state of the Component is a general anti-pattern of React. This implies that the state of the component is tied to the props of the component. The issue with doing this is that the constructor is only ever called once in the life cycle of the component.

How do I pass a prop to a component?

To pass props, add them to the JSX, just like you would with HTML attributes. To read props, use the function Avatar({ person, size }) destructuring syntax.

Should I use props or state?

Use state to store the data your current page needs in your controller-view. Use props to pass data & event handlers down to your child components. These lists should help guide you when working with data in your components.


1 Answers

You can achieve this by creating your own custom chip component. In order to be able to use props to control the styling, you can use the makeStyles. The makeStyles function returns a hook that can accept an object parameter for providing variables to your styles.

Here's a possible CustomChip implementaton:

import React from "react";
import Chip from "@material-ui/core/Chip";
import { makeStyles } from "@material-ui/core/styles";
import { emphasize } from "@material-ui/core/styles/colorManipulator";

const useChipStyles = makeStyles({
  chip: {
    color: ({ color }) => color,
    backgroundColor: ({ backgroundColor }) => backgroundColor,
    "&:hover, &:focus": {
      backgroundColor: ({ hoverBackgroundColor, backgroundColor }) =>
        hoverBackgroundColor
          ? hoverBackgroundColor
          : emphasize(backgroundColor, 0.08)
    },
    "&:active": {
      backgroundColor: ({ hoverBackgroundColor, backgroundColor }) =>
        emphasize(
          hoverBackgroundColor ? hoverBackgroundColor : backgroundColor,
          0.12
        )
    }
  }
});
const CustomChip = ({
  color,
  backgroundColor,
  hoverBackgroundColor,
  ...rest
}) => {
  const classes = useChipStyles({
    color,
    backgroundColor,
    hoverBackgroundColor
  });
  return <Chip className={classes.chip} {...rest} />;
};
export default CustomChip;

The styling approach (including the use of the emphasize function to generate the hover and active colors) is based on the approach used internally for Chip.

This can then be used like this:

      <CustomChip
        label="Custom Chip 1"
        color="green"
        backgroundColor="#ccf"
        onClick={() => {
          console.log("clicked 1");
        }}
      />
      <CustomChip
        label="Custom Chip 2"
        color="#f0f"
        backgroundColor="#fcc"
        hoverBackgroundColor="#afa"
        onClick={() => {
          console.log("clicked 2");
        }}
      />

Here's a CodeSandbox demonstrating this:

Edit Chip color (forked)


Here's a Material-UI v5 version of the example:

import Chip from "@material-ui/core/Chip";
import { styled } from "@material-ui/core/styles";
import { emphasize } from "@material-ui/core/styles";
import { shouldForwardProp } from "@material-ui/system";
function customShouldForwardProp(prop) {
  return (
    prop !== "color" &&
    prop !== "backgroundColor" &&
    prop !== "hoverBackgroundColor" &&
    shouldForwardProp(prop)
  );
}
const CustomChip = styled(Chip, { shouldForwardProp: customShouldForwardProp })(
  ({ color, backgroundColor, hoverBackgroundColor }) => ({
    color: color,
    backgroundColor: backgroundColor,
    "&:hover, &:focus": {
      backgroundColor: hoverBackgroundColor
        ? hoverBackgroundColor
        : emphasize(backgroundColor, 0.08)
    },
    "&:active": {
      backgroundColor: emphasize(
        hoverBackgroundColor ? hoverBackgroundColor : backgroundColor,
        0.12
      )
    }
  })
);

export default CustomChip;

Edit Chip color

like image 164
Ryan Cogswell Avatar answered Oct 21 '22 09:10

Ryan Cogswell