Is there a way for me to customize the appearance of the Material UI switch component when it is in the checked

I am seeking to customize the color of the switch component based on its checked and unchecked state. By default, it displays in red. My goal is to have the "ball knob" appear yellow when the switch is checked and grey when it is not. This styling must be implemented using createMuiTheme and ThemeProvider as I cannot apply classes directly to the component in this particular project.

I have attempted to replicate the customization of the purple knob example provided by Material-UI here: https://codesandbox.io/s/x8bz8 Source: https://material-ui.com/components/switches/

Despite managing to set the colors for the track in both states, as well as the color of the ball when unchecked, I have hit a roadblock with changing the color of the ball when it is checked (it reverts back to red). Can anyone offer assistance in applying the desired color style to the ball when checked?

I have created a CodeSandbox where I have been experimenting: https://codesandbox.io/s/material-demo-b6153

 const theme = createMuiTheme({
    overrides: {
      MuiSwitch: {
        switchBase: {
          color: "#ccc", // this works
          "&$checked": { // this doesn't work
            color: "#f2ff00"
          }
        },
        track: { // this works
          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 also attempted:

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

This was suggested in response to a similar question found here: How do I properly use theme overrides for the MUISwitch "bar" color when checked? However, it does not seem to be working, possibly due to version differences or discrepancies in styles when used within createMuiTheme.

Answer №1

The default setting for the Switch component now uses the secondary color.

To change the color of the thumb, modify the colorSecondary CSS class. Below are the default styles for this 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 customize the checked color in your theme using the following code snippet (which changes both the thumb and track colors):

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"
         }
       }
     }
   }
}); 

https://codesandbox.io/s/customize-switch-via-theme-0wr0j?fontsize=14&hidenavigation=1&theme=dark


Updates for MUI v5

In version 5, the structure of the object passed to createTheme has changed. Also, the default color is now primary instead of secondary, so you need to override the colorPrimary styles rather than colorSecondary.

Here is the equivalent code for MUI 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>
  );
} 

https://codesandbox.io/s/customize-switch-via-theme-1z09hu?fontsize=14&hidenavigation=1&theme=dark

Answer №2

give this a try

const customStyles = makeStyles((theme) => ({  
    toggle_track: {
        backgroundColor: "#f50057",
    },
    toggle_base: {
        color: "#f50057",
        "&.Mui-disabled": {
            color: "#e886a9"
        },
        "&.Mui-checked": {
            color: "#95cc97"
        },
        "&.Mui-checked + .MuiSwitch-track": {
            backgroundColor: "#4CAF50",
        }
    },
    toggle_primary: {
        "&.Mui-checked": {
            color: "#4CAF50",
        },
        "&.Mui-checked + .MuiSwitch-track": {
            backgroundColor: "#4CAF50",
        },
    },
}));

<Toggle
  classes={{
    track: customStyles.toggle_track,
    base: customStyles.toggle_base,
    primaryColor: customStyles.toggle_primary,
  }}
  color={!disabled ? "primary" : "default"}
  checked={value}
  onChange={updateValue}
  name="<your_name>"
  disabled={isDisabled}
/>

Answer №3

Response for MUI version 5

