How to customize the border for MUI components - reactjs

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;

Related

Dark Mode in react using MUI v5

Trying to create a Toggle to switch from dark mode to light mode has been quite difficult for me in v5.
Using the code directly from MUI Sandbox MUI darkmode, I attempted to separate the code to work in the app.js and my Navbarpractice.js.
App.js
import React from "react";
import useMediaQuery from '#mui/material/useMediaQuery';
import { createTheme, ThemeProvider } from '#mui/material/styles';
import CssBaseline from '#mui/material/CssBaseline';
import { Paper } from "#mui/material";
import BasicCard from "./components /Card.js";
import Navbarpractice from "./components /Navbar/Navbarpractice"
const ColorModeContext = React.createContext({ toggleColorMode: () => {} });
function App() {
const [mode, setMode] = React.useState('light');
const colorMode = React.useMemo(
() => ({
toggleColorMode: () => {
setMode((prevMode) => (prevMode === 'light' ? 'dark' : 'light'));
},
}),
[],
);
const theme = React.useMemo(
() =>
createTheme({
palette: {
mode,
},
}),
[mode],
);
return (
<ColorModeContext.Provider value={colorMode}>
<ThemeProvider theme={theme}>
<div className="App">
<Navbarpractice/>
<BasicCard/>
</div>
</ThemeProvider>
</ColorModeContext.Provider>
);
}
export default App;
Navbarpractice.js
import React from 'react';
import AppBar from '#mui/material/AppBar';
import Box from '#mui/material/Box';
import Toolbar from '#mui/material/Toolbar';
import Typography from '#mui/material/Typography';
import Button from '#mui/material/Button';
import IconButton from '#mui/material/IconButton';
import MenuIcon from '#mui/icons-material/Menu';
import { useTheme, ThemeProvider, createTheme } from '#mui/material/styles';
import { teal } from '#mui/material/colors';
import { withStyles } from '#mui/styles';
import { Switch } from '#mui/material';
import Brightness4Icon from '#mui/icons-material/Brightness4';
import Brightness7Icon from '#mui/icons-material/Brightness7';
const label = { inputProps: { 'aria-label': 'Switch' } };
const ColorModeContext = React.createContext({ toggleColorMode: () => {} });
const theme = createTheme({
Navbar: {
primary: {
// Purple and green play nicely together.
main: teal[500],
},
secondary: {
// This is green.A700 as hex.
main: '#11cb5f',
},
},
});
const TealTextTypography = withStyles({
root: {
color: "#008080"
}
})(Typography);
function Navbar() {
const theme = useTheme();
const colorMode = React.useContext(ColorModeContext);
return (
<ColorModeContext.Provider value={colorMode}>
<ThemeProvider theme={theme}>\
<Box sx={{ flexGrow: 1 }}>
<AppBar position="static"
style={{ background: 'transparent', boxShadow: 'none'}}>
<Toolbar>
<IconButton
size="large"
edge="start"
aria-label="menu"
sx={{ mr: 2 }}
>
<MenuIcon />
</IconButton>
<TealTextTypography variant="h6" component="div" sx={{ flexGrow: 1 }}>
Mentors
</TealTextTypography>
<TealTextTypography variant="h6" component="div" sx={{ flexGrow: 1 }}>
Mentees
</TealTextTypography>
<Box
sx={{
display: 'flex',
width: '100%',
alignItems: 'center',
justifyContent: 'center',
bgcolor: 'background.default',
color: 'text.primary',
borderRadius: 1,
p: 3,
}}
>
<IconButton sx={{ ml: 1 }} onClick={colorMode.toggleColorMode} color="inherit">
{ theme.palette.mode === 'dark' ? <Brightness7Icon /> : <Brightness4Icon />}
</IconButton>
</Box>
</Toolbar>
</AppBar>
</Box>
</ThemeProvider>
</ColorModeContext.Provider>
);
}
export default Navbar;
I am certain I am mixing up my const. and placing them in the wrong places. Although I am new to react and Mui I did manage to get it to work statically, however, the toggle is proving to be difficult.
This seem to work for me
App.js
import React from 'react';
import {
ThemeProvider,
createTheme,
responsiveFontSizes,
} from '#mui/material/styles';
import { deepmerge } from '#mui/utils';
import useMediaQuery from '#mui/material/useMediaQuery';
import { getDesignTokens, getThemedComponents } from 'theme/Theme';
import { ColorModeContext } from 'config/color-context';
export default function App() {
const prefersDarkMode = useMediaQuery('(prefers-color-scheme: dark)');
const [mode, setMode] = React.useState();
React.useEffect(() => {
setMode(prefersDarkMode ? 'dark' : 'light');
}, [prefersDarkMode]);
const colorMode = React.useMemo(
() => ({
toggleColorMode: () => {
setMode((prevMode) => (prevMode === 'light' ? 'dark' : 'light'));
},
}),
[]
);
let theme = React.useMemo(
() =>
createTheme(deepmerge(getDesignTokens(mode), getThemedComponents(mode))),
[mode]
);
theme = responsiveFontSizes(theme);
return (
<ColorModeContext.Provider value={colorMode}>
<ThemeProvider theme={theme}>
...
</ThemeProvider>
</ColorModeContext.Provider>
);
}
Theme.js
import { amber, deepOrange, grey, blue, common } from '#mui/material/colors';
const palette = {
light: {
primary: {
main: '#34C0AC',
light: '#B1DED3',
dark: '#00765A',
},
},
};
export const getDesignTokens = (mode) => ({
palette: {
mode,
...(mode === 'light'
? {
primary: {
main: palette.light.primary.main,
light: palette.light.primary.light,
dark: palette.light.primary.dark,
},
divider: amber[200],
text: {
primary: grey[900],
secondary: grey[800],
},
}
: {
primary: deepOrange,
divider: deepOrange[700],
background: {
default: deepOrange[900],
paper: deepOrange[900],
},
text: {
primary: '#fff',
secondary: grey[500],
},
}),
},
typography: {
fontFamily: [
'Oswald',
'Roboto',
'"Helvetica Neue"',
'Arial',
'sans-serif',
].join(','),
body1: {
fontFamily: 'Poppins, Arial, sans-serif',
},
},
});
export const getThemedComponents = (mode) => ({
components: {
...(mode === 'light'
? {
MuiAppBar: {
styleOverrides: {
colorPrimary: {
backgroundColor: grey[800],
},
},
},
MuiLink: {
variant: 'h3',
},
MuiButton: {
styleOverrides: {
root: {
borderRadius: 0,
color: common.white,
fontFamily:
"Oswald, Roboto, 'Helvetica Neue', Arial, sans-serif",
fontSize: 20,
borderWidth: 2,
'&:hover': {
borderWidth: 2,
},
},
},
variants: [
{
props: { variant: 'contained' },
style: {
fontFamily:
"Oswald, Roboto, 'Helvetica Neue', Arial, sans-serif",
},
},
{
props: { variant: 'outlined' },
style: {
color: palette.light.primary.main,
},
},
{
props: { variant: 'primary', color: 'primary' },
style: {
border: '4px dashed blue',
},
},
],
},
MuiList: {
styleOverrides: {
root: {},
},
},
MuiMenuItem: {
styleOverrides: {
root: {
color: common.white,
alignItems: 'stretch',
fontFamily:
"Oswald, Roboto, 'Helvetica Neue', Arial, sans-serif",
},
},
},
MuiAccordion: {
styleOverrides: {
root: {
color: common.white,
fontFamily:
"Oswald, Roboto, 'Helvetica Neue', Arial, sans-serif",
},
},
},
}
: {
MuiAppBar: {
styleOverrides: {
colorPrimary: {
backgroundColor: blue[800],
},
},
},
}),
},
});
color-context.js
import React from 'react';
export const ColorModeContext = React.createContext({
toggleColorMode: () => {
// This is intentional
},
});
ThemeToggler.js
import React from 'react';
import { IconButton, Box } from '#mui/material';
import { useTheme } from '#mui/material/styles';
import Brightness4Icon from '#mui/icons-material/Brightness4';
import Brightness7Icon from '#mui/icons-material/Brightness7';
import { ColorModeContext } from 'config/color-context';
export default function SubHeaderNavigation() {
const theme = useTheme();
const colorMode = React.useContext(ColorModeContext);
return (
<Box
sx={{
display: 'flex',
width: '100%',
alignItems: 'center',
justifyContent: 'center',
bgcolor: 'background.default',
color: 'text.primary',
borderRadius: 1,
p: 3,
}}
>
{theme.palette.mode} mode
<IconButton
sx={{ ml: 1 }}
onClick={colorMode.toggleColorMode}
color="inherit"
>
{theme.palette.mode === 'dark' ? (
<Brightness7Icon />
) : (
<Brightness4Icon />
)}
</IconButton>
</Box>
);
}
Make sure you are not nesting your Themes or both could be negated.
For example:
App.tsx
<>
<ThemeProvider theme={!isDark ? lightTheme : darkTheme}>
<CssBaseline />
<Dashboard />
</ThemeProvider>
</>
Dashboard.tsx taken from here
function Dashboard() {
...
return (
<ThemeProvider theme={mdTheme}>
<Box sx={{ display: 'flex' }}>
<CssBaseline />
...
</ThemeProvider>
);
}
export default function Dashboard() {
return <DashboardContent />;
}
The effect of this will negate the Themes in the App.tsx config.

