How to set css of different parts of a Material UI Dialog? - css

So this is a sample piece of code for Material Dialog
<Dialog
open={this.props.open}
onClose={this.props.closeAtParent}
PaperProps={{
style: {
minHeight: '75vh',
minWidth: '75vw',
},
}}
aria-labelledby="open-dialog-title"
aria-describedby="open-dialog-description"
>
<DialogTitle id="open-dialog-title">
{this.props.dialogs[this.state.selected].title}
</DialogTitle>
<DialogContent>
<DialogContentText id="open-dialog-description">
{this.props.dialogs[this.state.selected].desc}
</DialogContentText>
{this.imageIfExists()}
</DialogContent>
<DialogActions>
{this.populateButtons()}
</DialogActions>
</Dialog>
Now as you can see I was able to set the dialog width and height through PaperPros but I am unable to set other properties like backdrop color and DialogActions' button alignment.
There is no documentation or SO available for the same which is so sad. They mention classes and PaperProps but do not talk about them.
My questions therefore are,
How do I centre the buttons which by default are aligned at the right?
Also, how do I change the backdrop color which is initially grey?

Material-ui Dialog also inherits ModalComponent you can use the Props of Modal to change the Backdrop color
Modal API Description
Button in DialogActions are by default justified to flex-end. You can override this behaviour using classes property
const styles = {
backdrop: {
backgroundColor: blue[100],
color: blue[600],
},
action:{
justifyContent:'inherit',
}
};
<Dialog
BackdropProps={{
classes: {
root: classes.backdrop,
}
}}
{...other}/>
<DialogActions
className={classes.action}>

you can use Grid to align your content, in this case your buttons as described in here: https://material-ui.com/layout/grid/
you can use BackdropProps to change backdrop values. use: https://material-ui.com/api/dialog/
(it clearly says: The properties of the Modal component are also available. You can take advantage of this behavior to target nested components)
so the final outcome will be:
<Dialog
onClose={this.handleClose}
{...other}
BackdropProps={{
classes: {
root: classes.root
}
}}
PaperProps={{
style: {
minHeight: "75vh",
minWidth: "75vw"
}
}}
aria-labelledby="open-dialog-title"
aria-describedby="open-dialog-description"
>
<DialogTitle id="open-dialog-title">title</DialogTitle>
<DialogContent>
<DialogContentText id="open-dialog-description">
content
</DialogContentText>
</DialogContent>
<DialogActions>
<Grid container justify="center">
<Grid item>
<Button variant="raised" color="primary">
test
</Button>
</Grid>
</Grid>
</DialogActions>
</Dialog>
here is a working example : https://codesandbox.io/s/10vxmwqy7
hope this will help you.

Related

How to align a Button to the far right in MUI AppBar?

I'm having trouble understanding how to align items in MUI. I have the following code:
class SignUpForm extends React.Component {
render() {
return (
<Button sx={{ justifyContent: "flex-end" }}
color="inherit" }>Sign Up</Button>
)
}
}
which is composed by:
class Nav extends React.Component {
render() {
return (
<Box sx={{ flexGrow: 1}}>
<AppBar position="static">
<Toolbar>
<SignUpForm />
</Toolbar>
</AppBar>
</Box>
)
}
}
But unfortunately the content is still staying to the left. Using this resource https://mui.com/system/properties, I might be missing an important CSS concept here. Could anyone enlighten me?
Thank you.
Toolbar is a flexbox, so you can add a div on the left side and set justify-content to space-between to push the Button to the right:
<Toolbar sx={{ justifyContent: "space-between" }}>
<div />
<SignUpForm />
</Toolbar>
I'm pretty sure you just need to change sx={{ justifyContent: "flex-end" }} to sx={{ marginLeft: "auto" }} on the Button
Might help someone in the future, if you also include where you're importing your components from. Personally, when I encountered the sx not working (realized this was the issue because when I inspected the element says sx=[Object object]), it's because I should've been importing Toolbar from #mui/material, see this reference. Also, I'm using #mui/material v 5.10.11. PS. I'm using Auto-import extension on VSCode, hence, the incorrect import from cause.

Material-UI Dropdown overflowed in Dialog

I'm trying to use a dropdown select inside of a Dialog (modal). However, the options get cut off by the bottom of the modal.
How can I get the options to continue further down past the bottom border?
I'm using MUI v5.
<Dialog open={open}>
<DialogContent>
<Autocomplete
disablePortal
id="combo-box-demo"
options={options}
// getOptionLabel={(option) => option}
sx={{ width: 300 }}
renderInput={(params) => <TextField {...params} label="Numbers" />}
/>
</DialogContent>
</Dialog>
(extreme) example: Code Sandbox
Remove or set the disablePortal prop to false in your Autocomplete. If you use portal in the dropdown list. The dropdown's real DOM element will be attached outside of the Dialog hierarchy (you can use inspect element to confirm it), so its size isn't constrained by the layout of the dialog.

