Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can I override the style of the Material-UI switch component when checked?

I want to control the color of the switch component, both when it is checked and when is is unchecked. By default it is red. I want the "ball knob" to be yellow when the state of the switch is checked: true and I want it to be grey when is it checked: false

I must be achieving the styling with the use of createMuiTheme and ThemeProvider I cannot be using classes directly on the component due to the nature of my project.

I have tried to follow the styling example of their custom purple knob here: https://codesandbox.io/s/x8bz8 Source: https://material-ui.com/components/switches/

Unfortunately I haven't been able to figure out how to controle the color the the ball when it is checked (it always falls back to the default red). I have succeeded setting the colors of the track when both checked and not checked, and I have also been able to set the color of the ball when it is not checked. Can someone help me figure out how I can apply color style to the ball when it is checked?

I have made a CodeSandbox where I have been messing around: https://codesandbox.io/s/material-demo-b6153

 const theme = createMuiTheme({
    overrides: {
      MuiSwitch: {
        switchBase: {
          color: "#ccc", // this is working
          "&$checked": { // this is not working
            color: "#f2ff00"
          }
        },
        track: { // this is working
          opacity: 0.2,
          backgroundColor: "#fff",
          "$checked$checked + &": {
            opacity: 0.7,
            backgroundColor: "#fff"
          }
        }
      }
    }
  });

  return (
    <ThemeProvider theme={theme}>
      <FormGroup>
        <FormControlLabel
          control={
            <Switch
              checked={state.checkedA}
              onChange={handleChange}
              name="checkedA"
            />
          }
          label="Custom color"
        />
      </FormGroup>
    </ThemeProvider>
  );

I have also tried this:

checked: {
  "& + $bar": {
    opacity: 1.0,
    backgroundColor: "rgb(129, 171, 134)" // Light green, aka #74d77f
  }
},

Which was proposed in this answer to a somewhat similar question: How do I properly use theme overrides for the MUISwitch "bar" color when checked? but that does not seem to be working for what ever reason, maybe differences in MUI version or because the styles are different when created within createMuiTheme.

like image 256
Rasmus Puls Avatar asked Dec 01 '22 09:12

Rasmus Puls


1 Answers

Switch defaults to using the secondary color.

The color of the thumb is then controlled within the colorSecondary CSS. Here are the default styles for that class:

  /* Styles applied to the internal SwitchBase component's root element if `color="secondary"`. */
  colorSecondary: {
    '&$checked': {
      color: theme.palette.secondary.main,
      '&:hover': {
        backgroundColor: fade(theme.palette.secondary.main, theme.palette.action.hoverOpacity),
        '@media (hover: none)': {
          backgroundColor: 'transparent',
        },
      },
    },
    '&$disabled': {
      color: theme.palette.type === 'light' ? theme.palette.grey[400] : theme.palette.grey[800],
    },
    '&$checked + $track': {
      backgroundColor: theme.palette.secondary.main,
    },
    '&$disabled + $track': {
      backgroundColor:
        theme.palette.type === 'light' ? theme.palette.common.black : theme.palette.common.white,
    },
  },

You can adjust the checked color in your theme with the following (which shows overriding both the thumb and the track):

  const theme = createMuiTheme({
    overrides: {
      MuiSwitch: {
        switchBase: {
          // Controls default (unchecked) color for the thumb
          color: "#ccc"
        },
        colorSecondary: {
          "&$checked": {
            // Controls checked color for the thumb
            color: "#f2ff00"
          }
        },
        track: {
          // Controls default (unchecked) color for the track
          opacity: 0.2,
          backgroundColor: "#fff",
          "$checked$checked + &": {
            // Controls checked color for the track
            opacity: 0.7,
            backgroundColor: "#fff"
          }
        }
      }
    }
  });

Edit customize Switch via theme


For MUI v5

For v5, the structure of the object passed to createTheme changed. Another change is that primary is now the default color rather than secondary, so the colorPrimary styles need to be overridden instead of colorSecondary.

Here is the equivalent code for v5:

import React from "react";
import FormGroup from "@mui/material/FormGroup";
import FormControlLabel from "@mui/material/FormControlLabel";
import Switch from "@mui/material/Switch";
import { createTheme, ThemeProvider } from "@mui/material/styles";

export default function CustomizedSwitches() {
  const [state, setState] = React.useState({
    checkedA: true
  });

  const handleChange = (event: React.ChangeEvent<HTMLInputElement>) => {
    setState({ ...state, [event.target.name]: event.target.checked });
  };

  const theme = createTheme({
    components: {
      MuiSwitch: {
        styleOverrides: {
          switchBase: {
            // Controls default (unchecked) color for the thumb
            color: "#ccc"
          },
          colorPrimary: {
            "&.Mui-checked": {
              // Controls checked color for the thumb
              color: "#f2ff00"
            }
          },
          track: {
            // Controls default (unchecked) color for the track
            opacity: 0.2,
            backgroundColor: "#fff",
            ".Mui-checked.Mui-checked + &": {
              // Controls checked color for the track
              opacity: 0.7,
              backgroundColor: "#fff"
            }
          }
        }
      }
    }
  });

  return (
    <ThemeProvider theme={theme}>
      <FormGroup>
        <FormControlLabel
          control={
            <Switch
              checked={state.checkedA}
              onChange={handleChange}
              name="checkedA"
            />
          }
          label="Custom color"
        />
      </FormGroup>
    </ThemeProvider>
  );
}

Edit customize Switch via theme

like image 145
Ryan Cogswell Avatar answered Dec 03 '22 23:12

Ryan Cogswell