Material-UI: How to add Icons in the TextField label? - reactjs

I am trying to add Material-UI icons into TextField component, I want to add it to the label not in input Field.
Eg:
through Inputprops we can pass and add icon to input, but I want it in label. How to achieve this..?
<Field label="Name" required /> -> Name*
What I want to achieve is:
<Field label="Name" required /> -> Name*(icon)

It can be achieved by using flex and order properties of CSS, lightweight and effective.
Result:
Full code sample :
Code fragment :
const useStyles = makeStyles({
root: {
"& .MuiFormLabel-root": {
display: "flex",
alignItems: "center",
"& .myIcon": {
paddingLeft: "8px",
order: 999
}
}
}
});
const Demo = () => {
const classes = useStyles();
return (
<TextField
className={classes.root}
required
label={
<Fragment>
I am label
<SettingsRounded className="myIcon" fontSize="small" />
</Fragment>
}
variant="outlined"
/>
);
};
Hope to help you !

Because label can accept a ReactNode, you add an icon component to the TextField like this:
import { makeStyles } from "#material-ui/core/styles";
import TextField from "#material-ui/core/TextField";
import Add from "#material-ui/icons/Add";
const useStyles = makeStyles({
root: {
"& label": {
marginTop: -3, // fix the icon alignment issue
}
},
label: {
display: "inline-flex",
alignItems: "center"
}
});
export default function BasicTextFields() {
const classes = useStyles();
return (
<TextField
className={classes.root}
label={
<div className={classes.label}>
<span>My Label</span>
<Add />
</div>
}
variant="outlined"
/>
);
}
Live Demo

Related

Material ui: How to change DatePicker text and calendar icon color?

I am trying to change the Material UI DatePicker date text and calendar icon color.
I tried to change it passing style to InputProps, but it worked only for removing border.
Rather than that, nothing changes, I tried to apply style to theme.tsx, but it also didn't help.
Any help will be appreciated.
import * as React from "react";
import Stack from "#mui/material/Stack";
import TextField from "#mui/material/TextField";
import AdapterDateFns from "#mui/lab/AdapterDateFns";
import LocalizationProvider from "#mui/lab/LocalizationProvider";
import DesktopDatePicker from "#mui/lab/DesktopDatePicker";
import { makeStyles, createStyles } from "#material-ui/core";
const useStyles = makeStyles(() =>
createStyles({
noBorder: {
outline: "none",
border: "none",
color: "#fff",
},
})
);
export default function DatePicker() {
const [value, setValue] = React.useState<Date | null>();
const classes = useStyles();
const handleChange = (newvalue: Date | null) => {
setValue(newvalue);
};
return (
<LocalizationProvider dateAdapter={AdapterDateFns}>
<Stack spacing={2}>
<DesktopDatePicker
inputFormat="dd/MM/yyy"
value={value}
onChange={handleChange}
renderInput={(params) => <TextField {...params} />}
InputProps={{
classes: { notchedOutline: classes.noBorder },
}}
/>
</Stack>
</LocalizationProvider>
);
}
1st solution - using sx property
You can set sx property to <TextField/> component in order to overwrite default style properties:
const color = "#c44242";
...
return (
<DatePicker
renderInput={(params) => {
return (
<TextField
{...params}
sx={{
svg: { color },
input: { color },
label: { color }
}}
/>
);
}}
...other props
/>
)
Setting colors with sx prop
2nd solution - providing a custom theme
You can also create a custom theme and overwrite colors inside it:
const theme = createTheme({
components: {
MuiIconButton: {
styleOverrides: {
sizeMedium: {
color
}
}
},
MuiOutlinedInput: {
styleOverrides: {
root: {
color
}
}
},
MuiInputLabel: {
styleOverrides: {
root: {
color
}
}
}
}
});
Then you wrap your component with ThemeProvdier.
Overriding Theme Demo
The solution that worked for me is as follows -
I used the sx property in <TextField/> which is also mentioned by dmitriif.
The implementation looked something like this -
<DateTimePicker
value={value}
onChange={handleChange}
renderInput={(params) => (
<TextField
{...params}
sx={{
svg: { color: '#fff' },
input: { color: '#fff' },
}}
/>
)}
/>
Try to inspect element then you can see the styling of the inspected element. Inspect element is so useful.

Margin not working in TextField using MUI makeStyles

