Style Material UI textfield - reactjs

I'm trying to style a material-ui textfield but I don't get it to work the way I want. I just want a plain simple white input field with standard MUI animations. I want the textfield to always have a white background and text to be black.
You find the code on Code Sandbox: https://codesandbox.io/s/material-demo-2coo8?fontsize=14&hidenavigation=1&theme=dark
Thanks in advance!

You can custom style the TextField font and background color with the following code:
const useStyles = makeStyles((theme) => ({
root: {
"& .MuiInputBase-root": {
color: 'black' //or try theme.palette.primary.main
backgroundColor: 'white' //It should be white by default
}
}
}));
Then simply add the 'root' class to your TextField. As info, the above syntax is called JSS. .MuiInputBase-root is a class applied to the input component, which is a subcomponent of the TextField. This article explores the TextField component with dev tools open, so you can understand how the subcomponents work and get styled by MUI.
One more piece of info about the JSS syntax. Notice the 'space' between the '&' and the '.'. This space is important and acts as part of the selector, informing that .MuiInputBase-root class is on a child component of the parent that receive 'root' class styling.

I would highly suggest you to use functional components since it is the future of React.
Below you can see your example as functional component with regular Material-UI styles.
import React from "react";
import Grid from "#material-ui/core/Grid";
import TextField from "#material-ui/core/TextField";
import { makeStyles } from "#material-ui/core/styles";
const useStyles = makeStyles(theme => ({
root: { backgroundColor: "white" },
box: { backgroundColor: "white" },
input: {
root: { backgroundColor: "white", color: "black" }
}
}));
export default function FunctionalDemo() {
const classes = useStyles();
return (
<Grid
container
direction="row"
justify="center"
alignItems="center"
className={classes.root}
>
<Grid item xs={12} md={6} className={classes.box}>
<form noValidate>
<TextField
id="email"
label="Type here"
variant="filled"
color="secondary"
className={classes.input.root}
/>
</form>
</Grid>
</Grid>
);
}
Code sandbox: https://codesandbox.io/s/material-ui-plain-text-field-x2s48?fontsize=14&hidenavigation=1&theme=dark

Related

Material Form Field and TextFieldRoot overwrite theme with useStyles / jss

