Override Material-UI private style

Viewed 710

How can I override a material-ui private style?

I want to change the font color of the slider valueLabel.
In othe words, I want this:
slider with wrong color

To look like this:
enter image description here

Until now, I have tried to override the style globally but it isn't working:

const muiThemeOptions: MuiThemeOptions = {
  overrides:{
    MuiSlider:{
      valueLabel:{
        label:{
          color: "black"
        }
      }
    }
  }
};

Apparently is the valueLabel label style private. Is there a way to override private styles?

Here is a codesandbox for that: https://codesandbox.io/s/so-slider-label-kpp00?file=/demo.tsx

3 Answers

Unfortunately it seems that's not possible to customize the child elements of the PrivateValueLabel that's used by default in the MUI Slider component. The issue has been raised a couple of times in their Github page (@material-ui/#20063, @material-ui/#21912, @material-ui/#20911, ...) and the suggested solution by the maintainers is to create your own ValueLabelComponent with the styling you want and use that in your slider using Slider ValueLabelComponent={YourComponent} ... />. You can also find further documentation about it here.

If you want that component to look similar to the default one, you will have to dig into its source code to get inspired, since it is not a public component. There is an issue created that tracks this problem where it's has been suggested to make that default component public as a temporary workaround, but it hasn't been done yet.

In the css selector text can be targeted as grandchild of valueLabel:

            valueLabel: {
                "& > span > span": {
                    color: "orange",
                    fontWeight: 800
                }
            }

Full example:

const { Slider, Typography, makeStyles } = MaterialUI

const useStyles = makeStyles((theme) => ({
    root: {
        width: 300,
        margin: theme.spacing(3)
    },
    margin: {
        height: theme.spacing(3),
    },
    valueLabel: {
        "& > span > span": {
            color: "orange",
            fontWeight: 800
        }
    }
}))

const marks = [
    { value: 0, label: '0°C' },
    { value: 20, label: '20°C' },
    { value: 37, label: '37°C' },
    { value: 100, label: '100°C' },
];

function valuetext(value) {
    return `${value}°C`;
}

const App = function () {
    const classes = useStyles()

    return (
        <div className={classes.root}>
            <Typography id="discrete-slider-always" gutterBottom>
                Always visible
            </Typography>
            <Slider
                classes={{ valueLabel: classes.valueLabel }}
                defaultValue={80}
                getAriaValueText={valuetext}
                aria-labelledby="discrete-slider-always"
                step={10}
                marks={marks}
                valueLabelDisplay="on"
            />
        </div>
    );
}

ReactDOM.render(<App />, document.getElementById('root'))
<script src="https://unpkg.com/react@17.0.2/umd/react.development.js"></script>
<script src="https://unpkg.com/react-dom@17.0.2/umd/react-dom.development.js"></script>
<script src="https://unpkg.com/@material-ui/core@4.11.3/umd/material-ui.development.js"></script>

<div id="root"></div>

Note sure this is what the OP is looking for (the link to code sandbox seems broken in original question) and I guess it errs on the hacky side but you can impose custom css on the slider's valueLabel (and other components of the slider) through the global style provided you add !important after your custom style changes.

I found that out while trying to modify the value label's css to move it from above the track to below the track, though the same approach works for other aspects of the label's style, such as it's color:

App.js:

import "./styles.css";
import Slider from "@mui/material/Slider";

export default function App() {
  return (
    <div>
      <Slider
        valueLabelDisplay="on"
        defaultValue={2008}
        min={1998}
        max={2017}
        step={1}
      />
    </div>
  );
}

style.css (somehow, !important is only required for some css elements such as .MuiSlider-valueLabelLabel, not others such as .MuiSlider-valueLabel:before):

.MuiSlider-valueLabelLabel {
  color: #000000 !important;
}

.MuiSlider-valueLabel {
  top: 55px !important;
}

.MuiSlider-valueLabel:before {
  top: -6px;
}

https://codesandbox.io/s/objective-ptolemy-xn283p

Related