Material UI - Autocomplete Styling - reactjs

I am trying to style the padding so that the icon is pushed to the far right side in an AutoComplete Material UI component which is currently being overridden by this style:
.MuiAutocomplete-hasPopupIcon.MuiAutocomplete-hasClearIcon .MuiAutocomplete-inputRoot[class*="MuiOutlinedInput-root"]
This is the code:
const useStyles = makeStyles(theme => ({
inputRoot: {
color: "blue",
fontFamily: "Roboto Mono",
backgroundColor: fade("#f2f2f2", 0.05),
"& .MuiOutlinedInput-notchedOutline": {
borderWidth: '2px',
borderColor: "blue"
},
"&:hover .MuiOutlinedInput-notchedOutline": {
borderWidth: "2px",
borderColor: "blue"
},
"&.Mui-focused .MuiOutlinedInput-notchedOutline": {
borderWidth: "2px",
borderColor: "blue"
}
}
}));
const textStyles = makeStyles({
formControlRoot: {
fontFamily: "Roboto Mono",
width: "50vw",
color: "#ffffff",
borderRadius: "7px",
position: "relative",
"& label.Mui-focused": {
color: "blue"
},
},
inputLabelRoot: {
color: "#ffffff",
fontFamily: "Roboto Mono",
"&.focused": {
color: "#ffffff"
}
},
});
export default function ComboBox() {
const classes = useStyles();
const textClasses = textStyles();
return (
<Autocomplete
id="combo-box-demo"
classes={classes}
// options={top100Films}
getOptionLabel={option => option.title}
renderInput={params => {
return (
<TextField
{...params}
label="Combo box"
variant="outlined"
classes={{ root: textClasses.formControlRoot }}
fullWidth
InputProps={{
...params.InputProps,
endAdornment: (
<InputAdornment position="end">
<SearchIcon />
</InputAdornment>
)
}}
InputLabelProps={{ classes: {root: textClasses.inputLabelRoot}}}
/>
);
}}
/>
);
}
And this is the result:

You are specifying the endAdornment for the Input, but Autocomplete also tries to specify the endAdornment. Your endAdornment is winning, but the Autocomplete is still trying to apply all of the CSS related to its end adornment (space for the popup icon and clear icon).
You can turn off the CSS related to the Autocomplete's end adornment by passing the props that turn off those features:
<Autocomplete
disableClearable
forcePopupIcon={false}
v4 CodeSandbox: https://codesandbox.io/s/autocomplete-with-custom-endadornment-86c87?file=/src/App.js
v5 CodeSandbox: https://codesandbox.io/s/autocomplete-with-custom-endadornment-euzor?file=/src/App.js
Alternatively, if you want to keep the clear icon and/or force-popup icon (arrow-drop-down icon), you can leverage cloneElement to add the search icon to the existing end adornment as shown below.
import React from "react";
import Autocomplete from "#mui/material/Autocomplete";
import TextField from "#mui/material/TextField";
import SearchIcon from "#mui/icons-material/Search";
import { styled } from "#mui/material/styles";
const StyledSearchIcon = styled(SearchIcon)`
vertical-align: middle;
`;
function addSearchIconToEndAdornment(endAdornment) {
const children = React.Children.toArray(endAdornment.props.children);
children.push(<StyledSearchIcon />);
return React.cloneElement(endAdornment, {}, children);
}
export default function ComboBox() {
return (
<Autocomplete
id="combo-box-demo"
options={top100Films}
getOptionLabel={(option) => option.title}
renderInput={(params) => {
return (
<TextField
{...params}
label="Combo box"
variant="outlined"
fullWidth
InputProps={{
...params.InputProps,
endAdornment: addSearchIconToEndAdornment(
params.InputProps.endAdornment
)
}}
/>
);
}}
/>
);
}

Related

Change border color of mui's textfield using style={}

I'm trying to change the color to border of mui's textfield to white. Can I do this somehow by using style={} in component or do I have to use makeStyles?
<TextField
label="Search login"
variant="outlined"
value={searchLogin}
inputProps={{
style: {
color:"white",
},
}}
InputLabelProps={{
style: {
color: "white",
borderColor : "white",
},
}}
onChange={(e) => {
setSearchLogin(e.target.value);
}}
/>
For those nested element you likely won't be able to use direct styling. Try following:
import * as React from "react";
import { ThemeProvider } from "#mui/system";
import TextField from "#mui/material/TextField";
import { createTheme } from "#material-ui/core/styles"
const styles = createTheme({
notchedOutline: {
borderWidth: "1px",
borderColor: "white !important"
}
});
export default function Example() {
return (
<ThemeProvider theme={styles}>
<TextField
label="Search login"
variant="outlined"
value={searchLogin}
onChange={(e) => { setSearchLogin(e.target.value); }}
/>
</ThemeProvider>
);
}