How do I override Material themes for FormControl? It is usually html parent above a Textfield. I want the margin bottom to be 8px, instead of 4px. Below is not working. Currently using MUI version 4
export const useProcedureTableStyles = makeStyles({
overrides: {
'& .MuiTextField-root': {
marginBottom: '8px',
},
},
textField: {
height: '31px',
},
<TextField
{...params}
margin="dense"
value={listItem}
error={listItem.duplicateFlag}
InputProps={{
...params.InputProps,
style: { padding: 0 },
className: procedureStyles.overrides,
classes: {
input: procedureStyles.textField,
},
}}
/>
Researching this resource: material-ui overwrite theme with useStyles / jss
Below is a simplified version of the html structure shown in your screenshot:
<div class="MuiFormControl-root MuiTextField-root">
<div class="MuiOutlinedInput-root">
<input type="text" class="MuiOutlinedInput-input"/>
</div>
</div>
You are passing procedureStyles.textField via the input key of the classes prop in InputProps. That targets the innermost input element (and I assume that is working as intended). That input element can also be targeted using the className property of inputProps (lowercase i).
You are passing procedureStyles.overrides via the className property of InputProps. InputProps targets the second div in the structure above (the one with class="MuiOutlinedInput-root"), and then your margin bottom styles are being applied to any descendants of the div that have a class of MuiTextField-root. Since the div you want to target is an ancestor of that second div and not a descendant, your styles have no effect.
To target the first div in that structure, you can use the className prop directly on TextField. It would also be equivalent to use the root key of the classes prop directly on TextField.
Here's a working example:
import React from "react";
import { makeStyles } from "#material-ui/core/styles";
import TextField from "#material-ui/core/TextField";
const useStyles = makeStyles((theme) => ({
overrides: {
marginBottom: "8px"
}
}));
export default function BasicTextFields() {
const classes = useStyles();
return (
<>
<div>Something before to demonstrate top margin</div>
<TextField
id="outlined-basic"
margin="dense"
label="Outlined"
variant="outlined"
className={classes.overrides}
/>
<div>Something after to demonstrate bottom margin</div>
</>
);
}
Do this in your Material-UI theme:
overrides: {
MuiFormControl:{
marginDense:{
marginBottom:'8px'
}
}
}

MUI: cannot apply background color to Paper component

I'm trying to style the MUI <Paper> component, however setting the background color isn't working. Following the online tutorials I'm applying the background-color CSS property to the root element of the Paper but the color remains white while other CSS properties - in this case padding and text-align work. Can someone please tell me what I am missing?
import React from 'react';
import { Paper, Typography } from '#mui/material';
import { makeStyles } from '#mui/styles';
import AccessAlarmIcon from '#mui/icons-material/AccessAlarm';
const useStyles = makeStyles({
root: {
textAlign: 'center',
padding: 15,
backgroundColor: '#37474f',
}
});
export default function Header() {
const classes = useStyles();
return(
<Paper outlined square className={classes.root}
>
<Typography variant="h2" component="h1">
Pomodoro Cl
<AccessAlarmIcon sx={{ fontSize: 45, color: 'red' }} />
ck
</Typography>
</Paper>
)
}
First of all your attribute outlined is incorrect, it should bevariant="outlined" as per the documentation.
For the background-color not working, you will need to add !important to the property so it takes precedence over mui's default styling.
Here's a working codesandbox for you: https://codesandbox.io/s/strange-smoke-y6yhv?file=/src/App.tsx

How do I set a width for the TextAreaAutoSize component in Material-UI?

I can't find any info anywhere on how to change the default width of a TextAreaAutosize component in material-ui.
It seems the only choice is to have this little box. Does anyone know of a better text area auto size component I can use, or how to change the width of the TextAreaAutoSize component?
The API doesn't show any properties that have anything to do with 'className'. I tried to use it anyway and it was ignored. I also tried wrapping the component in a Box, and styling that, but it was ignored by the TextArea.
Any help would be greatly appreciated!
Resizing by the user is turned off (via resize: "none") for TextField here in InputBase: https://github.com/mui-org/material-ui/blob/v4.10.2/packages/material-ui/src/InputBase/InputBase.js#L140.
Below is an example of how to turn it back on:
import React from "react";
import { makeStyles } from "#material-ui/core/styles";
import TextField from "#material-ui/core/TextField";
const useStyles = makeStyles(theme => ({
root: {
"& .MuiTextField-root": {
margin: theme.spacing(1)
}
},
textarea: {
resize: "both"
}
}));
export default function MultilineTextFields() {
const classes = useStyles();
return (
<form className={classes.root} noValidate autoComplete="off">
<div>
<TextField
id="outlined-textarea"
label="Multiline Placeholder"
placeholder="Placeholder"
multiline
variant="outlined"
inputProps={{ className: classes.textarea }}
/>
</div>
</form>
);
}
CSS documentation for resize: https://developer.mozilla.org/en-US/docs/Web/CSS/resize
Multiline TextField demos: https://material-ui.com/components/text-fields/#multiline
You can change the style prop of the TextareaAutosize check here
<TextareaAutosize
rowsMin={3}
placeholder=''
defaultValue=''
style={{ width: "100%" }}
/>
I was able to get it to work thanks to Ryan Cogswell. Stupid me, though I wrapped the textarea in a box and applied className to the box (which didn't work), I should have applied it to the textareaautosize directly.
There's a bug in VSCODE Intellisense where it shows 'classes' as a property but not 'className' so I assumed it didn't exist.
Here's the code:
const FormStyles = makeStyles((theme) => ({
root: {
width: '100%',
},
button: {
marginTop: '20px',
marginRight: theme.spacing(1),
},
buttons: {
display: 'flex',
justifyContent: 'flex-end'
},
textarea: {
width: '100%',
},
}));
<TextareaAutosize
rowsMin={3}
aria-label={info.label}
name={info.name}
placeholder=''
defaultValue=''
className={classes.textarea}
/>
I could not get the drag icon to show up in textfield, so didn't use it. But I would appreciate an example of textfield using multiline and resizing.
Thanks Ryan!
Here's the trick I used. I wrapped it in a flex container and used align-items to stretch the width to cover the size of that container.
<Stack
direction="column"
justifyContent="center"
alignItems="stretch"
spacing={2}
>
<TextareaAutosize
label='Title'
value={pub.title || ''}
onChange={(e) => pub.title = e.target.value}
variant='outlined'
sx={{m: 1}}
size='small'
/>
</Stack>

Material UI | How to change the font colour of a disabled input text field?

The colour of a disabled input text field created using material UI is light grey by default and it is not very visible against a white background. Is there any way to change the font colour of a disabled input text field?
Below is an example of how to do this showing the customized version next to the default styling.
import React from "react";
import { withStyles } from "#material-ui/core/styles";
import TextField from "#material-ui/core/TextField";
import Button from "#material-ui/core/Button";
const DarkerDisabledTextField = withStyles({
root: {
marginRight: 8,
"& .MuiInputBase-root.Mui-disabled": {
color: "rgba(0, 0, 0, 0.6)" // (default alpha is 0.38)
}
}
})(TextField);
export default function Demo() {
const [disabled, setDisabled] = React.useState(true);
return (
<>
<Button onClick={() => setDisabled(!disabled)}>Toggle Disabled</Button>
<br />
<br />
<DarkerDisabledTextField
disabled={disabled}
id="outlined-basic"
label="Custom"
value={`Disabled = ${disabled}`}
variant="outlined"
/>
<TextField
disabled={disabled}
id="outlined-basic"
label="Default"
value={`Disabled = ${disabled}`}
variant="outlined"
/>
</>
);
}
I think the simplest way is to create an object to define the font color and pass it to the TextField's inputProps.
const fontColor = {
style: { color: 'rgb(50, 50, 50)' }
}
This way you can toggle the font with the components state as you wish or simply keep it constant.
<TextField
label="Title"
onChange={updateTitle}
value={title}
disabled={true}
inputProps={fontColor}/>
import { TextField, styled } from '#mui/material'
const CustomTextField = styled(TextField)({
'& .MuiInputBase-root.Mui-disabled': {
backgroundColor: '#f0f0f0',
},
});
Then use them as standard component
<CustomTextField
name="manual"
label="Manual"
size="small"
disabled={watch({}).platform === 'manual' ? false : true}
/>
if u use RHF with controller, mean u create custom TextField using RHF, u just change the component inside the styled()
For example:
import RHFTextField from "../RHFTextField"
const CustomTextField = styled(RHFTextField)({
'& .MuiInputBase-root.Mui-disabled': {
backgroundColor: '#f0f0f0',
},
});
with background color changes, it will more visible..
In the Mui-v5 above solution is not working.
Below are the solutions for Mui-v5.
Solution 1:
const styles = theme => ({
input: {
"& input.Mui-disabled": {
color: "green"
}
}
});
Solution: 2 (use sx property for the component)
sx={{
"& .MuiInputBase-input.Mui-disabled": {
WebkitTextFillColor: "#000000",
},
}}
eg.
<TextField
fullWidth
disabled=true
variant="outlined"
sx={{
"& .MuiInputBase-input.Mui-disabled": {
WebkitTextFillColor: "#000000",
},
}}
/>
None of all the many answers online worked for me, using MUI v4.
Finally I found a very easy but hacky solution for setting the font color of a disabled TextField component.
The problem is, (at least for Firefox) it will use this weird style cheet:
.css-[...]-MuiInputBase-input-MuiOutlinedInput-input.Mui-disabled {
opacity: 1;
-webkit-text-fill-color: rgba(0, 0, 0, 0.38);
}
I'm too new to this stuff and I don't know how to change it, so my way was to overwrite it:
.css-[...]-MuiFormControl-root-MuiTextField-root input {
-webkit-text-fill-color: rgba(255,255,255,0.6) !important;
color: rgba(255,255,255,0.6);
}
The !important part is important!
In React with MUI v4, it's as simple as that:
const textFieldColor = /*...*/;
const textFieldSX = {
input: {
"-webkit-text-fill-color": `${textFieldColor} !important`,
color: `${textFieldColor} !important`,
},
};
/*...*/
<TextField sx={textFieldSX} />
Just in case, this -webkit-text-fill-color property would turn into color one time, one can use an !important there too.
works (MUIv5):
sx={{
"& .MuiInputBase-input.Mui-disabled": {
WebkitTextFillColor: "#000000",
},
}}

Material-UI - Why should I use makeStyles instead of inline styles?

In Material-UI, there is the makeStyles function which can be used to get custom CSS-Styling.
Should I use it if I am not using a theme in that specific CSS?
For example:
import React from "react";
import { TextField, Paper, Button, Box } from "#material-ui/core";
const classes = {
paper: {
backgroundColor: "#eee",
marginLeft: "30%",
marginRight: "30%"
},
textField: {
backgroundColor: "#fff"
},
button: {
backgroundColor: "green",
marginLeft: 20
}
};
const Ohne = () => {
console.log(classes);
return (
<Paper style={classes.paper}>
<Box>
<TextField style={classes.textField} />
<Button style={classes.button}>abc</Button>
</Box>
</Paper>
);
};
export default Ohne;
The object was:
{
"paper": {
"backgroundColor": "#eee",
"marginLeft": "30%",
"marginRight": "30%"
},
"textField": {
"backgroundColor": "#fff"
},
"button": {
"backgroundColor": "green",
"marginLeft": 20
}
}
vs
import React from "react";
import { makeStyles } from "#material-ui/styles";
import { TextField, Paper, Button, Box } from "#material-ui/core";
const useStyles = makeStyles(theme => ({
paper: {
backgroundColor: "#eee",
marginLeft: "30%",
marginRight: "30%"
},
textField: {
backgroundColor: "#fff"
},
button: {
backgroundColor: "green",
marginLeft: 20
}
}));
const Mit = () => {
const classes = useStyles();
console.log(classes);
return (
<Paper className={classes.paper}>
<Box>
<TextField className={classes.textField} />
<Button className={classes.button}>abc</Button>
</Box>
</Paper>
);
};
export default Mit;
The object was:
{
"paper": "makeStyles-paper-85",
"textField": "makeStyles-textField-86",
"button": "makeStyles-button-87"
}
So there are 3 main points (that I see):
One way creates classes and references them, the other just uses the object as is.
In the first case an object is assigned to the style property which is inline and has a higher priority.
In the first example it is important to keep the const outside of the class, so the object is still created only once and won't trigger a rerender.
But the resulting component looks identical (in my Firefox).
My questions:
Can an example be constructed where these two approaches result in different controls?
Is there any performance aspect to it?
Any other differences?
There are a few scenarios where using CSS classes (e.g. via makeStyles or withStyles) is necessary:
If you want to use media queries in your CSS
If you want to target pseudo-classes (e.g. :hover)
If you are creating a reusable customization of one of the Material-UI components and want to customize some of the classes that are conditionally applied to the element based on props or some other context (e.g. if you want to customize the "error" look of an Input while leaving it up to the places where the custom component is used to specify the error prop either directly or via the FormControl context)
As far as performance concerns, I would expect inline styles to be faster for most use cases. Whether the difference is enough to matter would depend on a lot of specifics regarding your particular application. The team I work with uses makeStyles or withStyles for most of our styling.
Inline styles can result in a lot of duplicated CSS in the DOM if a particular component is rendered many times within the document (e.g. list items, table cells, etc.). One nice thing about always using classes is that you can change the CSS for the class in the browser's developer tools and see that change applied throughout all its usages in the document.

Resources