I am trying to add margin to my TextField component by making an object of makestyles using MUI v5.
The background color is reflecting in the component but not margin and padding. Here is my code
import React, { useState } from 'react'
import { Typography } from '#mui/material'
import { Button } from '#mui/material'
import { ButtonGroup } from '#mui/material'
import { Container } from '#mui/material'
import { makeStyles } from '#mui/styles';
import TextField from '#mui/material/TextField';
Here I have used makeStyles
const useStyles = makeStyles({
field: {
// paddingTop: '20px',
padding: '100px',
backgroundColor: 'red',
marginBottom: '100px',
// margin: 100
// display: 'block'
},
});
export default function Create() {
const classes = useStyles()
return (
<Container>
<Typography
variant="h6"
component="h2"
gutterBottom
color="textSecondary"
>
Create a New Note
</Typography>
<form noValidate autoComplete="off" >
<TextField
className={classes.field}
label="Note Title"
variant="outlined"
color="secondary"
fullWidth
required
error={titleError}
>
</TextField>
<Button
type="submit"
color="secondary"
variant="outlined"
onClick={() => console.log("you clicked me")}
endIcon={<KeyboardArrowRightOutlinedIcon />}
>Submit </Button>
</form>
</Container>
)
}
All of this is in a single file
Here is the screenshot.
TextField is just a wrapper component of the Input inside it, to target the input for styling, you can use InputProps:
<TextField
InputProps={{
className: classes.field
}}
EDIT: The margin doesn't work in your TextField because of the CSS specificity. Your style is overrode by the other one from emotion, to fix it, double the className using this technique:
const useStyles = makeStyles({
field: {
// append the same classname to increase the specificity
// output has something like: .makeStyles-field-5.makeStyles-field-5
"&&": {
marginBottom: "100px"
}
}

Mui Tabs - How to use custom icons

I'm new to mui and react in general, and I have 2 questions.
I'm trying to use my own SVG files as custom icons in a mui tab, but can't figure out how exactly to do that (with all the effects as using mui icon).
my code:
import { ReactComponent as SecondIcon } from "../../images/tabs/secondTab.svg";
import { ReactComponent as ThirdIcon } from "../../images/tabs/thirdTab.svg";
import { ReactComponent as FourthIcon } from "../../images/tabs/fourthTab.svg";
import FirstTabSvg from "../../images/svg/FirstTabSvg";
const useStyles = makeStyles((theme) => ({
root: {
flexGrow: 1,
maxWidth: 500,
width: 80,
alignItems: "center",
display: "flex",
flexDirection: "column",
},
margin: {
padding: theme.spacing(2),
},
tab: {
width: 80,
},
imageIcon: {
height: '100%'
},
iconRoot: {
textAlign: 'center'
}
}));
export default function IconTabs() {
const classes = useStyles();
const [value, setValue] = React.useState(0);
const handleChange = (event, newValue) => {
setValue(newValue);
};
return (
<Paper square className={classes.root}>
<IconButton color="primary" size="small" className={classes.margin}>
<LogoIcon />
</IconButton>
<Divider variant="middle" style={{ alignSelf: "stretch" }} />
<Tabs
value={value}
onChange={handleChange}
// variant="fullWidth"
width="auto"
indicatorColor="primary"
textColor="primary"
aria-label="icon tabs example"
orientation="vertical"
>
<Tab icon={<FirstTabSvg />} aria-label="first" />
<Tab icon={<SecondIcon />} aria-label="second" />
<Tab icon={<ThirdIcon />} aria-label="third" />
<Tab icon={<FourthIcon />} aria-label="fourth" />
</Tabs>
</Paper>
);
}
I've tried 2 options (import as ReactComponent & SvgIcon with src)
FirstTabSvg.js (saw this as an answer in another question):
import React from 'react';
import pure from 'recompose/pure';
import { SvgIcon } from '#material-ui/core';
let FirstTabSvg = (props) => (
<SvgIcon {...props}>
<img src="../tabs/firstTab.svg" />
</SvgIcon>
);
FirstTabSvg = pure(FirstTabSvg);
FirstTabSvg.displayName = 'FirstTabSvg';
FirstTabSvg.muiName = 'SvgIcon';
export default FirstTabSvg;
result:
Tabs
as you can see, the FirstTabSvg does not render, and the ReactComponent does render but I don't know how to change the color for an active tab.
how can I change the tabs width? as you can see in the picture, the indicator is not in the same line as the tabs

How can I set an static outlined div similar to Material-UI's outlined textfield?

I want wrap some TextFields in a outlined container and I found this answer. This work as i want:
But when I click in an inside textfield all the texfields focused:
This is my code:
import React from "react";
import ReactDOM from "react-dom";
import OutlinedDiv from "./OutlinedDiv";
import TextField from "#material-ui/core/TextField";
import Grid from "#material-ui/core/Grid";
function App() {
return (
<div className="App">
<OutlinedDiv label="DIV">
<Grid container justify="center" alignItems="center" spacing={3}>
<Grid item sm={4} xs={12}>
<TextField label="Text1" variant="outlined" />
</Grid>
<Grid item sm={4} xs={12}>
<TextField label="Text2" variant="outlined" />
</Grid>
<Grid item sm={4} xs={12}>
<TextField label="Text3" variant="outlined" />
</Grid>
<Grid item sm={4} xs={12}>
<TextField label="Text4" variant="outlined" />
</Grid>
<Grid item sm={4} xs={12}>
<TextField label="Text5" variant="outlined" />
</Grid>
<Grid item sm={4} xs={12}>
<TextField label="Text6" variant="outlined" />
</Grid>
</Grid>
</OutlinedDiv>
</div>
);
}
const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);
How I can achive this style and when click in an inside component only focus the selected component?
A response with another approach and the similar solution for outlined div is welcome.
Thanks in advance.
Below is an approach that does not leverage TextField or FormControl and thus can be safely used to wrap other inputs. This copies some styles from OutlinedInput and the InputLabel styles applied when within a FormControl.
import React from "react";
import ReactDOM from "react-dom";
import InputLabel from "#material-ui/core/InputLabel";
import NotchedOutline from "#material-ui/core/OutlinedInput/NotchedOutline";
import { withStyles } from "#material-ui/core/styles";
import clsx from "clsx";
const styles = {
root: {
position: "relative",
marginTop: "8px"
},
contentWrapper: {
position: "relative"
},
content: {
padding: "18.5px 14px"
},
inputLabel: {
position: "absolute",
left: 0,
top: 0,
// slight alteration to spec spacing to match visual spec result
transform: "translate(0, 24px) scale(1)"
},
notchedOutline: {}
};
const LabelledOutline = ({ classes, id, label, children, className }) => {
const [labelWidth, setLabelWidth] = React.useState(0);
const labelRef = React.useRef(null);
React.useEffect(() => {
const labelNode = ReactDOM.findDOMNode(labelRef.current);
setLabelWidth(labelNode != null ? labelNode.offsetWidth : 0);
}, [label]);
return (
<div className={clsx(className, classes.root)}>
<InputLabel
ref={labelRef}
htmlFor={id}
variant="outlined"
className={classes.inputLabel}
shrink
>
{label}
</InputLabel>
<div className={classes.contentWrapper}>
<div id={id} className={classes.content}>
{children}
<NotchedOutline
className={classes.notchedOutline}
notched
labelWidth={labelWidth}
/>
</div>
</div>
</div>
);
};
export default withStyles(styles)(LabelledOutline);
And below is an example using it both without customization and once with customized colors for the label, outline, and content that changes on hover.
import React from "react";
import ReactDOM from "react-dom";
import { withStyles } from "#material-ui/core/styles";
import LabelledOutline from "./LabelledOutline";
const CustomColorLabelledOutline = withStyles({
root: {
"& $notchedOutline": {
borderColor: "purple"
},
"&:hover $notchedOutline": {
borderColor: "orange"
},
"& $inputLabel": {
color: "green"
},
"&:hover $inputLabel": {
color: "blue"
},
"& $content": {
color: "black"
},
"&:hover $content": {
color: "purple"
}
},
notchedOutline: {},
inputLabel: {},
content: {}
})(LabelledOutline);
function App() {
return (
<div>
<LabelledOutline id="myID" label="My Label">
My Content
</LabelledOutline>
<CustomColorLabelledOutline label="My Label">
My Content with custom label and outline color
</CustomColorLabelledOutline>
</div>
);
}
const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);
And the obligatory TS version (deeply inspired by #Ryan Cogswell's version):
import React, { ReactElement, ReactNode } from "react";
import InputLabel from "#material-ui/core/InputLabel";
import NotchedOutline from "#material-ui/core/OutlinedInput/NotchedOutline";
import { makeStyles, Theme } from "#material-ui/core/styles";
import clsx from "clsx";
const useStyles = makeStyles((theme: Theme) => ({
root: {
position: "relative",
marginTop: "8px",
},
contentWrapper: {
position: "relative",
},
content: {
// padding: "18.5px 14px",
padding: theme.spacing(1),
},
inputLabel: {
position: "absolute",
left: 0,
top: 0,
// slight alteration to spec spacing to match visual spec result
transform: "translate(0, 24px) scale(1)",
},
notchedOutline: { borderRadius: theme.shape.borderRadius },
}));
interface Props {
id: string;
label: string;
children: ReactNode;
className?: string;
}
export default function Conftainer({ id, label, children, className }: Props): ReactElement {
const [labelWidth, setLabelWidth] = React.useState(0);
const labelRef = React.useRef(null);
React.useEffect(() => {
if (labelRef && labelRef.current && (labelRef.current as any).offsetWidth) {
setLabelWidth((labelRef.current as any).offsetWidth);
}
}, [label]);
const classes = useStyles();
return (
<div className={clsx(className, classes.root)}>
<InputLabel
ref={labelRef}
htmlFor={id}
variant="outlined"
className={classes.inputLabel}
shrink
>
{label}
</InputLabel>
<div className={classes.contentWrapper}>
<div id={id} className={classes.content}>
{children}
<NotchedOutline className={classes.notchedOutline} notched labelWidth={labelWidth} />
</div>
</div>
</div>
);
}
(any edits to get rid of the any more than welcome)
I don't have enough point to post a comment on #AntonOfTheWoods answer (I signed up SO today especially for this question).
Just use const labelRef = React.useRef<HTMLLabelElement>(null); and you should be able to get rid of the any

Change TextField font color in MUI?

I'm currently using MUI.
And I'm having issues trying to change the font color of the multiline TextField.
<TextField className = "textfield"
fullWidth
multiline
label = "Debugger"
rows = "10"
margin = "normal"/>
And the CSS:
.textfield {
background-color: #000;
color: green;
}
However, somehow I only get the black background and the font is still black. Does anyone know how to properly change the font color of a TextField using MUI?
In MUI v5, you can just do this using sx prop:
<TextField sx={{ input: { color: 'red' } }} />
A bit longer approach if you want something more reusable:
const options = {
shouldForwardProp: (prop) => prop !== 'fontColor',
};
const StyledTextField = styled(
TextField,
options,
)(({ fontColor }) => ({
input: {
color: fontColor,
},
}));
<StyledTextField label="Outlined" fontColor="green" />
<StyledTextField label="Outlined" fontColor="purple" />
Live Demo
I referred this page TextField API
And I override the TextField using Classes
const styles = theme => ({
multilineColor:{
color:'red'
}
});
Apply the class to TextField using InputProps.
<TextField
className = "textfield"
fullWidth
multiline
InputProps={{
className: classes.multilineColor
}}
label = "Debugger"
rows = "10"
margin = "normal" />
EDIT In older version you have to specify the key input
<TextField
className = "textfield"
fullWidth
multiline
InputProps={{
classes: {
input: classes.multilineColor
}
}}
label = "Debugger"
rows = "10"
margin = "normal"
/>
Hope this will work.
Using inputProps is correct, as others have posted. Here's a slightly simpler example:
<TextField
multiline
inputProps={{ style: { color: "red" } }}
/* ... */
/>
How to set color property and background property of Text Field
import PropTypes from "prop-types";
import { withStyles } from "#material-ui/core/styles";
import TextField from "#material-ui/core/TextField";
const styles = {
root: {
background: "black"
},
input: {
color: "white"
}
};
function CustomizedInputs(props) {
const { classes } = props;
return (
<TextField
defaultValue="color"
className={classes.root}
InputProps={{
className: classes.input
}}
/>
);
}
CustomizedInputs.propTypes = {
classes: PropTypes.object.isRequired
};
export default withStyles(styles)(CustomizedInputs);
//textfield customization
const CssTextField = withStyles({
root: {
'& .MuiInputBase-root': {
color: 'white',
},
},
})(TextField);
This should work !
import { TextField, makeStyles } from "#material-ui/core";
const useStyles = makeStyles((theme) => ({
input: {
color: "#FFF",
},
}));
const MyInput = () => {
const classes = useStyles();
return (
<TextField
inputProps={{ className: classes.input }}
id="outlined-basic"
label="Write something..."
variant="outlined"
/>
);
};
export default MyInput;
If you are looking for a more generic fix, you can change your theme to contain that color, in my case I needed to change the input background and the disabled as well, so I end up using the ThemeProvider and a custom Theme.
Custom theme
const theme = createTheme({
components: {
MuiInputBase: {
styleOverrides: {
root: {
backgroundColor: '#fff',
'&.Mui-disabled': {
backgroundColor: '#e4e4e4',
},
},
},
},
},
});
const withDefaultTheme =
<P extends object>(Component: React.ComponentType<P>) =>
(props: any) =>
(
<ThemeProvider theme={theme}>
<Component {...props} />
</ThemeProvider>
);
This is working in my case:
import React from 'react';
import { TextField, } from '#mui/material';
import { makeStyles } from "#mui/styles";
const useStyles = makeStyles((theme) => ({
textfield_input: {
color: `#c5cae9 !important`,
}
}));
function Videoedit() {
const classes = useStyles();
return (<div>
<TextField
value={title}
required
label="Title"
variant="filled"
inputProps={{className: classes.textfield_input}}
color="primary"
focused
/>)
</div>;
}
export default Videoedit;
if you are using styled component with TextField then just write this code inside your styled component:
input: {
color: '#ffffff',
},
if you want to change placeholder color:
label: {
color: '#ffffff',
},
Use your Component like below
const MyTextField = withStyles({
root: {
"& .MuiInputBase-root.Mui-disabled": {
color: "rgba(0, 0, 0,0.0)"
},
"& .MuiFormLabel-root.Mui-disabled": {
color: "rgba(0, 0, 0,0.0)"
},
}
})(TextField);
Try below css
.textfield{
color: #000;
}

Resources