I'm using MuiThemeProvider in my component and I wanted to style the MenuItem from MUI. What I did here is creating a variable with createMuiTheme like this
const themes = createMuiTheme({
overrides: {
MuiListItem: {
root: {
"&$selected": {
background: '#459FB6',
color: '#fff',
}
}
}
}
});
and I passed this to my ThemeProvider like this
<MuiThemeProvider theme={themes}>
<MenuItem>
Menu Item
</MenuItem>
</MuiThemeProvider>
I also have an object with a color palette and I want to use them inside my themes. My question is how to achieve something like this
const themes = createMuiTheme({
overrides: {
MuiListItem: {
root: {
"&$selected": {
background: colors.blue, // here i want to use my custom variable
color: colors.white, // here i want to use my custom variable
}
}
}
}
});
Thanks in advance!
If someone else stuck with the same problem, I created this answer. I achieved this by using makeStyles instead of createMuiTheme and ThemeProvider. The code sample is down below
const useStyle = makeStyles({
root: {
"&:hover": {
backgroundColor: `${theme.colors.highlight}`,
color: `${theme.colors.white}`,
}
},
selected: {
"&$selected": {
backgroundColor: `${theme.colors.textLink}`,
color: `${theme.colors.white}`,
},
"&$selected:hover": {
backgroundColor: `${theme.colors.highlight}`,
color: `${theme.colors.white}`,
},
},
});
const classes = useStyle();
and then I passed classes to my MenuItem component like this
<MenuItem classes={{ root: classes.root, selected: classes.selected}}>
Menu Item
</MenuItem>
and voila!
Related
How can I change the border properties for an MUI Select component using ThemeProvider? I'm able to change the backgroundColor, but for some reason border properties like border and borderColor do not work.
App.js
import React from "react";
import {
ThemeProvider,
Box,
FormControl,
InputLabel,
MenuItem,
Select,
} from "#mui/material";
import theme from "./theme";
function App() {
return (
<ThemeProvider theme={theme}>
<Box sx={{ minWidth: 200, margin: "5%" }}>
<FormControl>
<InputLabel id="demo-simple-select-label">Select Label</InputLabel>
<Select
labelId="demo-simple-select-label"
id="demo-simple-select"
label="Select Label"
variant="outlined"
sx={{ minWidth: 200 }}
>
<MenuItem value={"1"}>Item 1</MenuItem>
<MenuItem value={"2"}>Item 2</MenuItem>
<MenuItem value={"3"}>Item 3</MenuItem>
</Select>
</FormControl>
</Box>
</ThemeProvider>
);
}
export default App;
theme.js
import { createTheme } from "#mui/material";
const darkGrey = "#262626";
const mediumGrey = "#595959";
const lightGrey = "#adadad";
const white = "#ffffff";
const limeGreen = "3df730";
const theme = createTheme({
components: {
MuiSelect: {
styleOverrides: {
root: {
backgroundColor: mediumGrey,
border: "4px",
borderColor: "red",
},
},
},
// This doesn't work either
// MuiOutlinedInput: {
// styleOverrides: {
// root: {
// border: "4px",
// borderColor: limeGreen,
// },
// },
// },
MuiInputLabel: {
styleOverrides: {
root: {
color: white,
},
},
},
},
});
export default theme;
There are three main issues here:
First, the styleOverrides of the Select component do not have any root property (see https://mui.com/material-ui/api/select/#css). You can use select instead.
Second, your border doesn't have any specified thickness so it won't be visible.
Third, your limeGreen color doesn't start with a # so it won't be recognized as a hex color.
Here is a fixed version of the styling file:
import { createTheme } from '#mui/material';
const darkGrey = '#262626';
const mediumGrey = '#595959';
const lightGrey = '#adadad';
const white = '#ffffff';
const limeGreen = '#3df730';
const theme = createTheme({
components: {
MuiSelect: {
styleOverrides: {
select: {
backgroundColor: mediumGrey,
border: 'solid 3px',
borderColor: limeGreen,
},
},
},
// This doesn't work either
// MuiOutlinedInput: {
// styleOverrides: {
// root: {
// border: "4px",
// borderColor: limeGreen,
// },
// },
// },
MuiInputLabel: {
styleOverrides: {
root: {
color: white,
},
},
},
},
});
export default theme;
I have a navbar with some list items and I want to override the style of MuiListItemText when MuiListItemButton is selected. I can override the hightlight but can't do it with the text or the icon. I can override the ListItemText but all of them, I just want to override if 'selected' (Mui-selected).
I'm using Mui 5.2.0.
This is my approach.
const Theme = createTheme({
components: {
MuiListItemButton: {
styleOverrides: {
root: {
borderRadius: '4px',
padding: '12px',
'&.Mui-selected': {
backgroundColor: '#F2F2EA',
MuiListItemText: {
styleOverrides: {
secondary: {
color: 'red',
...
You should define the overriding theme structure in the same depth.
const Theme = createTheme({
components: {
MuiListItemButton: {
styleOverrides: {
root: {...}
}
},
// it should be another component, not a nested structure
MuiListItemText: {
styleOverrides: {
secondary: {
...
And you can customize an individual component by using sx prop, styled-components, or makeStyles API.
https://mui.com/customization/how-to-customize/
Here's an example using styled-components.
const CustomListItemButton = styled(ListItemButton)(() => ({
borderRadius: '4px',
padding: '12px',
'&.Mui-selected': {
backgroundColor: '#F2F2EA',
...
}));
Try this:
import { createMuiTheme, ThemeProvider } from '#material-ui/core/styles';
I don't think it's the best approach but I was able to do it with something like this:
<ListItemText
secondary={
<Typography
variant="body2"
style={selected === '/' ? { color: 'red' } : { color 'green' }>
Item Text</Typography> } />
I want to change the global style of the disabled Button component from Material-UI. But the problem is I am unable to keep the original color scheme of the button.
Consider this button:
<Button color="secondary" disabled={isLoading}>Create Account</Button>
Now by default Mui-disabled would be attached to this button. Whose color and the background-color are taken from theme.palatte.action property. So this disabled button would be having CSS as:
color: rgba(0,0,0,0.26);
box-shadow: none;
background-color: rgba(0,0,0,0.12);
But I want my disabled button to maintain its original color ("primary, secondary", "error" etc.) added with an opacity of 0.7. By default, the cursor events are set to none by MUI.
I tried it using the custom theme but I don't know how to maintain the original color of the button. E.g if the Button is primary keep the primary color, if the Button is secondary keep the secondary colors.
MuiButton: {
styleOverrides: {
root: {
textTransform: "none",
boxShadow: "none",
"&.Mui-disabled": {
// background: "initial",
// color: "initial",
opacity: .7
}
},
}
}
Of course, I don't want to write a custom code for each code. I can do this even by creating a wrapper around the MUI's button and use that wrapper everywhere in my code.
But I want to do it the MUI way by overriding the theme.
How can I implement a global solution?
Is this what you want? just don't set the disabledBackground color in the palette:
import Button, { buttonClasses } from "#mui/material/Button";
import { createTheme, ThemeProvider } from "#mui/material/styles";
const defaultTheme = createTheme();
const theme = createTheme({
palette: {
action: {
disabledBackground: "", // don't set the disable background color
disabled: "white", // set the disable foreground color
}
},
components: {
MuiButtonBase: {
styleOverrides: {
root: {
[`&.${buttonClasses.disabled}`]: {
opacity: 0.5
},
// Fix ButtonGroup disabled styles.
[`&.${toggleButtonClasses.root}.${buttonClasses.disabled}`]: {
color: defaultTheme.palette.action.disabled,
borderColor: defaultTheme.palette.action.disabledBackground
}
}
}
}
}
);
At the current time I'm writing. There is also other components that reuses the disableBackground property, make sure you take a look and are okay with that too. I display them all in the example below.
Live Demo
With the way that the disabled state is handled in the default styles, I think you need to redefine the default colors within your override in order for it to work.
In the source code you can find how the default colors are defined for the text, outlined, and contained variants.
The example below demonstrates overriding the disabled styles for all three variants with opacity: 0.7 by redefining the non-disabled colors within the "&.Mui-disabled" style overrides.
import * as React from "react";
import Stack from "#mui/material/Stack";
import Button from "#mui/material/Button";
import { createTheme, ThemeProvider } from "#mui/material/styles";
import { alpha } from "#mui/system";
const defaultTheme = createTheme();
const colors = [
"inherit",
"primary",
"secondary",
"success",
"error",
"info",
"warning"
];
const containedColorStyles = {};
const textColorStyles = {};
const outlinedColorStyles = {};
function capitalizeFirstLetter(string) {
return string.charAt(0).toUpperCase() + string.slice(1);
}
colors.forEach((color) => {
containedColorStyles[`&.MuiButton-contained${capitalizeFirstLetter(color)}`] =
color === "inherit"
? {
backgroundColor: defaultTheme.palette.grey[300],
color: defaultTheme.palette.getContrastText(
defaultTheme.palette.grey[300]
)
}
: {
backgroundColor: defaultTheme.palette[color].main,
color: defaultTheme.palette[color].contrastText
};
textColorStyles[`&.MuiButton-text${capitalizeFirstLetter(color)}`] =
color === "inherit"
? {
color: "inherit"
}
: {
color: defaultTheme.palette[color].main
};
outlinedColorStyles[`&.MuiButton-outlined${capitalizeFirstLetter(color)}`] =
color === "inherit"
? {
color: "inherit",
borderColor:
defaultTheme.palette.mode === "light"
? "rgba(0, 0, 0, 0.23)"
: "rgba(255, 255, 255, 0.23)"
}
: {
color: defaultTheme.palette[color].main,
borderColor: `${alpha(defaultTheme.palette[color].main, 0.5)}`
};
});
const theme = createTheme({
components: {
MuiButton: {
styleOverrides: {
root: {
textTransform: "none",
boxShadow: "none",
"&.Mui-disabled": {
...containedColorStyles,
...textColorStyles,
...outlinedColorStyles,
opacity: 0.7
}
}
}
}
}
});
export default function ColorButtons() {
const variants = ["text", "outlined", "contained"];
return (
<ThemeProvider theme={theme}>
{variants.map((variant) => (
<div key={variant}>
{capitalizeFirstLetter(variant)} Variant
<Stack direction="row" spacing={2}>
{colors.map((color) => (
<Button key={color} variant={variant} color={color}>
{capitalizeFirstLetter(color)}
</Button>
))}
</Stack>
Disabled {capitalizeFirstLetter(variant)} Variant
<Stack direction="row" spacing={2} sx={{ mb: 2 }}>
{colors.map((color) => (
<Button key={color} disabled variant={variant} color={color}>
{capitalizeFirstLetter(color)}
</Button>
))}
</Stack>
</div>
))}
</ThemeProvider>
);
}
I have a nice solution for now.
I use the ownerState props to get the color props. Next, I use it in the theme's palette. The following example illustrates how to do this for a contained button.
let theme = createTheme({
palette: {
// Your custom palette
},
});
theme = createTheme(theme, {
components: {
MuiButton: {
defaultProps: {
disableElevation: true
},
styleOverrides: {
root: ({ ownerState }) => ({
'&.MuiButton-contained.Mui-disabled': {
backgroundColor: theme.palette[ownerState.color].main,
}
}),
}
}
}
});
I'm building an app with the Material-UI library for ReactJS. Using the Theme Overrides API, I'm trying to figure out how I can globally style a component, but only when it is a child of another specific component.
For example, I'm trying to set the background/text coloring of MenuItems inside a <Select> menu, where each <MenuItem> contains a <listItemText>. Here's my component:
import { MenuItem, Select, ListItemText } from '#material-ui/core';
import { MuiThemeProvider } from '#material-ui/core/styles';
import * as React from 'react';
import theme from './theme';
const MySelect = props => {
return (
<MuiThemeProvider theme={theme}>
<Select variant="standard" value="2" open>
<MenuItem value="1">
<ListItemText>One</ListItemText>
</MenuItem>
<MenuItem value="2">
<ListItemText>Two</ListItemText>
</MenuItem>
<MenuItem value="3">
<ListItemText>Three</ListItemText>
</MenuItem>
<MenuItem value="4">
<ListItemText>Four</ListItemText>
</MenuItem>
</Select>
</MuiThemeProvider>
);
};
export default MySelect;
Unfortunately, applying a color to the <MenuItem> directly doesn't work because the <ListItemText> overrides it with a <Typography> that has its own coloring set. This is fine for a non-hovered, non-selected state, but if I style the "selected" MenuItem to have a darker background, I need it to have a lighter text.
Here is my theme file:
import { createMuiTheme, createStyles } from '#material-ui/core';
const myTheme = createMuiTheme({
overrides: {
MuiMenuItem: createStyles({
root: {
'&&:hover': {
backgroundColor: 'pink',
color: 'white'
}
},
selected: {
'&&': {
backgroundColor: 'blue',
color: 'white'
},
'&&:hover': {
backgroundColor: 'darkblue',
color: 'white'
}
}
}),
// How do I enforce this ONLY inside of MuiMenuItem and only for
// the selected variant of that?
MuiTypography: {
subheading: {
color: 'white'
}
}
}
});
export default myTheme;
So, my question is: is there a way to do this using just Theme Overrides? Or do I need to conditionally pass this styling into the <ListItemText> component using props? Since most of the styling here fits nicely into Theme Overrides, that seems like a nicer way to do it, but maybe I'm misusing the API.
For a working demo of my above code, see: https://codesandbox.io/s/3r9mkxq231
Any insight is welcome! Thank you!
One way to accomplish that is to target the descendant html element (e.g. the span for the ListItemText) from the ancestor styles (MenuItem in this case).
Here's an example of how the MenuItem.selected style could be specified:
selected: {
"&&": {
backgroundColor: "blue",
color: "white",
"&& span": {
color: "white"
}
},
"&&:hover": {
backgroundColor: "darkblue",
color: "white"
}
}
The full code (forked from your CodeSandbox) is here:
First of all, I don't think we can do that in the theme overrides. Theme overrides is a way to override a default style configuration of an existing material-ui component.
Second, I don't think you need to make it too complex with conditional statements. This can be solved without that also. I didn't understand why did you need to use <ListItemText> when <MenuItem> itself has functionality to display text.
Just simply remove <ListItemText> from you code and then you can use theme overrides to modify your <MenuItem> as you like.
Find the modified code here : https://codesandbox.io/s/30p3o4jjz5
Let me know if this clarifies your doubt.
Yes you can do this in theme overrides using jss-nested syntax:
const myTheme = createMuiTheme({
overrides: {
MuiMenuItem: createStyles({
root: {
"&&:hover": {
backgroundColor: "pink",
"& *": {
color: "white"
}
}
},
selected: {
"&&": {
backgroundColor: "blue",
"& *": {
color: "white"
}
},
"&&:hover": {
backgroundColor: "darkblue",
"& *": {
color: "white"
}
}
}
})
}
});
export default myTheme;
See working codepen here: https://codesandbox.io/embed/308mk7k5x6?fontsize=14
Currently I am struggling with setting the background color of a MenuItem component which is selected to a different color. (without having to using !important to force it)
The component code:
<MenuItem
classes={{
root: this.props.classes.root,
selected: this.props.classes.selected
}}
value={10}>
Alfabetical
</MenuItem>
This is the css:
const homePageStyle = (theme) => ({
root: {
width: "300px"
},
selected: {
backgroundColor: "turquoise !important",
color: "white",
fontWeight: 600
}
});
What do I want to achieve?
I would like to set the backgroundColor of the MenuItem without having to set the !important flag. I've done that with plenty of components but this seems not work around at the moment.
I am using version "#material-ui/core": "^1.0.0-rc.0",
I just made a working example here
For your selected class to be taken into account, you have to set the selected property of your MenuItem component to true
<MenuItem
onClick={this.handleClose}
selected
classes={{ selected: classes.selected }}
>
I'm doing it this way to change the MenuItem background of selected. (selected prop provided by material UI).
export default createMuiTheme({
overrides: {
MuiMenuItem: { // For ListItem, change this to MuiListItem
root: {
"&$selected": { // this is to refer to the prop provided by M-UI
backgroundColor: "black", // updated backgroundColor
},
},
},
},
});
These are the defaults that can be overridden https://material-ui.com/customization/default-theme/#default-theme
Reference: https://material-ui.com/customization/components/#global-theme-override
Note: I'm using Material-UI version 4.9.11
In MUI v5, this is how you do it:
<Select
MenuProps={{
sx: {
"&& .Mui-selected": {
backgroundColor: "pink"
}
}
}}
>
Live Demo
You can updated your styles to this:
const homePageStyle = (theme) => ({
root: {
width: "300px"
},
selected: {
'&.Mui-selected': {
backgroundColor: "turquoise",
color: "white",
fontWeight: 600
}
}
});
This is because of how material-ui styles this component: .MuiListItem-root.Mui-selected
The specificity of those two classes is taking priority over the provided override.
To customize component style in Mui v5, you can try this:
MuiListItemButton: {
styleOverrides: {
root: {
'&.Mui-selected': {
backgroundColor: '#e44444',
}
}
},
},
You'll want to use MuiListItemButton component, because "selected" is deprecated in MuiListItem.
Customizing components: https://mui.com/material-ui/customization/theme-components/