Remove Label on Material-UI Select Text Field - reactjs

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

Related

Mui select - change background color once a menuItem is selected

I have a Mui Select with different menu items. I want to be able to change the background color of the select once a user has chosen a menu item.
This is one of my selects with the menu items:
<p className="text-md font-nunito font-medium">Role</p>
<FormControl>
<Select
displayEmpty
variant="outlined"
id="role"
name="role"
className="border text-white"
sx={{
bgColor: '#393939',
color: 'white',
'& .MuiSelect-iconOutlined': {
color: '#393939',
},
}}
value={role}
onChange={(event) => {
handleChange(event);
handleRoleSwitch(event);
}}
onBlur={handleBlur('role')}
MenuProps={{
PaperProps: {
sx: {
bgcolor: '#393939',
'& .MuiMenuItem-root': {
padding: 2,
color: 'white',
},
},
},
}}
>
<MenuItem value="">
<em>None</em>
</MenuItem>
<MenuItem className="text-white" value="admin">
Admin
</MenuItem>
<MenuItem className="text-white" value="user">
User
</MenuItem>
<MenuItem className="text-white" value="viewer">
Viewer
</MenuItem>
</Select>
</FormControl>
How about using a useState variable for representing the bgColor that changes when clicking a menu item?
Here is a quick example on how you could do it.
const [bgColorValue, setBgColorValue] = useState('#393939')
const handleBgColorChange = (newValue) => {
setBgColorValue(newValue)
}
<Select
displayEmpty
variant="outlined"
id="role"
name="role"
className="border text-white"
sx={{
bgColor: '#393939',
color: 'white',
'& .MuiSelect-iconOutlined': {
color: '#393939',
},
}}
value={role}
onChange={(event) => {
handleChange(event);
handleRoleSwitch(event);
}}
onBlur={handleBlur('role')}
MenuProps={{
PaperProps: {
sx: {
bgcolor: bgColorValue,
'& .MuiMenuItem-root': {
padding: 2,
color: 'white',
},
},
},
}}
>
```
And then just use the onClick={() => handleBgColorChange('#404040')} where you want the new bgValue to be set. Obviously, i just used #404040 as a example. Hope this helps in some sort of way.
You can create a variable to set if a selection happened using useState. Then control it using the onChange of the Select.
Have a look at the code below and in this working codesandbox
Here is a working codesandbox with your code.
I have used styled-components in both.
import * as React from "react";
import Box from "#mui/material/Box";
import InputLabel from "#mui/material/InputLabel";
import MenuItem from "#mui/material/MenuItem";
import FormControl from "#mui/material/FormControl";
import Select, { SelectChangeEvent } from "#mui/material/Select";
import styled from "#emotion/styled";
export interface StyledSelectProps {
isSelected: boolean;
}
const StyledSelect = styled(Select)`
background: ${({ isSelected }: StyledSelectProps) =>
isSelected ? "#f38713" : "white"};
`;
export default function BasicSelect() {
const [age, setAge] = React.useState("");
const [itemSelected, setItemSelected] = React.useState(false);
const handleChange = (event: SelectChangeEvent) => {
setAge(event.target.value as string);
setItemSelected(true);
};
return (
<Box sx={{ minWidth: 120 }}>
<FormControl fullWidth>
<InputLabel id="demo-simple-select-label">Age</InputLabel>
<StyledSelect
labelId="demo-simple-select-label"
id="demo-simple-select"
value={age}
label="Age"
onChange={handleChange}
isSelected={itemSelected}
>
<MenuItem value={10}>Ten</MenuItem>
<MenuItem value={20}>Twenty</MenuItem>
<MenuItem value={30}>Thirty</MenuItem>
</StyledSelect>
</FormControl>
</Box>
);
}

How to change Color of the arrow down textfield material ui

I have a select textfiled and i want when i hover or select the textfiled the arrow down color change too, this is my textfiled and style of that
Style
const styles = theme => ({
icon: {
fill: themeStyle.textColor,
},
underline: {
'&:before': {
borderBottomColor: themeStyle.textFieldUnderLineColor,
},
'&:after': {
borderBottomColor: themeStyle.tabIndicatorProps,
color: themeStyle.tabIndicatorProps,
},
'&:hover:before': {
borderBottomColor: [themeStyle.underLineSearchTextFieldColor, '!important'],
},
color: themeStyle.titleTextColor,
},
notchedOutline: {},
outlinedInput: {
'&$focused $notchedOutline': {
border: `2px solid ${themeStyle.tabIndicatorProps}`
},
backgroundColor: themeStyle.bkgBodyColor
},
focused: {},
notchedOutline: {},
})
textfield
<TextField
select
SelectProps={{
native: true,
}}
className = {classes.textField}
InputLabelProps={{
classes: {
root: classes.cssLabel,
focused: classes.cssFocused,
}
}}
InputProps={{
classes:{
underline: classes.underline,
icon: classes.icon
}
}}
type= 'select'
>
{Tools.GetEnumSelectOptionsAddAll(APP_Enums.DoModeEnum)}
</TextField>
now i want to change the color of this when i hover or select or ...
You should use the SelectProps property to feed the style you required.
Here is a working example - https://codesandbox.io/s/material-demo-select-6lewu
Refer to the below,
const useStyles = makeStyles((theme) => ({
root: {
"& .MuiTextField-root": {
margin: theme.spacing(1),
width: "25ch"
}
},
icon: {
color: "red"
}
}));
export default function MultilineTextFields() {
const classes = useStyles();
const [currency, setCurrency] = React.useState("EUR");
const [isMouseOver, setMouseOver] = React.useState(false);
const handleChange = (event) => {
setCurrency(event.target.value);
};
const handleMouseEnter = () => {
setMouseOver(true);
};
const handleMouseLeave = () => {
setMouseOver(false);
};
return (
<form className={classes.root} noValidate autoComplete="off">
<div>
<TextField
id="standard-select-currency-native"
select
label="Native select"
value={currency}
onChange={handleChange}
onMouseEnter={handleMouseEnter}
onMouseLeave={handleMouseLeave}
SelectProps={{
native: true,
classes: {
icon: isMouseOver ? classes.icon : null
}
}}
helperText="Please select your currency"
>
{currencies.map((option) => (
<option key={option.value} value={option.value}>
{option.label}
</option>
))}
</TextField>
</div>
</form>
);
}
In addition to that, I used onMouseEnter and onMouseLeave triggers to apply the special request you had to change the icon color when mouse over.

Matrial UI change border of outlined select

I want to change the default outline color of the Select component in Material UI.
This is what I've tried but did not work:
const useStyles = makeStyles(theme => ({
formControl: {
margin: theme.spacing(1),
minWidth: 120,
borderColor: "green",
},
selectEmpty: {
marginTop: theme.spacing(2)
},
outlined: {
'&:before': {
borderColor: "green",
},
'&:after': {
borderColor: "green",
}
},
}));
export default function SimpleSelect() {
const classes = useStyles();
const [age, setAge] = React.useState("");
const handleChange = event => {
setAge(event.target.value);
};
return (
<div>
<FormControl variant="outlined" className={classes.formControl}>
<InputLabel id="demo-simple-select-outlined-label">Age</InputLabel>
<Select
labelId="demo-simple-select-outlined-label"
id="demo-simple-select-outlined"
value={age}
onChange={handleChange}
label="Age"
className={classes.outlined}
>
<MenuItem value="">
<em>None</em>
</MenuItem>
<MenuItem value={10}>Ten</MenuItem>
<MenuItem value={20}>Twenty</MenuItem>
<MenuItem value={30}>Thirty</MenuItem>
</Select>
</FormControl>
</div>
);
}
Thank you in advance for the help!
P.S. This is how it looks when focused/selected
Try with deep nesting or with important.
borderColor: "green !important",

Material UI - Autocomplete Styling

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

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
];

Resources