Matrial UI change border of outlined select - reactjs

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",

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 pass variable to MUI styled function in ReactJS

How can I pass variable to conditionally change styles properties while using MUI styled function? I want to achieve this: borderColor: darkMode ? 'white' : 'black'
const StyledSelect = styled(Select)(() => ({
"& fieldset": {
borderColor: 'dark',
}
}));
function BasicSelect() {
const { darkMode }= useSelector((state: {options: {darkMode: boolean}})=>state.options)
const [age, setAge] = React.useState('');
const handleChange = (event: SelectChangeEvent) => {
setAge(event.target.value as string);
};
return (
<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}
>
<MenuItem value={10}>Ten</MenuItem>
<MenuItem value={20}>Twenty</MenuItem>
<MenuItem value={30}>Thirty</MenuItem>
</Select>
</FormControl>
);
}
One of the options that works is to make function and pass it to sx prop like this, but I wonder if it is possible to pass variable directly to styled function
const selectstyles = (darkMode) => ({
"& fieldset": {
borderColor: darkMode ? 'white' : 'black'
}
})
<StyledSelect sx={selectStyles(darkMode)} ...></StyledSelect>
The same question was asked here: https://stackoverflow.com/a/69341672/8972840
This will help you pass props through the styled() function.

Importing useStyles into a function - TypeError: prevDeps is undefined

I have been using class components and importing my useStyles files with const classes = useStyles();. What is the correct way to use this in a function?
The classes.formControl etc is being used on each of my MaterialUI dropdowns and they are throwing the errors. Does I need to write this as a hook? do I need to remove makeStyles from my styleSheet?
error message
TypeError: prevDeps is undefined
areHookInputsEqual
const classes = useStyles();
return (
<form>
<FormControl className={classes.formControl}>
<InputLabel id="Enter-the-dive-type">Dive Type</InputLabel>
<Select
labelId="Enter-the-dive-type"
id="Enter-the-dive-typer"
value={dive.typeID}
onChange={handleChange}>
<MenuItem value="">
<em>None</em>
</MenuItem>
<MenuItem value={10}>Ten</MenuItem>
<MenuItem value={20}>Twenty</MenuItem>
<MenuItem value={30}>Thirty</MenuItem>
</Select>
</FormControl>
styles
export const useStyles = makeStyles((theme) => ({
table: {
maxWidth: 450,
},
form: {
width: '100%', // Fix IE 11 issue.
marginTop: theme.spacing(1),
},
submit: {
margin: theme.spacing(3, 0, 2),
},
formControl: {
margin: theme.spacing(1),
minWidth: 120,
},
selectEmpty: {
marginTop: theme.spacing(2),
},
}));

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

Give <Select> options a border

Is it possible to give the container of the <Select> options a border? The <Select> tag implements a <Popover> with a <Menu> component on which the <MenuItem>s options are rendered, but the documentation does not detail how this container can be styled.
There is an option to apply props to the menu via MenuProps, but it is not clear in the examples/documentation how a border could be applied to it.
https://codesandbox.io/s/material-demo-2cdqs?fontsize=14
import ...;
const useStyles = makeStyles((theme: Theme) =>
createStyles({
containerWithBorder: {
paper: {
border: "1px solid red"
}
}
})
);
function SimpleSelect() {
const classes = useStyles();
return (
<form className={classes.root} autoComplete="off">
<FormControl className={classes.formControl}>
<InputLabel htmlFor="age-simple">Age</InputLabel>
<Select
MenuProps={{ // Can this be used to give the options a border?
classes: classes.containerWithBorder
}}
value={values.age}
onChange={handleChange}
inputProps={{
name: "age",
id: "age-simple"
}}
>
<MenuItem value="">
<em>None</em>
</MenuItem>
<MenuItem value={10}>Ten</MenuItem>
<MenuItem value={20}>Twenty</MenuItem>
<MenuItem value={30}>Thirty</MenuItem>
</Select>
</FormControl>
</form>
);
}
export default SimpleSelect;
Yes, what you would do is write your style in the in the override useStyles section
const useStyles = makeStyles((theme: Theme) =>
createStyles({
select: {
border: "1px solid black",
},
}),
);
like this and then you would pass it to the Select component:
<Select className={classes.select} />
like this

Resources