How to add backgrounds to mui outlined textfield

I tried creating a custom MUI Text field with the following code:
const CustomTextField = styled(TextField)(() => ({
height: '56px',
width: '505px',
'& input + fieldset': {
borderRadius: '12px',
borderColor: 'white',
color: 'black'
}
}));
export function SearchTextField(props: TextFieldProps): JSX.Element {
return (
<CustomTextField
style={{ width: '505px' }}
InputProps={{
style: {
height: '56px'
},
startAdornment: (
<InputAdornment position="start">
<SearchOutlined fontSize="medium" color="info" />
</InputAdornment>
)
}}
// eslint-disable-next-line react/jsx-props-no-spreading
{...props}
/>
);
}
When I add a background to the same, the input and the icon I have added is disappearing. I can still type and the input is still being taken but I can't see them.
It's supposed to look like this
But looks like this
Any kind of help is appreciated

How can I set the value of my MaterialUI TextField to uppercase?

I have a Material UI TextField as an input and I need to force the entered text as uppercase. I have tried using textTransform: "uppercase" as part of the style attribute but this does not seem to work. All of the other styling in my component is applied correctly however the textTransform is not.
I have also tried using the standard style method of passing my style as a prop to the component but I get the same result.
My component:
const MenuInput = (props) => {
const useStyles = makeStyles((theme) => ({
input: {
textTransform: "uppercase",
marginTop: "10px",
width: "100%",
borderRadius: 4,
backgroundColor: "#FFFFFF",
},
}));
const classes = useStyles();
return (
<TextField
className={classes.input}
id={props.id}
color="primary"
label={props.label}
variant="filled"
onChange={(e) => props.onChange(e)}
error={props.isError}
helperText={props.error}
/>
);
};
The output:
You could try applying styles through the inputProps like the following:
<TextField
className={classes.input}
id={props.id}
color="primary"
label={props.label}
variant="filled"
onChange={(e) => props.onChange(e)}
error={props.isError}
helperText={props.error}
inputProps={{ style: { textTransform: "uppercase" } }}
/>
I'll leave a link with a sandbox where I tested that solution.
try adding important
textTransform: "uppercase !important"
Or add inline style
<Textfield style={{textTransform:"uppercase"}} />

How to customize Autocomplete tag - Material UI

I'm using autocomplete of material ui and this is what default tag looks like
I want to customize tag like this.
How can i do that? Thank you.
<Autocomplete
disableCloseOnSelect={true}
multiple
options={this.options}
getOptionLabel={options => options.title}
value={this.state.value}
onChange={(e, techs) => {
this.newValue(techs);
}}
renderInput={params => (
<TextField
{...params}
variant="outlined"
placeholder={Technology}
fullWidth
/>
)}
></Autocomplete>
The renderTags prop from the Autocomplete API docs: https://material-ui.com/api/autocomplete/
The "tags" are Material UI Chips https://material-ui.com/components/chips/
so you can style an individual Chip component or variants to your liking and then override the default tags for Autocomplete.
Your styling for the chip would look something like
import { makeStyles } from '#material-ui/core/styles';
import Chip from '#material-ui/core/Chip';
export const useStyles = makeStyles((theme) => ({
root: {
borderRadius: 0,
color: labelColor,
boxSizing: 'border-box',
border: '1px solid',
borderColor: '#bddaff',
}
}));
;
const MyChip = (props) => {
const classes = useStyles();
return (
<Chip
className={classes.root}
{...props}
/>
);
};
And then you override the default chips
<Autocomplete
getOptionLabel={(option) => option.title}
label
placeHolder
multiple
openOnFocus
renderInput={(params) => <TextField {...params} label={label} placeholder={placeHolder} />}
renderTags={(tagValue, getTagProps) => {
return tagValue.map((option, index) => (
<MyChip {...getTagProps({ index })} label={option.title} />
));
}}
{...rest}
/>
);
You can use the tag CSS class to customize the tags as shown below.
import React from "react";
import TextField from "#material-ui/core/TextField";
import Autocomplete from "#material-ui/lab/Autocomplete";
import { withStyles } from "#material-ui/core/styles";
const CustomAutocomplete = withStyles({
tag: {
backgroundColor: "#a0a",
height: 24,
position: "relative",
zIndex: 0,
"& .MuiChip-label": {
color: "#fff"
},
"& .MuiChip-deleteIcon": {
color: "red"
},
"&:after": {
content: '""',
right: 10,
top: 6,
height: 12,
width: 12,
position: "absolute",
backgroundColor: "white",
zIndex: -1
}
}
})(Autocomplete);
export default function Tags() {
return (
<div style={{ width: 500 }}>
<CustomAutocomplete
multiple
id="tags-standard"
options={top100Films}
getOptionLabel={option => option.title}
defaultValue={[top100Films[13]]}
renderInput={params => (
<TextField
{...params}
variant="standard"
label="Multiple values"
placeholder="Favorites"
margin="normal"
fullWidth
/>
)}
/>
</div>
);
}
// Top 100 films as rated by IMDb users. http://www.imdb.com/chart/top
const top100Films = [
{ title: "The Shawshank Redemption", year: 1994 },
{ title: "The Godfather", year: 1972 },
{ title: "The Godfather: Part II", year: 1974 },
// ... plus many more
];