const lightTheme = createTheme({
  components: {
    MuiSwitch: {
      styleOverrides: {
        switchBase: {
          color: "#E60060",
          "&.Mui-checked": {
            color: "#16DF97"
          }
        },
      },
    },
  },
}

Alternatively

<Switch
 name="mySwitch"
 checked={isChecked}
 onChange={handleChange}
 sx={{
  "&.MuiSwitch-root .MuiSwitch-switchBase": {
    color: "red"
  },

  "&.MuiSwitch-root .Mui-checked": {
   color: "green"
  }
 }}
/>

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

The Vue.js component was unable to retrieve the data

I am facing an issue with accessing data inside a simple component. Here is the code for my component: <template> <!-- success --> <div class="message-box message-box-success animated fadeIn" id="message-box-success"> <div cl ...

What could be the reason for not just removing the pseudo-class, but instead deleting the entire CSS document altogether?

var style = document.styleSheets[1] style.deleteRule(`.block__header::after`) console.log(`.block__header::after`) What is preventing it from being removed from the CSS document? The pseudo-class is still found in the console, and when trying to dele ...

Reduce the count by clicking a button while maintaining the previous state

export default class App extends Component { state = { info: [{ name: "Zuko", value: 1 }], }; handleClick = () => { this.setState((prev) => { console.log(prev.info[0].value); return { ... ...

Struggling with parsing JSON strings into PHP arrays

I'm looking to transmit a JSON string using JavaScript and later convert it into an array using a PHP encoding function. After successfully converting the string in JavaScript and transmitting it via Ajax to a PHP page, I am encountering difficulties ...

Display the initial x list items without utilizing ngFor in Angular 2

In the template, there are 9 <li> elements, each with a *ngIf condition present. It is possible that 5 or more of them may return true, but the requirement is to only display the first 4 or less if needed. Priority is given to the order of the < ...

Need to know how to invoke a function from an http callback function that resides in a separate file? Simply use the `app.get("/", callbackFun)` method

Directory Organization: testAPI contactDetail dispMobNo.js myModule.js index.js index.js const express = require("express"); const app = express(); const port = process.env.port || 3000; const getCustNo = require("./cont ...

Implementing setInterval() leads to the dynamic alteration of images

I've created Marquees using CSS animations and a countdown timer. The Marquees display 100 random images that move from left to right and right to left. However, when the countdown timer decreases, the images in the Marquee change but the scrolling co ...

The call signatures for `node-fetch -- typeof import("[...]/node-fetch/index")'` are not properly defined

Originated from this source: https://github.com/node-fetch/node-fetch#json ... my personal code: const fetch = require('node-fetch'); async function doFetch() { const response = await fetch('https://api.github.com/users/github'); ...

The response from the XHR object is coming back as "Object Object

Recently, I've been faced with the challenge of working with an API that provides articles. Within the array returned by the API, there are attributes like author, title, and description. However, despite my efforts, each time I attempt to retrieve th ...

A Guide on Modifying a Pseudo Element When Clicked

How can I create a click handler in jQuery to change the color of an 'eyebrow' element above a Heading element? The eyebrow element is set up with a pseudo element in my project, and I'm struggling to make it change color when the heading is ...

Implementing Vuejs sorting feature post rendering

Currently, I have elements linked to @click event listeners. <th @click="sort('dateadded')" class="created_at">Date Added I am looking for a way to automatically trigger this sorting function when the Vue.js component renders, so that th ...

What are the steps to displaying Jade in an Electron application?

With Express, you can easily establish the view engine as Jade by using the following code snippet: app.set('view engine', 'jade'); This enables Express to parse and deliver compiled HTML from Jade files directly. But how can this be ...

Are there any other options besides using the React Material-UI makeStyles() function for styling class Components?

While experimenting with the makeStyles() function in Material-UI's React library, I encountered a specific error message: The use of hooks is limited to the body of a function component. Below is a snippet of the code that triggered this error: ...

When the jQuery keyup event is triggered, the "function" will be incremented to 0

There are three input fields to search a JSON tree. When all three fields are filled correctly, the data from the next level of the JSON tree is retrieved. A number is incremented through the keyup event to access the next data of the JSON tree. However, ...

Launch a PowerPoint presentation in a separate tab on your web browser

If you have a link that leads to a .pdf file, it will open in a new tab like this: <a target="_blank" href="http://somePDF.pdf">Download</a> But what about a Powerpoint file, such as a .ppt? Is there a way to make it open in a new browser tab ...

unable to connect to the web service using webview

When attempting to call a web service or display an alert, I am encountering some issues: Here is the code from my activity: mWebView = (WebView)findViewById(R.id.webViewRootAciviy); mWebView.setWebViewClient(new WebViewClient()); mWebView.setWebChromeCl ...

Require a function to be invoked upon the user's action of closing the browser tab

Lately, I've been encountering a challenge. I need to call a method when the user closes a tab or window, but before that happens, I want to execute a particular function. My project is in functional component ReactJS. Any help in resolving this issue ...

Obtain the content of a dynamic text input field from a nested directive

I recently developed a custom directive using AngularJS that contains a child directive. The child directive's main task is to create various dynamic input elements like textboxes, radio buttons, and checkboxes, each with default values sourced from a ...

Using Vuejs to pass the SAVE function into a CRUD component

I am facing a challenge in finding a suitable solution that involves advanced parent-child communication in Vue.js. The scenario is such that there are multiple parent components, each with its own logic on how to save data. On the other hand, there is onl ...

Disabling the submit button after submitting the form results in the page failing to load

I am encountering an issue with my HTML form that submits to another page via POST. After the form validates, I attempt to disable or hide the submit button to prevent double submission and inform the user that the next page may take some time to load. He ...