How to change the position of material-ui's dialog? - reactjs

Using material-ui in my react app, is there a way I can change the position when the dialog is opened? now it's always centered.
Thanks in advance!

You can create styles and pass it through classes prop. Here is an example of how you could do that.
import React from 'react';
import { makeStyles, Dialog } from '#material-ui/core';
const useStyles = makeStyles({
dialog: {
position: 'absolute',
left: 10,
top: 50
}
});
function Example() {
const classes = useStyles();
return (
<Dialog
classes={{
paper: classes.dialog
}}
/* rest of the props */
>
{/* content of the dialog */}
</Dialog>
);
}

I would say don't use position: absolute, it could break the scrolling behavior. The position was control differently with scroll='paper' or scroll='body'
You can use the following code to always align your dialog to the top of the page with two custom classes.
Demo: codesandbox.io
See the original article with explanation
const useStyles = makeStyles({
topScrollPaper: {
alignItems: 'flex-start',
},
topPaperScrollBody: {
verticalAlign: 'top',
},
})
function SimpleDialog(props: SimpleDialogProps) {
const classes = useStyles()
return (
<Dialog
onClose={handleClose}
aria-labelledby="simple-dialog-title"
open={open}
scroll="paper"
classes={{
scrollPaper: classes.topScrollPaper,
paperScrollBody: classes.topPaperScrollBody,
}}
></Dialog>
)
}

For MUI 5, we can use both SxProps and styled() utility:
Via SxProps:
// flex-start: to position it at the top
// flex-end: to position it at the bottom
// center: to position it at the center
const sx: SxProps = {
"& .MuiDialog-container": {
alignItems: "flex-start"
}
};
<Dialog
open={infoModalOpen}
onClose={() => setInfoModalOpen(false)}
sx={sx}
scroll="paper"
>
....
</Dialog>
Via styled components:
const StyledDialog = styled(Dialog)(({theme}) => ({
"& .MuiDialog-container": {
alignItems: "flex-start"
}
}));
<StyledDialog
open={infoModalOpen}
onClose={() => setInfoModalOpen(false)}
sx={sx}
scroll="paper"
>
....
</StyledDialog>

#radovix's and #Sumit Wadhwa's answers are correct. In case you don't want to use makeStyles, Here is how I resolved it.
When scroll="body";
<Dialog
fullWidth
onClose={() => setOpen(false)}
open={true}
scroll="body"
PaperProps={{ sx: { mt: "50px", verticalAlign: "top" } }}
>
{/* Dialog Content here */}
</Dialog>;
When scroll="paper";
<Dialog
fullWidth
onClose={() => setOpen(false)}
open={true}
scroll="paper"
sx={{
"& .MuiDialog-container": {
alignItems: "flex-start",
},
}}
PaperProps={{ sx: { mt: "50px" } }}
>
{/* Dialog Content here */}
</Dialog>;
You can adjust the margin-top however you like

Related

Can I Change Box background color on click in material ui with typescript?

I want to change the background color of my Box whenever it is clicked.
OOTB i couldn't find something which could help my use case.
SO, I tried using events onClick but couldn't find the right event which could bring info on selected event and allow me to change the styling value.
Use Case -
i am creating multiple box dynamically and at once only one Box could be highlighted
{allSports !== null &&
allSports?.map((sports) => (
<Grid
item
xs={4}
sx={{ mx: "auto", my: 1, minWidth: "80%" }}
onClick={backgroundChange}
>
<Item
// onClick={() => sportChoose(sports)}
>
<Box sx={{ display: "flex", justifyContent: "space-evenly" }}>
<Box>
<img
src={
require(`../../../../../resources/images/sportsIcons/${sports.icon}`)
.default
}
/>
</Box>
<Box sx={{ m: "auto" }}>
<Typography variant="h6">{sports.name}</Typography>
</Box>
</Box>
</Item>
</Grid>
))}
import { FC, ReactElement, useState } from 'react'
import { Box } from '#mui/material'
export const MuiCard: FC = (): ReactElement => {
const [clicked, setClicked] = useState(false)
const toggleClicked = () => setClicked((prev) => !prev)
return (
<Box
component="div"
onClick={toggleClicked}
sx={{ height: 20, backgroundColor: clicked ? 'red' : 'white' }}
/>
)
}