How to keep the background color of disabled Button in Material-UI?

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

How to change border color material-ui select component [duplicate]

I want to alter the style of the SelectInput. I'm using a class based component. I set it up this way:
const QuoteListStyle = {
color: "#eceff1",
borderBottom: "1px solid #90caf9",
"&:hover:not($disabled):not($focused):not($error) $underline": {
borderBottom: "2px solid #90caf9"
},
width: "196px",
marginTop: "1rem"
};
Then in the render I have this section with the Select:
<FormControl>
<Select
style={QuoteListStyle}
value={this.state.quoteListName}
onChange={this.handleChange}
displayEmpty={true}
renderValue={
this.state.quoteListName > 0
? undefined
: () => <em>{this.state.quoteListName}</em>
}
>
<MenuItem value="" disabled>
<em>Select a Quote List</em>
</MenuItem>
{data.me.quoteList.map(item => {
return (
<MenuItem value={item.name} key={item.name}>
{item.name}
</MenuItem>
);
})}
</Select>
</FormControl>
I'm using the basic Select component that only has an underline. I want to change the color and size of the underline. I looked here in the source:
https://github.com/mui-org/material-ui/blob/master/packages/material-ui/src/Select/SelectInput.js
What do I look for to control the underline?
I am seeing the underline that I want when the component loads. The hover is not working. After an item from the Select is chosen, I see my style on top but the default style is below and I can see some of that color.
I would be ok using overrides for this. Here's my theme code:
const theme = createMuiTheme({
palette: {
primary: {
main: "#90caf9",
contrastText: "#f5f5f5"
},
secondary: {
main: "#19857b"
},
error: {
main: "#f44336"
},
background: {
default: "#102027",
paper: "#37474f"
},
text: {
primary: "#eceff1",
secondary: "#90caf9"
},
button: {
borderColor: "#90caf9"
}
},
overrides: {
MuiOutlinedInput: {
root: {
"& $notchedOutline": {
borderColor: "#90caf9"
},
"&:hover:not($disabled):not($focused):not($error) $notchedOutline": {
borderColor: "#90caf9",
borderWidth: 2
},
"&$focused $notchedOutline": {
borderColor: "#90caf9"
}
},
notchedOutline: {}
},
MuiSelect: {
icon: {
fill: "#90caf9"
}
}
}
});
export default theme;
I also looked in the devtools and found this:
<div class="MuiSelect-root MuiSelect-select MuiSelect-selectMenu MuiInputBase-input MuiInput-input MuiInputBase-inputSelect" aria-pressed="false" tabindex="0" role="button" aria-haspopup="true"><em>Tech</em></div>
I'm not sure how to use that to target what I want.
You can't target other rules or pseudo-classes (e.g. "&:hover:not($disabled):not($focused):not($error) $underline") in inline styles. Instead you need to use CSS classes (e.g. via makeStyles for function components or withStyles can be used with both class and function components).
The styles you need to customize are within Input. Below is an example of how to customize the underline.
You can read more about this in my related answers:
How do I custom style the underline of Material-UI without using theme?
How to change color border bottom blue line to green green line in select field using react js?
import React from "react";
import ReactDOM from "react-dom";
import FormControl from "#material-ui/core/FormControl";
import InputLabel from "#material-ui/core/InputLabel";
import Select from "#material-ui/core/Select";
import MenuItem from "#material-ui/core/MenuItem";
import { makeStyles } from "#material-ui/core/styles";
const useStyles = makeStyles({
select: {
"&:before": {
// normal
borderBottom: "1px solid orange"
},
"&:after": {
// focused
borderBottom: `3px solid green`
},
"&:hover:not(.Mui-disabled):not(.Mui-focused):not(.Mui-error):before": {
// hover
borderBottom: `2px solid purple`
}
}
});
const App = () => {
const [age, setAge] = React.useState("");
const classes = useStyles();
return (
<div className="wrapper">
<FormControl style={{ minWidth: "200px" }}>
<InputLabel htmlFor="age-simple">Age</InputLabel>
<Select
className={classes.select}
value={age}
onChange={event => setAge(event.target.value)}
inputProps={{
name: "age",
id: "age-simple"
}}
>
<MenuItem value="" disabled />
<MenuItem value={10}>Ten</MenuItem>
<MenuItem value={20}>Twenty</MenuItem>
<MenuItem value={30}>Thirty</MenuItem>
</Select>
</FormControl>
</div>
);
};
const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);