Remove Label on Material-UI Select Text Field

I have a select field for gender which has the label positioned in the centre of the select, which is the desired layout.
When the user selects this field the label flies away to the top left corner as shown. What I want to do is remove the label entirely and replace that with a blue border.
Here is my code:
<TextField
id='gender-select'
select
label="Gender"
className={classes.textField}
value={gender}
onChange={data => setGender(data.target.value)}
margin='normal'
variant='outlined'>
{genders.map(option => (
<MenuItem key={option.value} value={option.value}>
{option.label}
</MenuItem>
))}
</TextField>
and here is my styling code:
const useStyles = makeStyles(theme => ({
textField: {
marginLeft: theme.spacing(1),
marginRight: theme.spacing(1),
marginTop: theme.spacing(1),
'& .MuiOutlinedInput-root': {
'& fieldset': {
borderColor: '#CACACA'
},
'&:hover fieldset': {
borderColor: '#007AFF'
},
'&.Mui-focused hover': {
borderColor: '#007AFF'
},
'&.Mui-focused fieldset': {
borderColor: '007AFF'
}
}
}
}))
I have tried adding a conditional on the label prop to nullify it, eg:
label={gender== "" ? "Gender": null}
but this simply gives me a blank line in place of the label.
How do I change the label for a blue line when the field is in focus?
The reason your solution didn't quite work is because TextField doesn't watch for changes to the label. It figures out the label width in an effect after the initial rendering.
Fortunately, there is an easy way to avoid the notch. You can prevent the label from "shrinking" up with InputLabelProps={{shrink: false}}.
Here is a full working example:
import React from 'react';
import { makeStyles } from '#material-ui/core/styles';
import MenuItem from '#material-ui/core/MenuItem';
import TextField from '#material-ui/core/TextField';
const genders = [
{
value: 'M',
label: 'Male',
},
{
value: 'F',
label: 'Female',
},
{
value: 'O',
label: 'Other',
},
];
const useStyles = makeStyles(theme => ({
container: {
display: 'flex',
flexWrap: 'wrap',
},
textField: {
marginLeft: theme.spacing(1),
marginRight: theme.spacing(1),
width: 100
},
dense: {
marginTop: theme.spacing(2),
},
menu: {
width: 100,
},
}));
export default function OutlinedTextFields() {
const classes = useStyles();
const [gender, setGender] = React.useState("");
const handleChange = event => {
setGender(event.target.value);
};
return (
<form className={classes.container} noValidate autoComplete="off">
<TextField
id="outlined-select-gender"
select
label={gender=== "" ? "Gender": ""}
className={classes.textField}
value={gender}
onChange={handleChange}
InputLabelProps={{shrink: false}}
SelectProps={{
MenuProps: {
className: classes.menu,
},
}}
margin="normal"
variant="outlined"
>
{genders.map(option => (
<MenuItem key={option.value} value={option.value}>
{option.label}
</MenuItem>
))}
</TextField>
</form>
);
}
Try this -
<TextField
sx={{ '& legend': { display: 'none' }, '& fieldset': { top: 0 },}}
/>
That's the simplest way to do it:
<TextField
id='gender-select'
select
placeholder="Gender" // <<<<< See here
className={classes.textField}
value={gender}
onChange={data => setGender(data.target.value)}
margin='normal'
variant='outlined'>
{genders.map(option => (
<MenuItem key={option.value} value={option.value}>
{option.label}
</MenuItem>
))}
</TextField>
The TextField forwards props of the FormControl. And the latter has the hiddenLabel property. It removes the label w/o any CSS workarounds.
Property definition - https://mui.com/material-ui/api/form-control/#:~:text=of%20its%20container.-,hiddenLabel,-bool
Demo - https://mui.com/material-ui/react-text-field/#sizes

Resources