React Material UI custom tooltip AND speed dial style

I'm trying to customize the tooltip appearance and the position of the speed dial but get an error when doing both.
const useStyles = makeStyles((theme) => ({
root: {
height: 380,
transform: "translateZ(0px)",
flexGrow: 1,
},
speedDial: {
position: "absolute",
bottom: theme.spacing(2),
right: theme.spacing(0),
},
tooltip: {
backgroundColor: "#37517e",
fontSize: "1.1em",
},
}));
<SpeedDial
ariaLabel="Tutor SpeedDial"
className={classes.speedDial}
icon={<SpeedDialIcon openIcon={<EditIcon />} />}
onClose={handleClose}
onOpen={handleOpen}
open={open}
>
{actions.map((action) => (
<SpeedDialAction
key={action.name}
icon={action.icon}
tooltipTitle={action.name}
TooltipClasses={classes}
onClick={handleClose}
/>
))}
</SpeedDial>
The code actually compiles and works but I get a console error
index.js:1 Material-UI: The key speedDial provided to the classes prop is not implemented in ForwardRef(Tooltip).
You can only override one of the following: popper,popperInteractive,popperArrow,tooltip,tooltipArrow,arrow,touch,tooltipPlacementLeft,tooltipPlacementRight,tooltipPlacementTop,tooltipPlacementBottom.
It's pretty clear that the issue is because ToolTipClasses cannot override the speedDial class but I'm not sure how else to do it.
Any guidance will be much appreciated
Thanks
I came up with solution by by creating a StyledSpeedDial instead so that I could remove the speeddial onbject from the classes style
const StyledSpeedDial = styled(SpeedDial)(({ theme }) => ({
position: "absolute",
"&.MuiSpeedDial-directionUp, &.MuiSpeedDial-directionLeft": {
bottom: theme.spacing(2),
right: theme.spacing(0),
},
}));
<StyledSpeedDial
ariaLabel="Tutor SpeedDial"
icon={<SpeedDialIcon openIcon={<EditIcon />} />}
onClose={handleClose}
onOpen={handleOpen}
open={open}
>
{actions.map((action) => (
<SpeedDialAction
key={action.name}
icon={action.icon}
tooltipTitle={action.name}
TooltipClasses={classes}
onClick={handleClose}
/>
))}
</StyledSpeedDial>

How to set Material UI Fab to Outline

Is there a way to use the outline variant for the fab button in material ui
<Fab variant="here i see rounded || extended" color="primary" size="small" aria-label="scroll back to top">
<KeyboardArrowUp />
</Fab>
is there a way i could use the outline version and still inherit material ui ripple effect and other styles
As far as I know you cannot have outline version for that. But you can always write CSS for that. I had a simple demo for this
Edit: here are the code
const useStyles = makeStyles((theme: Theme) =>
createStyles({
root: {
"& > *": {
margin: theme.spacing(1)
}
},
fabStyle: {
backgroundColor: "white",
color: theme.palette.primary.light,
borderColor: theme.palette.primary.light,
"&:hover": {
backgroundColor: theme.palette.primary.light,
color: "white"
}
}
})
);
export default function FloatingActionButtons() {
const classes = useStyles();
return (
<div className={classes.root}>
<Fab color="primary" aria-label="add" className={classes.fabStyle}>
<AddIcon />
</Fab>
</div>
);
}
You should be able to inject classes into the Fab component. You can refer to this link for more information Customizing Components
<Fab
classes={{
root: classes.root, // class name, e.g. `classes-nesting-root-x`
label: classes.label, // class name, e.g. `classes-nesting-label-x`
}}
variant="here i see rounded || extended" color="primary" size="small" aria-label="scroll back to top">
<KeyboardArrowUp />
</Fab>

Displaying arrow to popover in material UI

