How to use 'classes' to customize compound components in Mui? - reactjs

I am trying to override the Mui styles by using the classes prop.
For example, I would like to override the InputLabel color of the TextField component.
I would like to use one definition of makeStyles that will set all css rules, starting at the root (TextField) and overriding whatever I want in the hierarchy (for example, the InputLabel when focused), when passing it to the component in the classes prop.
How is it done?
import * as React from "react";
import TextField from "#mui/material/TextField";
import makeStyles from "#mui/styles/makeStyles";
const useStyles = makeStyles({
root: {
color: "yellow",
label: {
color: "brown"
}
}
});
export default function Input() {
const classes = useStyles();
return (
<TextField
classes={classes}
id="outlined-basic"
label="Outlined"
variant="outlined"
/>
);
}
Answer
import * as React from "react";
import TextField from "#mui/material/TextField";
import makeStyles from "#mui/styles/makeStyles";
const useStyles = makeStyles({
root: {
"& .MuiInputBase-input": {
color: 'red',
padding: "0.2rem"
},
},
});
export default function Input() {
const classes = useStyles();
return (
<TextField
InputProps={{ classes }}
/>;
);
}
codesandbox

The classes prop in MUI gives you access to the CSS Rule Names for a component. When you're using this prop, check the API spec for that component. The CSS Rule Names are at the bottom of the page.
https://mui.com/api/text-field/#css
For this component, there is only 1 rule available (root), so this will (I think) have the same effect as just using className.
What you probably want to do is use the InputProps prop instead. The Input component has way more CSS Rules you can target: https://mui.com/api/input/#css
So, I think you probably want to do this:
<TextField
InputProps={{ classes }}
id="outlined-basic"
label="Outlined"
variant="outlined"
/>
EDIT to help answer comment:
I don't think you need to target InputBase, as I believe you can target input instead. To target the input CSS Rule, just change the root key to input:
import * as React from "react";
import TextField from "#mui/material/TextField";
import makeStyles from "#mui/styles/makeStyles";
const useStyles = makeStyles({
input: {
color: 'red',
padding: "0.2rem"
},
});
export default function Input() {
const classes = useStyles();
return (
<TextField
InputProps={{ classes }}
/>;
);
}
The CSS rules in the docs are sensitive to the keys in the object you pass.

