Technologies:
Tolerim
a month ago
'What is the method for placing the MUI icon button within the Drawer?'
I am currently building a dashboard layout using the MUI-5 drawer component. My aim is to position the open-close button of the drawer at the center-right corner. However, I am facing some issues with the implementation. Although I can place the icon at the center using absolute positioning, half the button gets hidden. Below is the current code implementation of the dashboard layout using MUI-5 drawer component:
To achieve the desired position, I have made changes to the code for the button's absolute positioning. By adding the `position: 'absolute'` and `right: '5px'` properties to the button style class, the button gets correctly positioned. You can check the modified code snippet below:
import { PropsWithChildren, useState } from 'react';
import { styled, useTheme, Theme, CSSObject } from '@mui/material/styles';
import Box from '@mui/material/Box';
import MuiDrawer from '@mui/material/Drawer';
import MuiAppBar, { AppBarProps as MuiAppBarProps } from '@mui/material/AppBar';
import Toolbar from '@mui/material/Toolbar';
import List from '@mui/material/List';
import CssBaseline from '@mui/material/CssBaseline';
import Typography from '@mui/material/Typography';
import Divider from '@mui/material/Divider';
import IconButton from '@mui/material/IconButton';
import MenuIcon from '@mui/icons-material/Menu';
import ChevronLeftIcon from '@mui/icons-material/ChevronLeft';
import ChevronRightIcon from '@mui/icons-material/ChevronRight';
import ListItem from '@mui/material/ListItem';
import ListItemButton from '@mui/material/ListItemButton';
import ListItemIcon from '@mui/material/ListItemIcon';
import ListItemText from '@mui/material/ListItemText';
import InboxIcon from '@mui/icons-material/MoveToInbox';
import MailIcon from '@mui/icons-material/Mail';
import { Grid, SvgIcon } from '@mui/material';
import Test from '../assets/Subtract.svg';
import Logo from '../assets/logo-dash.png';
const drawerWidth = 240;
const openedMixin = (theme: Theme): CSSObject => ({
width: drawerWidth,
transition: theme.transitions.create('width', {
easing: theme.transitions.easing.sharp,
duration: theme.transitions.duration.enteringScreen,
}),
overflowX: 'hidden',
});
const closedMixin = (theme: Theme): CSSObject => ({
transition: theme.transitions.create('width', {
easing: theme.transitions.easing.sharp,
duration: theme.transitions.duration.leavingScreen,
}),
overflowX: 'hidden',
width: `calc(${theme.spacing(7)} + 1px)`,
[theme.breakpoints.up('sm')]: {
width: `calc(${theme.spacing(8)} + 1px)`,
},
});
const DrawerHeader = styled('div')(({ theme }) => ({
display: 'flex',
alignItems: 'center',
justifyContent: 'flex-end',
padding: theme.spacing(0, 1),
// necessary for content to be below app bar
...theme.mixins.toolbar,
}));
interface AppBarProps extends MuiAppBarProps {
open?: boolean;
}
const ExpandableDrawer = styled(Grid, {
shouldForwardProp: (prop) => prop !== 'open',
})<AppBarProps>(({ theme, open }) => ({
zIndex: theme.zIndex.drawer + 1,
transition: theme.transitions.create(['width', 'margin'], {
easing: theme.transitions.easing.sharp,
duration: theme.transitions.duration.leavingScreen,
}),
...(open && {
marginLeft: drawerWidth,
width: `calc(100% - ${drawerWidth}px)`,
transition: theme.transitions.create(['width', 'margin'], {
easing: theme.transitions.easing.sharp,
duration: theme.transitions.duration.enteringScreen,
}),
}),
}));
const Drawer = styled(MuiDrawer, {
shouldForwardProp: (prop) => prop !== 'open',
})(({ theme, open }) => ({
width: drawerWidth,
flexShrink: 0,
whiteSpace: 'nowrap',
boxSizing: 'border-box',
...(open && {
...openedMixin(theme),
'& .MuiDrawer-paper': openedMixin(theme),
}),
...(!open && {
...closedMixin(theme),
'& .MuiDrawer-paper': closedMixin(theme),
}),
}));
export default function DashboardDrawer({ children }: PropsWithChildren) {
const theme = useTheme();
const [open, setOpen] = useState(false);
const handleDrawerOpen = () => {
setOpen(true);
};
const handleDrawerClose = () => {
setOpen(false);
};
return (
<Box sx={{ display: 'flex' }}>
<CssBaseline />
<ExpandableDrawer open={open} />
<Drawer
variant="permanent"
open={open}
PaperProps={{
sx: {
backgroundColor: '#005248',
},
}}
>
<Grid container alignItems="center" justifyContent="center">
<Grid item className="my-4">
<img src={Logo} alt="" className="h-10" />
</Grid>
<Grid
item
container
justifyContent="center"
alignItems="center"
className="h-5 my-4 "
>
<Grid item xs={2}>
<IconButton
color="inherit"
aria-label="open drawer"
className="p-1"
onClick={handleDrawerOpen}
sx={{
marginRight: 5,
backgroundColor: theme.palette.secondary.main,
...(open && { display: 'none' }),
}}
>
<ChevronRightIcon className="text-sm" />
</IconButton>
<IconButton
color="inherit"
aria-label="open drawer"
className="p-1"
onClick={handleDrawerClose}
sx={{
'&:hover': { color: 'green' },
marginRight: 5,
backgroundColor: theme.palette.secondary.main,
position: 'absolute',
right: '5px',
}}
>
<ChevronLeftIcon className="text-sm" />
</IconButton>
</Grid>
</Grid>
<Grid item container>
<List>
{['Dashboard', 'Appointments', ' Checkout', 'Clients'].map(
(text, index) => (
<ListItem key={text} disablePadding sx={{ display: 'block' }}>
<ListItemButton
sx={{
minHeight: 48,
justifyContent: open ? 'initial' : 'center',
px: 2.5,
}}
>
<ListItemIcon
sx={{
minWidth: 0,
mr: open ? 3 : 'auto',
justifyContent: 'center',
}}
>
<MailIcon/>
</ListItemIcon>
<ListItemText
className="text-white"
primary={text}
sx={{ opacity: open ? 1 : 0 }}
/>
</ListItemButton>
</ListItem>
)
)}
</List>
</Grid>
</Grid>
</Drawer>
<Box component="main" sx={{ flexGrow: 1, p: 3 }}>
<DrawerHeader />
{children}
</Box>
</Box>
);
}
Here is an expected UI image that shows the desired position of the icon:

I hope this solves your issue. Let me know if you have any further questions.Answers(2)
Vogi
a month ago
Verified Answer
Hello! I see that you are building a dashboard layout using the MUI-5 drawer component and you are facing some issues with the implementation. I understand that you want to position the open-close button of the drawer at the center-right corner.
To achieve this, you can add the position: 'absolute' and right: '5px' properties to the button style class. This will correctly position the button. You can check the modified code snippet below:
<IconButton
color="inherit"
aria-label="open drawer"
className="p-1"
onClick={handleDrawerClose}
sx={{
'&:hover': { color: 'green'},
marginRight: 5,
backgroundColor: theme.palette.secondary.main,
position: 'absolute',
right: '5px'
}}
>
<ChevronLeftIcon className="text-sm" />
</IconButton>
I hope this helps. Let me know if you have any further questions.
Tolerim
a month ago
To achieve the expected UI as shown in the image, you can make use of flexbox to achieve the desired layout.
First, remove the absolute positioning used to center the icons and replace it with a flex container. Change the width of the container to 100% and set display property to flex. Next, use justify-content property to center the child elements horizontally and align-items property to center it vertically as shown:
.flex-container{
width: 100%;
display: flex;
justify-content: center;
align-items: center;
}
Then for the right icon use marginLeft: 'auto' to push the icon to the right side of its container as follows:
<Grid item container justifyContent="flex-end">
<IconButton
color="inherit"
aria-label="open drawer"
className="p-1"
onClick={handleDrawerClose}
sx={{
'&:hover': { color: 'green' },
backgroundColor: theme.palette.secondary.main,
}}
>
<ChevronLeftIcon className="text-sm" />
</IconButton>
</Grid>
And for the left icon use marginRight property to create space between the icon and the logo if needed.
<Grid item container justifyContent="flex-start" className="mt-auto">
<img src={Logo} alt="" className="h-10" />
<IconButton
color="inherit"
aria-label="open drawer"
className="p-1"
onClick={handleDrawerOpen}
sx={{
marginLeft: 'auto',
backgroundColor: theme.palette.secondary.main,
...(open && { display: 'none' }),
}}
>
<ChevronRightIcon className="text-sm" />
</IconButton>
</Grid>
This should give you your desired UI.