Is it possible to add arrow to material UI popover component?
Thanks,
I think this is what you want (Without using popper Component)
You will need to override background color of Popover's child component i.e. paper with transparent color;
Using psudo element of Box Component to create an arrow element.
import * as React from "react";
import Popover from "#mui/material/Popover";
import Typography from "#mui/material/Typography";
import Button from "#mui/material/Button";
import Box from "#mui/material/Box";
export default function BasicPopover() {
const [anchorEl, setAnchorEl] = React.useState(null);
const handleClick = (event) => {
setAnchorEl(event.currentTarget);
};
const handleClose = () => {
setAnchorEl(null);
};
const open = Boolean(anchorEl);
const id = open ? "simple-popover" : undefined;
return (
<div style={{ width: 400, height: 200, backgroundColor: "lightblue" }}>
<Button aria-describedby={id} variant="contained" onClick={handleClick}>
Open Popover
</Button>
<Popover
id={id}
open={open}
anchorEl={anchorEl}
onClose={handleClose}
anchorOrigin={{
vertical: "bottom",
horizontal: "left"
}}
PaperProps={{
style: {
backgroundColor: "transparent",
boxShadow: "none",
borderRadius: 0
}
}}
>
<Box
sx={{
position: "relative",
mt: "10px",
"&::before": {
backgroundColor: "white",
content: '""',
display: "block",
position: "absolute",
width: 12,
height: 12,
top: -6,
transform: "rotate(45deg)",
left: "calc(50% - 6px)"
}
}}
/>
<Typography sx={{ p: 2, backgroundColor: "white" }}>
The content of the Popover.
</Typography>
</Popover>
</div>
);
}
Here is working Demo: basic Popover With Arrow
If you'd like to use a Popper instead, then the following sandbox has a component you should be able to copy straight into your codebase (typescript): RichTooltip. The standard Tooltip was not that suited to rich content for our project and did not allow buttons, selecting text, etc.
https://codesandbox.io/s/popper-with-arrow-58jhe
If you want arrow to a button which open popover you can just put html for arrow there.
<Button aria-describedby={id} variant="contained" color="primary" onClick={handleClick}>
Open Popover <img src="//path-for-arrow-image" />
</Button>
<Popover {...propsOfPopover}> {children} </Popover>

How to display a modal inside a parent container

I have a small sub-window like div in my app, and I need to display a modal inside the sub-window instead of the whole viewport.
So the backdrop of the modal should only cover the sub-window and not the entire screen
I am using material-ui, so any solution native to material-ui is preferred.
Add disablePortal prop to <Dialog> and add styles as given in the code snippet
For some reason the styles applied to root didn't work through classes or className so had to add the style prop
import { makeStyles, DialogContent, Dialog } from '#material-ui/core';
import React from 'react';
const useStyles = makeStyles({
root: {
position: 'absolute',
},
backdrop: {
position: 'absolute',
},
});
interface ISubWindow {
onClose: () => void;
open: boolean;
}
const SubWindow: React.FC<ISubWindow> = ({onClose, open}) => {
const classes = useStyles();
return (
<Dialog
disablePortal
onClose={onClose}
open={open}
fullWidth
className={classes.root}
classes={{
root: classes.root,
}}
BackdropProps={{
classes: { root: classes.backdrop },
}}
style={{ position: 'absolute' }}
>
<DialogContent />
</Dialog>
);
};
export default SubWindow;
#Rahul's example got me most of the way, but it didn't quite work until I combined it with #Scott Sword and #Gretchen F. 's answers from this similar question.
The most important part was setting the position property of the parent div to relative though I also passed in props slightly differently which has worked a little easier for me:
import { makeStyles, DialogContent, Dialog } from '#material-ui/core';
import React from 'react';
const useStyles = makeStyles({
root: {
height: 'max-content',
minHeight: '100%',
},
backdrop: {
position: 'absolute',
},
paperScrollPaper: {
overflow: 'visible',
}
});
interface ISubWindow {
onClose: () => void;
open: boolean;
}
const SubWindow: React.FC<ISubWindow> = ({onClose, open}) => {
const classes = useStyles();
return (
<Dialog
disableAutoFocus//disables rescrolling the window when the dialog is opened
disableEnforceFocus//allows user to interact outside the dialog
disableScrollLock//prevents the div from shrinking to make room for a scrollbar
disablePortal
onClose={onClose}
open={open}
fullWidth
className={classes.root}
classes={{
paperScrollPaper: classes.paperScrollPaper
}}
BackdropProps={{
classes: { root: classes.backdrop },
}}
style={{ position: 'absolute' }}
>
<DialogContent />
</Dialog>
);
};
export default SubWindow;
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>

Resources