How to change the border color of MUI TextField

I can't seem to figure out how to change the outline color of an outlined variant TextField
I looked around GitHub issues and people seem to be pointing towards using the TextField "InputProps" Property but this seems to do nothing.
Here is my code in its current state
import React from 'react';
import { withStyles } from '#material-ui/core/styles';
import TextField from '#material-ui/core/TextField';
import PropTypes from 'prop-types';
const styles = theme => ({
field: {
marginLeft: theme.spacing.unit,
marginRight: theme.spacing.unit,
height: '30px !important'
},
});
class _Field extends React.Component {
render() {
const { classes, fieldProps } = this.props;
return (
<TextField
{...fieldProps}
label={this.props.label || "<Un-labeled>"}
InputLabelProps={{ shrink: true }} // stop from animating.
inputProps={{ className: classes.fieldInput }}
className={classes.field}
margin="dense"
variant="outlined"
/>
);
}
}
_Field.propTypes = {
label: PropTypes.string,
fieldProps: PropTypes.object,
classes: PropTypes.object.isRequired
}
export default withStyles(styles)(_Field);
https://codesandbox.io/s/6rx8p
<CssTextField
label="Username"
className="username"
name="username"
onChange={this.onChange}
type="text"
autoComplete="current-password"
margin="normal"
inputProps={{ style: { fontFamily: 'nunito', color: 'white' } }}
/>
//declare the const and add the material UI style
const CssTextField = withStyles({
root: {
'& label.Mui-focused': {
color: 'white',
},
'& .MuiInput-underline:after': {
borderBottomColor: 'yellow',
},
'& .MuiOutlinedInput-root': {
'& fieldset': {
borderColor: 'white',
},
'&:hover fieldset': {
borderColor: 'white',
},
'&.Mui-focused fieldset': {
borderColor: 'yellow',
},
},
},
})(TextField);
Take a look at this, I made a quick demo:
https://stackblitz.com/edit/material-ui-custom-outline-color
It changes the default border color and the label color of the Material-UI TextField but keeps the primary color when focused.
Also, take a look at this link, it gave me the "idea":
https://github.com/mui-org/material-ui/issues/13347
If you want to change the color when focused look at these examples from the documentation:
https://mui.com/components/text-fields/#customization
In case anyone wants to do this with styled-components:
import styled from "styled-components";
import {TextField} from "#material-ui/core";
const WhiteBorderTextField = styled(TextField)`
& label.Mui-focused {
color: white;
}
& .MuiOutlinedInput-root {
&.Mui-focused fieldset {
border-color: white;
}
}
`;
This took me WAY too long to figure out. Hope it helps someone.
const styles = theme => ({
notchedOutline: {
borderWidth: "1px",
borderColor: "yellow !important"
}
});
<TextField
variant="outlined"
rows="10"
fullWidth
InputProps={{
classes: {
notchedOutline: classes.notchedOutline
}
}}
id="standard-textarea"
label="Input Set"
helperText="Enter an array with elemets seperated by , or enter a JSON object"
placeholder="Placeholder"
multiline
value={"" + this.props.input}
onChange={this.props.handleChangeValue("input")}
className={classes.textField}
margin="normal"
/>
The Problem with the Textfield border is that the color you want to set
has a lower specificity than the original style that Material-UI (MUI) sets.
E.g. MUI sets this class when focused:
.MuiOutlinedInput-root.Mui-focused .MuiOutlinedInput-notchedOutline {
border-color: (some color);
}
which is more specific than a custom selector like:
.Component-cssNotchedOutline {
border-color: #f0f;
}
Solution A (not recommended)
You can add the !important exception to the color, but this is 'bad practice':
import React from 'react';
import { createStyles, TextField, WithStyles, withStyles } from '#material-ui/core';
interface IProps extends WithStyles<typeof styles> {}
const styles = createStyles({
notchedOutline: { borderColor: '#f0f !important' },
});
export const TryMuiA = withStyles(styles)((props: IProps) => {
const { classes } = props;
return ( <TextField variant={ 'outlined' } label={ 'my label' }
InputProps={ {
classes: {
notchedOutline: classes.notchedOutline,
},
} }
/> );
});
Solution B (recommended)
The official MUI example uses other ways to increase specificity.
The 'trick' is not to style the Element directly, like:
.someChildElement { border-color: #f0f }
but to add some extra selectors (more than MUI does*), e.g.:
.myRootElement.someExtra { border-color: #f0f }
or:
.myRootElement .someChildElement { border-color: #f0f }
*(Actually it might be enough to use the same selectors as MUI does,
because if specificity of the selectors is the same,
then the 'later' ones are used. But in case of SSR, the order of the CSS rules might change after rehydration.)
Include the parent: You might have noticed that setting notchedOutline does set the color for the un-focused element, but not for the focused.
That is because the MUI style includes the parent element of the input box (.MuiOutlinedInput-root.Mui-focused).
So you need to include the parent as well.
import React from 'react';
import { withStyles } from '#material-ui/core/styles';
import TextField from '#material-ui/core/TextField';
const styles = {
root: { // - The TextField-root
border: 'solid 3px #0ff', // - For demonstration: set the TextField-root border
padding: '3px', // - Make the border more distinguishable
// (Note: space or no space after `&` matters. See SASS "parent selector".)
'& .MuiOutlinedInput-root': { // - The Input-root, inside the TextField-root
'& fieldset': { // - The <fieldset> inside the Input-root
borderColor: 'pink', // - Set the Input border
},
'&:hover fieldset': {
borderColor: 'yellow', // - Set the Input border when parent has :hover
},
'&.Mui-focused fieldset': { // - Set the Input border when parent is focused
borderColor: 'green',
},
},
},
};
export const TryMui = withStyles(styles)(function(props) {
const { classes } = props;
return (<TextField label="my label" variant="outlined"
classes={ classes }
/>);
})
Note that you can increase specificity in different ways, e.g. this would work as well (a bit different):
'& fieldset.MuiOutlinedInput-notchedOutline': {
borderColor: 'green',
},
Remark: It might seem a little bit 'dirty' to add selectors only to increase specificity,
when you don't really 'need' them. I think it is, but this workaround was sometimes
the only solution since CSS was invented, so it is considered kind of acceptable.
For the latest MUI v5.2.2:
There are two main ways of changing TextField color properties:
1st one is by using InputProps and InputLabelProps:
First you can create a some.module.css file, where you can create your classes:
.input-border {
border-color: #3E68A8 !important;
}
.inputLabel {
color: #3E68A8 !important;
}
.helper-text {
text-transform: initial;
font-size: 1rem !important;
}
after that you can apply them like:
<TextField
sx={{
textTransform: 'uppercase',
}}
FormHelperTextProps={{
classes: {
root: classes['helper-text'],
},
}}
InputProps={{
classes: {
notchedOutline: classes['input-border'],
},
}}
InputLabelProps={{
classes: {
root: classes.inputLabel,
focused: classes.inputLabel,
},
}}
/>
Note the above shows also how to change the color of the FormHelperText!
But if you have multiple input fields, the best way is to override the components that you need by using createTheme from #mui/material/styles
The below example shows some of the components, the rest you can just check in the dev tools, and later on inside the theme file just Ctrl + Space will show you all available components.
Example:
import { createTheme, responsiveFontSizes } from '#mui/material/styles';
const theme = createTheme({
components: {
// CTRL + SPACE to find the component you would like to override.
// For most of them you will need to adjust just the root...
MuiTextField: {
styleOverrides: {
root: {
'& label': {
color: '#3E68A8',
},
'& label.Mui-focused': {
color: '#3E68A8',
},
'& .MuiInput-underline:after': {
borderBottomColor: '#3E68A8',
},
'& .MuiOutlinedInput-root': {
'& fieldset': {
borderColor: '#3E68A8',
},
'&:hover fieldset': {
borderColor: '#3E68A8',
borderWidth: '0.15rem',
},
'&.Mui-focused fieldset': {
borderColor: '#3E68A8',
},
},
},
},
},
MuiFormHelperText: {
styleOverrides: {
root: {
textTransform: 'initial',
fontSize: '1rem',
},
},
},
},
});
export default responsiveFontSizes(theme);
inputProps={{ style: { fontFamily: 'nunito', color: 'white'}}}
The Inputprops works by styling the enterd input data in the textfield and also we can use className for custom coloring..
const CssTextField = withStyles({
root: {
'& label.Mui-focused': {
color: 'white',
},
'& .MuiInput-underline:after': {
borderBottomColor: 'yellow',
},
'& .MuiOutlinedInput-root': {
'& fieldset': {
borderColor: 'white',
},
'&:hover fieldset': {
borderColor: 'white',
},
'&.Mui-focused fieldset': {
borderColor: 'yellow',
},
},
},
This const style works the outer potion of the text filed...
The styling of the outer portion of material UI is above asked for change...
use this overrides CSS property
.MuiFormLabel-root.Mui-focused {
color: red !important;
}
.MuiOutlinedInput-root.Mui-focused .MuiOutlinedInput-notchedOutline {
border-color: red !important;
}
Extending Peter's answer. You could also change all event colors without the !important:
cssOutlinedInput: {
"&:not(hover):not($disabled):not($cssFocused):not($error) $notchedOutline": {
borderColor: "red" //default
},
"&:hover:not($disabled):not($cssFocused):not($error) $notchedOutline": {
borderColor: "blue" //hovered
},
"&$cssFocused $notchedOutline": {
borderColor: "purple" //focused
}
},
notchedOutline: {},
cssFocused: {},
error: {},
disabled: {}
https://stackblitz.com/edit/material-ui-custom-outline-color-c6zqxp
This is how I solved mine.
I wanted to change the color of the TextField when on foucused. As you already know, material Ui textField default color when on focused is blue. Blue the primary color.
So here was the hack, I went to the outer component App, and then defined a function called createMuiTheme. This fuctions returns an object called pallete. Inside the pallete is where you provide your color overides. You will use ThemeProvider from materia ui to apply your new defined color theme to your app just as below. For more clarification, follow this link https://material-ui.com/customization/palette/
import {createMuiTheme, ThemeProvider} from '#material-ui/core';
import FormInput from './FormInput';
const theme = createMuiTheme({
palette: {
primary: {
main: "your own color", //this overide blue color
light: "your own color", //overides light blue
dark: "your own color", //overides dark blue color
},
},
});
//apply your new color theme to your app component
function App(){
return(
<ThemeProvider theme={theme}> //applies custom theme
<FormInput/>
</ThemeProvider>
)
}
The overrides key enables you to customize the appearance of all instances of a component type,... Material-Ui
In this case there is a short answer, you have to use ThemeProvider and createMuiTheme
import React from 'react';
import {
createMuiTheme,
ThemeProvider
} from '#material-ui/core/styles';
import TextField from '#material-ui/core/TextField';
const theme = createMuiTheme({
palette: {
primary: {
main: '#ff5722' //your color
}
}
});
function CustomTextfield(props) {
return (
<ThemeProvider theme={theme}>
<TextField variant='outlined'/>
</ThemeProvider>
);
}
For a more complete customization you can use the default theme names pallete.
If you dont know where are the names or naming conventions.
Using de browser inspector in the style section is your savior, you can notice how the css chain is made in material-ui.
.MuiFilledInput-root {
position: relative;
transition: background-color 200ms cubic-bezier(0.0, 0, 0.2, 1) 0ms;
background-color: rgba(255,255,255,0.8);
border-top-left-radius: 4px;
border-top-right-radius: 4px;
}
MuiFilledInput > root > background-color:
we have to create de theme using the data from the inspector, we only have to place the chain in overrides:{}
const theme = createMuiTheme({
overrides: {
MuiFilledInput: {
root: {
backgroundColor: 'rgba(255,255,255,0.8)',
'&:hover': {
backgroundColor: 'rgba(255,255,255,1)'
},
'&.Mui-focused': {
backgroundColor: 'rgba(255,255,255,1)'
}
}
}
}
});
Now you can make the override using ThemeProvider
import {
createMuiTheme,
ThemeProvider
} from '#material-ui/core/styles';
const theme = createMuiTheme({
overrides: {
MuiFilledInput: {
root: {
backgroundColor: 'rgba(255,255,255,0.8)',
'&:hover': {
backgroundColor: 'rgba(255,255,255,1)'
},
'&.Mui-focused': {
backgroundColor: 'rgba(255,255,255,1)'
}
}
}
}
});
function CustomTextfield(props) {
return (
<ThemeProvider theme={theme}>
<TextField variant='filled' />
</ThemeProvider>
);
}
So for this question you have to search your own components, because have different names.
you can override this style like below
/* for change border color*/
.MuiOutlinedInput-root.Mui-focused .MuiOutlinedInput-notchedOutline{
border-color: #5EA841 !important;
}
/*for change label color in focus state*/
.MuiFormLabel-root.Mui-focused{
color: #212121 !important;
}
Here's how I did it for hover and focused states of the TextField component.
MuiTextField: {
styleOverrides: {
root: {
"& .MuiOutlinedInput-root:hover .MuiOutlinedInput-notchedOutline": {
borderColor: "#ffb535",
},
"& .MuiOutlinedInput-root.Mui-focused .MuiOutlinedInput-notchedOutline":
{
borderColor: "#ffb535",
},
},
},
},
you can refer this code:
styles.js
cssLabel: {
color : 'rgb(61, 158, 116) !important'
},
notchedOutline: {
borderWidth: '1px',
borderColor: 'rgb(61, 158, 116) !important',
color: 'rgb(61, 158, 116)',
},
form.js
<TextField
name="creator"
focused="true"
variant="outlined"
label="Creator"
fullwidth
InputLabelProps={{
classes: {
root: classes.cssLabel,
focused: classes.cssLabel,
},
}}
InputProps={{
classes: {
root: classes.notchedOutline,
focused: classes.notchedOutline,
notchedOutline: classes.notchedOutline,
},
}}
/>
basically, you need to set border color of notchedOutline of the InputProps appropriately.
Below is the code to customize its border color using styled() in MUI v5. The resulted TextField has an extra borderColor prop that lets you pass any color you want, not just the ones from MUI palette.
import { styled } from '#mui/material/styles';
import MuiTextField from '#mui/material/TextField';
const options = {
shouldForwardProp: (prop) => prop !== 'borderColor',
};
const outlinedSelectors = [
'& .MuiOutlinedInput-notchedOutline',
'&:hover .MuiOutlinedInput-notchedOutline',
'& .MuiOutlinedInput-root.Mui-focused .MuiOutlinedInput-notchedOutline',
];
const TextField = styled(
MuiTextField,
options,
)(({ borderColor }) => ({
'& label.Mui-focused': {
color: borderColor,
},
[outlinedSelectors.join(',')]: {
borderWidth: 3,
borderColor,
},
}));
Usage
<TextField label="green" borderColor="green" />
<TextField label="red" borderColor="red" />
<TextField label="blue" borderColor="blue" />
In MUI V5 :
const theme = createTheme({
components: {
MuiInputBase: {
styleOverrides: {
root: {
"&:before":{
borderBottom:"1px solid yellow !imporatnt",}
},
},
},
},
})
In MUI V5, the best way to handle the styles is through the SX props, as shown in the following example:
import * as React from 'react';
import TextField from '#mui/material/TextField';
// 1- Default styles
const rootStyles = {
backgroundColor: '#ffd60a',
border: '3px solid #001d3d',
};
const inputLabelStyles = {
color: '#003566',
textTransform: 'capitalize',
};
const rootInputStyles = {
'&:hover fieldset': {
border: '2px solid blue!important',
borderRadius: 0,
},
'&:focus-within fieldset, &:focus-visible fieldset': {
border: '4px solid red!important',
},
};
const inputStyles = {
color: 'red',
paddingLeft: '15px',
fontSize: '20px',
};
const helperTextStyles = {
color: 'red',
};
export default function InputField({
label = 'default label',
// 2- User custom styles
customRootStyles,
customInputLabelStyles,
customRootInputStyles,
customInputStyles,
customHelperTextStyles,
}) {
return (
<TextField
label={label}
helperText="Please enter a valid input"
sx={{ ...rootStyles, ...customRootStyles }}
InputLabelProps={{
sx: {
...inputLabelStyles,
...customInputLabelStyles,
},
}}
InputProps={{
sx: {
...rootInputStyles,
...customRootInputStyles,
},
}}
inputProps={{
sx: {
...inputStyles,
...customInputStyles,
},
}}
FormHelperTextProps={{
sx: {
...helperTextStyles,
...customHelperTextStyles,
},
}}
/>
);
}
To understand more about how this works, you can checkout the original article through this link.
Here this example on a select input:
import {
FormControl,
InputLabel,
Select,
MenuItem,
OutlinedInput as MuiOutlinedInput,
} from "#material-ui/core";
const OutlinedInput = withStyles((theme) => ({
notchedOutline: {
borderColor: "white !important",
},
}))(MuiOutlinedInput);
const useStyles = makeStyles((theme) => ({
select: {
color: "white",
},
icon: { color: "white" },
label: { color: "white" },
}));
function Component() {
return (
<FormControl variant="outlined">
<InputLabel id="labelId" className={classes.label}>
Label
</InputLabel>
<Select
labelId="labelId"
classes={{
select: classes.select,
icon: classes.icon,
}}
input={<OutlinedInput label="Label" />}
>
<MenuItem>A</MenuItem>
<MenuItem>B</MenuItem>
</Select>
</FormControl>
);
}
For me, I had to use pure css with this:
.mdc-text-field--focused .mdc-floating-label {
color: #cfd8dc !important;
}
.mdc-text-field--focused .mdc-notched-outline__leading,
.mdc-text-field--focused .mdc-notched-outline__notch,
.mdc-text-field--focused .mdc-notched-outline__trailing {
border-color: #cfd8dc !important;
}
// optional caret color
.mdc-text-field--focused .mdc-text-field__input {
caret-color: #cfd8dc !important;
}
J
You can override all the class names injected by Material-UI thanks to the classes property.
Have a look at overriding with classes section and the implementation of the component for more detail.
and finally :
The API documentation of the Input React component. Learn more about the properties and the CSS customization points.

How to eliminate hover, active, focus gray color in Material UI Chip component

I have Chips implemented in several colors (green, yellow, blue etc.) and by default MUI Chip comes with grey hover/active/focus CSS style. I need to eliminate this hover/active/focus grey background color in MUI Chip component. So once again I don't want to replace gray color with another color but to completely eliminate following CSS styles:
clickable: {
// Remove grey highlight
WebkitTapHighlightColor: theme.palette.common.transparent,
cursor: 'pointer',
'&:hover, &:focus': {
backgroundColor: emphasize(backgroundColor, 0.08),
},
'&:active': {
boxShadow: theme.shadows[1],
backgroundColor: emphasize(backgroundColor, 0.12),
},
},
deletable: {
'&:focus': {
backgroundColor: emphasize(backgroundColor, 0.08),
},
},
In the end this can be done by overriding Chip component in all the colors needed, but there has to be a better way.
You can create a factory function that returns a component with the color of your choice and overrides the behavior highlighted in your question:
import React from 'react';
import { withStyles } from 'material-ui/styles';
import Chip from 'material-ui/Chip';
import { emphasize, fade } from 'material-ui/styles/colorManipulator';
const ChipFactory = (color = null, deleteIconColor = null) => {
const styles = theme => {
const backgroundColor = emphasize(color || theme.palette.background.default, 0.12);
const deleteIconColor = fade(deleteIconColor || theme.palette.text.primary, 0.26);
return {
root: {
color: theme.palette.getContrastText(backgroundColor),
backgroundColor,
},
clickable: {
cursor: 'pointer',
'&:hover, &:focus': {
backgroundColor: emphasize(backgroundColor, 0.08),
},
'&:active': {
backgroundColor: emphasize(backgroundColor, 0.12),
},
},
deletable: {
'&:focus': {
backgroundColor: emphasize(backgroundColor, 0.08),
},
},
deleteIcon: {
color: deleteIconColor,
'&:hover': {
color: fade(deleteIconColor, 0.4),
},
},
};
};
const CustomChip = ({ classes, ...props }) =>
<Chip classes={classes} {...props} />;
return withStyles(styles)(CustomChip);
};
export default ChipFactory;
Rather than creating individual components for each color, you can generate a new variety on the fly by invoking this function:
// excerpt from Chips demo
render() {
const { classes } = props;
const GreenChip = ChipFactory('#0f0');
const RedChip = ChipFactory('#f00');
const BlueChip = ChipFactory('#00f');
return (
<div className={classes.row}>
<GreenChip label="Basic Chip" className={classes.chip} />
<RedChip
avatar={<Avatar>MB</Avatar>}
label="Clickable Chip"
onClick={handleClick}
className={classes.chip}
/>
<BlueChip
avatar={<Avatar src="/static/images/uxceo-128.jpg" />}
label="Deletable Chip"
onRequestDelete={handleRequestDelete}
className={classes.chip}
/>
</div>
);
}
See this code sandbox for a working version.

Resources