Apply style to ButtonBase in a Tab component

I am trying to figure out Material UI style overriding with a nested component. Say I want to increase bottom border height on a active Tab. This border is applied by the underlying ButtonBase.
Here is the style definition:
const useStyles = makeStyles(theme => ({
root: {
// an example brutal overriding, not clean, I'd like a better approach for the button
"& .MuiSvgIcon-root": {
marginRight: "8px"
}
},
// override Tab
tabWrapper: {
flexDirection: "row"
},
tabSelected: {
color: theme.palette.primary.main
},
tabLabelIcon: theme.mixins.toolbar, // same minHeight than toolbar
// TODO override buttonBase ???
// ...
}));
An example usage:
<Tab
value="/"
classes={{
wrapper: classes.tabWrapper,
selected: classes.tabSelected,
labelIcon: classes.tabLabelIcon
}}
icon={
<React.Fragment>
<DashboardIcon />
</React.Fragment>
}
label="Home"
// TODO: is this the expected syntax? TypeScript is not happy with this prop...
buttonBaseProps={{ classes: {} }}
/>
I have no idea how to define the ButtonBase classes in this example.
How should I define my props to override the ButtonBase style?
Edit: doc is here https://material-ui.com/api/tab/, the last section describe the inheritance process but the documentation is very terse.
Edit 2: the example use case is bad as you should override ".MuiTabs-indicator" to increase the bottom border height (it's actually an additional span not a border) but the question stands. Imagine that I want to change the ButtonBase background-color for example.
So as it turns out, There is no separate ButtonBase component inside the Tab component. So you won't find prop called buttonBaseProps. The tab itself is rendered as the button component.
Whatever style you wanna pass, pass it to the root inside classes. See below
<Tab classes={{
root: classes.customButtonBaseRoot,
wrapper: classes.tabWrapper,
selected: classes.tabSelected,
labelIcon: classes.tabLabelIcon
}}
/>
https://codesandbox.io/s/apply-style-to-buttonbase-in-a-tab-component-izgj5

how to assign color to helperText material ui to highlight error in TextField

How to assign a color to helperText material-UI to highlight the error in TextField.I am unable to set the color to helperText in material-UI.
I tried to use MuiFormHelperText-root-406 to apply CSS
but it does not work
<Grid item xs={3}>
<TextField
label="EmailId"
name="emailId"
value={editItem.emailId}
onChange={this.editInputValue}
helperText={this.state.emailerror} />
</Grid>
.MuiFormHelperText-root-406{
color:rgba(255,0,0,0.5);
}
Add this code: add className={classes.textField} in TextField
textField: {
marginLeft: theme.spacing(1),
marginRight: theme.spacing(1),
width: 200,
'& p':{
color:'blue',
},
},
<TextField
id="standard-helperText"
label="Helper text"
defaultValue="Default Value"
className={classes.textField}
helperText="Some important text"
margin="normal"
/>
#arpita-patel's answer is correct but you should know that you can also just add this to your CSS:
.MuiFormHelperText-root {
color:rgba(255,0,0,0.5);
}
Or do it based on the parent:
.MuiTextField-root p {
color:rgba(255,0,0,0.5);
}
Each of the above worked for me. I am using Material UI 4.0.2
The best way which I found to style the helperText for the TextField component is similar to the way presented by Arpita Patel.
The only difference is that I am using the attribute classes instead of className as it has been described in Material-UI docs here
You can find there that TextField component can use only one CSS rule name called root (global class is called .MuiTextField-root).
So basically you need to use the below code to style helperText as you like:
JSX (based on your initial code example)
const classes = useStyles();
<TextField
label="EmailId"
name="emailId"
value={editItem.emailId}
onChange={this.editInputValue}
helperText={this.state.emailerror}
classes={{root: classes.textField}}
/>
STYLE via makeStyles
import { makeStyles } from '#material-ui/core/styles';
const useStyles = makeStyles((theme) => ({
textField: {
'& p':{
/* your style for helperText here*/
}
}
})
If #ange-loron's answer didn't work, try to add !important :
.MuiFormHelperText-root {
color: rgba(255,0,0,0.5) !important;
}

How can I imitate the look of the outline and label from Material-UI's outlined textfield?

I'm trying to imitate the outlined textfield from Material-UI but I don't know how to hide the border behind the title text.
In the below image, notice how the "Due Date/Time" is taken from the Material-UI library and the title hides the border behind it but when I tried to imitate it with a custom component I just couldn't hide the border.
Alternatively, Is there a better way to use this outline design instead of just implementing it with CSS?
My current component looks liks this:
<div style={inputContainerStyle}>
<div style={{
...titleStyle,
transform: 'translate(-43px, -11px) scale(0.75)',
fontSize: '17px',
color: 'rgba(0, 0, 0, 0.54)',
position: 'absolute',
}}
>
Color
</div>
<div
className="flex-row"
style={{
border: '1px solid rgba(0, 0, 0, 0.23)',
padding: '18.5px 14px',
borderRadius: '4px',
}}
>
{
availableColors.map(color => <div style={colorCircleStyle(color)} />)
}
</div>
</div>
UPDATE
For many scenarios, my later answer (which avoids using TextField and therefore has no side-effects on FormControl context) may be more appropriate: How can I set an static outlined div similar to Material-UI's outlined textfield?
There is a great deal of flexibility in what you can do with TextField. TextField supports plugging in different types of inputs (e.g. Select, input, custom pickers) via the inputComponent property. You could leverage this to put anything inside its labelled outline by creating a custom component like this OutlinedDiv:
import React from "react";
import TextField from "#material-ui/core/TextField";
const InputComponent = ({ inputRef, ...other }) => <div {...other} />;
const OutlinedDiv = ({ children, label }) => {
return (
<TextField
variant="outlined"
label={label}
multiline
InputLabelProps={{ shrink: true }}
InputProps={{
inputComponent: InputComponent
}}
inputProps={{ children: children }}
/>
);
};
export default OutlinedDiv;
The className passed to the inputComponent takes care of the CSS that makes this all work. You can then use this like in the following:
import React from "react";
import ReactDOM from "react-dom";
import OutlinedDiv from "./OutlinedDiv";
import Avatar from "#material-ui/core/Avatar";
import deepOrange from "#material-ui/core/colors/deepOrange";
import deepPurple from "#material-ui/core/colors/deepPurple";
import red from "#material-ui/core/colors/red";
import green from "#material-ui/core/colors/green";
import blue from "#material-ui/core/colors/blue";
import Grid from "#material-ui/core/Grid";
function App() {
return (
<div className="App">
<OutlinedDiv label="Color Picker">
<Grid container justify="center" alignItems="center">
<Avatar style={{ backgroundColor: deepOrange[500] }} />
<Avatar style={{ backgroundColor: deepPurple[500] }} />
<Avatar style={{ backgroundColor: red[500] }} />
<Avatar style={{ backgroundColor: green[500] }} />
<Avatar style={{ backgroundColor: blue[500] }} />
</Grid>
</OutlinedDiv>
<br />
<br />
<OutlinedDiv label="Custom Outlined Thing">
You can put whatever you want in here.
</OutlinedDiv>
</div>
);
}
const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);
No need to write Outlined div component and all. As we can achieve this using FormControl, FormLabel and Formgroup.
If you follow the Outlined div logic your input fields will lose focus.
The below solution is very easy and quick you just need to wrap your code:
<FormControl component="fieldset" className="fieldset">
<FormLabel component="Legend">Title</FormLabel>
<FormGroup row>
{/*Your Input fields e.g TextField or Select e.t.c*/}
</FormGroup>
</FormControl>
Now using useStyles apply some css:
fieldset: {
width: '100%',
marginBottom: 10,
padding: 10,
border: '1px solid #ddd',
borderRadius: 5
}
The outlined textfield was really tricky to implement. When pushing that feature, we had to consider several options, each with their own drawbacks
SVG Element
Easy to build and animate, but tough to scale with the surrounding elements. If we had gone this route, we would have needed to listen for some type of resize event, which would mean either using a window resize event, which is not robust, or using a newer and less supported feature such as a ResizeObserver/MutationObserver. There are polyfills, but that would have increased the bundle size about 2K for a relatively small feature.
The SVG route is likely what will be used in the future. It is also worth noting that this is how Google's Material Components Web solves the problem.
Plain old border with a background on the label
This is by far the simplest approach, but it is also somewhat inflexible. You can see an example of this in Google's new sign-in flow. There they actually set the background color to white. This is probably a fine approach for plenty of users, but of course won't work if your background is a gradient or some similar edge case. That said, there's no need to worry about resize because it's just a border.
Fieldset and legend
This is what we ended up going with, largely because of its flexibility for end users. Fieldset and its legend component are both built-in ways of attaining pretty much this exact functionality. The big drawbacks to this are that styling across browsers is tough, and the properties we'd be animating on are not performant, such as legend width. Additionally, it's always best to use semantic HTML of course, which this is not, which means we need to use aria-hidden to instruct screen readers to ignore the element.
Depending on your goals, any one of these solutions may work best for you. Beware that getting the perfect solution that solves all of these problems may be very tricky!
Just apply the same background color on the color div as the parent's background color, you can do it by background-color: inherit like this:
<div style={inputContainerStyle}>
<div style={{
...titleStyle,
transform: 'translate(-43px, -11px) scale(0.75)',
fontSize: '17px',
color: 'rgba(0, 0, 0, 0.54)',
position: 'absolute',
background-color:'inherit' **(just add this line)**
}}
>
Color
</div>
<div
className="flex-row"
style={{
border: '1px solid rgba(0, 0, 0, 0.23)',
padding: '18.5px 14px',
borderRadius: '4px',
}}
>
{
availableColors.map(color => <div style={colorCircleStyle(color)} />)
}
</div>
</div>

Resources