June 19, 2024 in MUI, React

Building a Custom Color Picker Component with MUI and React-Color

In modern web applications, integrating a robust and user-friendly color picker can significantly enhance the user experience. This is especially true for design tools, customizable theme interfaces, and other interactive applications. In this blog post, we’ll walk you through creating a custom MUI Color Picker component using Material-UI (MUI) and React-Color.

The MUI Color Picker component we will build leverages Material-UI for the UI elements and React-Color for the color selection functionality. This combination allows us to create a seamless, visually appealing, and accessible color picker.

Here’s the complete code for the MUI Color Picker component:

import {
  FormControl,
  IconButton,
  InputAdornment,
  Popover,
  TextField,
  Typography,
} from "@mui/material";
import { useState, Fragment } from "react";
import PropTypes from "prop-types";
import { SketchPicker } from "react-color";
import SquareIcon from "@mui/icons-material/Square";

// The ColorPicker component allows users to select and input a color in hex format.
// It uses MUI for the UI elements and React-Color for the color picker functionality.
export default function ColorPicker({ hexColor, setHexColor }) {
  // State to manage the anchor element for the popover
  const [anchorEl, setAnchorEl] = useState(null);
  // State to track if there's an error in the hex input
  const [error, setError] = useState(false);

  // Handle the opening of the popover when the color icon is clicked
  const handleClick = (event) => {
    setAnchorEl(event.currentTarget);
  };

  // Handle the closing of the popover
  const handleClose = () => {
    setAnchorEl(null);
  };

  // Determine if the popover is open based on the presence of an anchor element
  const open = Boolean(anchorEl);
  // Assign a unique ID to the popover for accessibility purposes
  const id = open ? "color-picker-popover" : undefined;

  // Handle color changes from the SketchPicker component
  const handleColorChange = (selectedColor) => {
    const newHexColor = selectedColor.hex;
    setHexColor(newHexColor);
  };

  // Handle changes in the hex input field
  const handleHexInputChange = (event) => {
    const inputColor = event.target.value;
    setHexColor(inputColor);

    // Validate the hex color input
    if (/^#([A-Fa-f0-9]{6}|[A-Fa-f0-9]{3})$/.test(inputColor)) {
      setError(false); // Valid hex color
    } else {
      setError(true); // Invalid hex color
    }
  };

  return (
    <Fragment>
      {/* Form control to wrap the text field */}
      <FormControl fullWidth>
        {/* Label for the color picker */}
        <Typography component="label" mb={1} htmlFor="color-picker-input">
          Color Picker
        </Typography>
        {/* Text field for hex color input */}
        <TextField
          id="color-picker-input"
          value={hexColor}
          onChange={handleHexInputChange}
          InputProps={{
            // End adornment with an icon button to open the color picker
            endAdornment: (
              <InputAdornment position="end">
                <IconButton onClick={handleClick} aria-describedby={id} aria-label="select color">
                  {/* Icon to show the current color */}
                  <SquareIcon sx={{ color: hexColor }} />
                </IconButton>
              </InputAdornment>
            ),
          }}
          error={error} // Display error state if the input is invalid
          helperText={error ? "Invalid Color" : ""} // Helper text for error message
        />
      </FormControl>

      {/* Popover for the SketchPicker component */}
      <Popover
        id={id}
        open={open}
        anchorEl={anchorEl}
        onClose={handleClose}
        anchorOrigin={{
          vertical: "bottom",
          horizontal: "left",
        }}
      >
        {/* SketchPicker component for color selection */}
        <SketchPicker color={hexColor} onChange={handleColorChange} />
      </Popover>
    </Fragment>
  );
}

// PropTypes to validate props passed to the ColorPicker component
ColorPicker.propTypes = {
  hexColor: PropTypes.string.isRequired, // hexColor must be a string
  setHexColor: PropTypes.func.isRequired, // setHexColor must be a function
};

Step-by-Step Breakdown

  1. Imports and Initial Setup:
    • We import necessary components from MUI, React, and React-Color.
    • useState is used for managing component state, such as the color value and error state.
  2. Component Definition:
    • The ColorPicker function is defined, accepting hexColor and setHexColor as props.
    • PropTypes are used to ensure these props are passed correctly.
  3. State Management:
    • anchorEl is used to manage the popover’s position.
    • error tracks whether the current hex input is valid.
  4. Event Handlers:
    • handleClick and handleClose manage the opening and closing of the color picker popover.
    • handleColorChange updates the color state when a new color is selected.
    • handleHexInputChange updates the color state based on text input and validates the hex value.
  5. Rendering the Component:
    • A FormControl contains the label and TextField.
    • The TextField includes an InputAdornment with an IconButton that displays the current color.
    • A Popover contains the SketchPicker from React-Color, allowing users to pick a color visually.
  6. PropTypes Validation:
    • We ensure hexColor is a string and setHexColor is a function.

Accessibility and User Experience Enhancements

  • ARIA Attributes: Added aria-describedby and aria-label to improve accessibility.
  • Error Handling: Visual feedback for invalid hex color inputs.
  • Dynamic Icon Color: The color of the SquareIcon dynamically reflects the current color value.

Conclusion

By combining the power of MUI for the UI components and React-Color for the color picker, we have created a robust, accessible, and user-friendly custom MUI Color Picker. This component can easily be integrated into any React application to allow users to select and input colors effectively.

Feel free to customize and extend this MUI Color Picker component further based on your application’s needs. Happy coding!

If you found this guide helpful, consider sharing it with your network or following our blog for more tutorials on building modern web applications with React and MUI. Let us know in the comments how you’re using the MUI Color Picker in your projects!

About the author

Alok Jain

As a Frontend Developer and Founder, I blend technical skills with entrepreneurial drive. Skilled in crafting intuitive user interfaces, I bridge design and development for seamless digital experiences. Beyond work, I'm passionate about Philately, sharing my collection, and connecting with fellow enthusiasts in both tech and stamp collecting communities.

Leave a Reply

Your email address will not be published. Required fields are marked *