The best way I found is to use the Mui v5 sx property.
(makeStyles is deprecated - https://mui.com/guides/migration-v4/#2-use-tss-react)
(input signifies the rule in https://mui.com/api/input-base/#css)
import * as React from "react";
import TextField from "#mui/material/TextField";
export default function Input() {
const classes = useStyles();
return (
<TextField
sx={{
"& input":
{ padding: "0rem",color: "blue" }
}}
/>
);
}

Related

DatePicker MUI how to display "Clear" text on the left side of the calendar

I have DesktopDatePicker from material-ui(version 5.0.0) and like to display "Clear" text on the left side of the calendar.
import * as React from "react";
import dayjs from "dayjs";
import TextField from "#mui/material/TextField";
import { AdapterDayjs } from "#mui/x-date-pickers/AdapterDayjs";
import { LocalizationProvider } from "#mui/x-date-pickers/LocalizationProvider";
import { DesktopDatePicker } from "#mui/x-date-pickers/DesktopDatePicker";
export default function ResponsiveDatePickers() {
const [value, setValue] = React.useState(dayjs("2022-04-07"));
return (
<LocalizationProvider dateAdapter={AdapterDayjs}>
<DesktopDatePicker
label="For desktop"
value={value}
minDate={dayjs("2017-01-01")}
onChange={(newValue) => {
setValue(newValue);
}}
componentsProps={{
actionBar: { actions: ["clear"], position: "left" }
}}
renderInput={(params) => <TextField {...params} />}
/>
</LocalizationProvider>
);
}
I added position:"left" in actionBar but this didn't work.
Since it is justified by a flexbox, you will need to add justifyContent: "flex-start" to your action bar style properties.
eg:
componentsProps={{
actionBar: { actions: ["clear"], style: {justifyContent: "flex-start"} }
}}
To further answer the question in the comment, since MUI components all give you access to styling I tried it and it worked - this is the MUIv4 way to access styling and it appears that it still works. The MUIv5 way to do it would likely be to access styling through the sx property that the components now have.
componentsProps={{
actionBar: { actions: ["clear"], sx: {justifyContent: "flex-start"} }
}}
All MUI components give access to styling with the sx property.

How to use sx prop in styled components without mui

Instead of using multiple props for each css attribute, I want to make an sx prop like material-ui has. I'm trying to implement this with styled-components. The idea is that I can pass an object as a prop, and reference a value from the object in the styled component.
things to note:
material-ui is not added as a dependancy. I want to "clone" sx from it.
currently looking into prop-types to add some value in finding bug.
Button Component
import styled from "styled-components";
export const Button = styled.button`
background-color: ${(sx) => sx.backgroundColor};
color: ${(sx) => sx.color};
`;
Rendering Button
import React from "react";
import styled from "styled-components";
import { Button } from "./Button/Button";
function App() {
return (
<>
<Button sx={{ backgroundColor: "red", color: "white" }} />
<>
);
}
export default App;
Update:
After adding prop-types to maybe find the issue, I get an error when I pass the prop to the Button component when I added this code:
// typechecking prop types passed
Button.propTypes = {
sx: PropTypes.string,
};
And the error I got back:
Warning: Failed prop type: Invalid prop `sx` of type `object` supplied to `styled.button`, expected `string`
Im not sure exactly where its going wrong. I've tried doing a console.log to see the value passed, which seems to be a string. Therefore dot notation should work?
Any help would be appreciated, thanks very much :)
After adding prop-types and finding the passed types, I was able to find this answer:
// required prop to be passed as an object
Button.propTypes = {
sx: PropTypes.object,
};
// updating the props for Button component
export const Button = styled.button`
background-color: ${(props) => props.sx.backgroundColor};
color: ${(props) => props.sx.color};
`;
then using sx as normal...
import React from "react";
import styled from "styled-components";
import { Button } from "./Button/Button";
function App() {
return (
<>
<Button sx={{ backgroundColor: "red", color: "white" }} />
</>
);
}
export default App;

MUI5 :Cannot read properties of undefined (reading 'primary')

I am using MUI5 with reactjs and I wanted to use the makeStyles to add some custom CSS to the MUI components but its not allowing me to use the default theme inside the makestyles so my code is :
import { Grid, Card, CardContent,Typography, CardActions,Button, AppBar, Toolbar,
Box,IconButton, Menu, MenuItem, InputBase, alpha, styled, Badge, Container, CardHeader,
CardMedia } from '#mui/material';
import EmailIcon from '#mui/icons-material/Email';
import NotificationsIcon from '#mui/icons-material/Notifications';
import React from 'react'
import { makeStyles } from '#mui/styles'
const useStyles = makeStyles((theme) => ({
root: ({
backgroundColor: theme.palette.primary.light,
color: theme.color,
}),
}));
const App = () => {
const classes = useStyles();
return(
<Fragment>
<Container className={classes.root}>
<Typography>
this is a very random text to fill
</Typography>
</Container>
</Fragment>
)
}
export default App;
its not allowing me to get to the theme props inside the makestyles
First of all, try assigning "root" as a normal object property like this-
const useStyles = makeStyles((theme) => ({
root: {
backgroundColor: theme.palette.primary.light,
color: theme.color,
}
}));
If it does not work, you may want to take a look at this-
https://mui.com/styles/basics/#using-the-theme-context

Style a component's [aria-checked="true"] using Material UI's makeStyle

I have a check box (not a Material-UI checkbox) that I'd like to style using it's aria-checked="true" attribute via makeStyles. I see in the Material-UI docs that you can style pseudo selectors as such:
'&:hover': { /* … */ },
But I haven't been able to make this work for the aria attribute? Is this possible? If so, how?
The syntax for attribute selectors is largely the same as in CSS. & is used to refer to the generated class (classes.myCheckboxStyles in my example below) and then further selectors can be added within the quotes (e.g. "&[aria-checked=true]").
Below is a working example demonstrating the syntax:
import React from "react";
import { makeStyles } from "#material-ui/core/styles";
const useStyles = makeStyles({
myCheckboxStyles: {
border: "1px black solid",
color: "white",
"&[aria-checked=true]": {
backgroundColor: "blue"
}
}
});
export default function Checkboxes() {
const classes = useStyles();
const [checked, setChecked] = React.useState(false);
return (
<div>
<span
onClick={() => setChecked(!checked)}
aria-checked={checked}
className={classes.myCheckboxStyles}
>
X
</span>
</div>
);
}
I've tried to use aria-checked="true" to activate MUI checkbox, but it doesn't work. So, in my view, you should try using onMouseEnter to activate MUI checkbox. You can try this:
import React from "react";
import Checkbox from "#material-ui/core/Checkbox";
export default function Checkboxes() {
const [checked, setChecked] = React.useState(false);
const handleChange = event => {
setChecked(event.target.checked);
};
return (
<div>
<Checkbox
checked={checked}
onMouseEnter={() => setChecked(true)}
onChange={handleChange}
inputProps={{ "aria-label": "primary checkbox" }}
/>
</div>
);
}

ReactJS material-ui use the class `Mui-disabled` for read-only components

I'm building a new component from TextField and I need to apply the same style for text fields with the readOnly than disabled property.
So, I was trying to use the property className but it does not work.
// some logic here ..
<TextField
{...props}
className={readOnly ? 'Mui-disabled' : undefined}
/>
So, I also tried to use the classses prop, but I don't know how to get the current config from the disabled class.
When you use the disabled property, Material-UI places the Mui-disabled class on many different elements. To get the equivalent look, you need to add it to all the same elements.
Below is an example of how to do this. In addition to adding the Mui-disabled class, it is also necessary to override the "focused" styling of the underline (handled via the :after pseudo-class).
import React from "react";
import ReactDOM from "react-dom";
import TextField from "#material-ui/core/TextField";
import { makeStyles } from "#material-ui/core/styles";
const disabledClassNameProps = { className: "Mui-disabled" };
const useStyles = makeStyles(theme => {
const light = theme.palette.type === "light";
const bottomLineColor = light
? "rgba(0, 0, 0, 0.42)"
: "rgba(255, 255, 255, 0.7)";
return {
underline: {
"&.Mui-disabled:after": {
borderBottom: `1px dotted ${bottomLineColor}`,
transform: "scaleX(0)"
}
}
};
});
function App() {
const classes = useStyles();
return (
<div className="App">
<TextField
{...disabledClassNameProps}
inputProps={{ readOnly: true }}
InputProps={{ ...disabledClassNameProps, classes }}
InputLabelProps={disabledClassNameProps}
FormHelperTextProps={disabledClassNameProps}
label="Test Disabled Look"
defaultValue="Some Text"
helperText="Helper Text"
/>
</div>
);
}
const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);
Related answers:
Altering multiple component roots for MUI Textfield
How can I remove the underline of TextField from Material-UI?
How do I custom style the underline of Material-UI without using theme?
After some digging, I found that the InputProps also have the className property. The following worked for me:
<TextField
{...props}
inputProps={{
readOnly,
}}
InputProps={{
className: (readOnly) ? 'Mui-disabled' : undefined,
}}
/>
To see all the properties you can look here.
You need to use classes on TextField
<TextField
{...props}
classes={readOnly ? { root: 'Mui-disabled' } : {}}
/>
Hope it helps

Resources