Drawer в MUI — это компонент для создания боковых панелей и навигационных меню. Он может появляться слева, справа, сверху или снизу экрана и поддерживает как временное, так и постоянное отображение. Основные варианты Drawer:
Простейший пример Drawer с временным отображением:
import * as React from 'react';
import Drawer from '@mui/material/Drawer';
import Button from '@mui/material/Button';
import List from '@mui/material/List';
import ListItem from '@mui/material/ListItem';
import ListItemText from '@mui/material/ListItemText';
export default function TemporaryDrawer() {
const [open, setOpen] = React.useState(false);
const toggleDrawer = (state) => () => {
setOpen(state);
};
const list = () => (
<List>
{['Главная', 'Профиль', 'Настройки'].map((text) => (
<ListItem button key={text}>
<ListItemText primary={text} />
</ListItem>
))}
</List>
);
return (
<div>
<Button onCl ick={toggleDrawer(true)}>Открыть меню</Button>
<Drawer anchor="left" open={open} onCl ose={toggleDrawer(false)}>
{list()}
</Drawer>
</div>
);
}
Anchor определяет сторону экрана, откуда появляется Drawer:
"left" — слева."right" — справа."top" — сверху."bottom" — снизу.<Drawer anchor="right" open={open} onCl ose={toggleDrawer(false)}>
{list()}
</Drawer>
Ширина и стили регулируются через sx
или PaperProps:
<Drawer
anchor="left"
open={open}
onCl ose={toggleDrawer(false)}
PaperProps={{
sx: { width: 300, backgroundColor: '#f0f0f0' }
}}
>
{list()}
</Drawer>
Permanent Drawer всегда на экране, поэтому содержимое страницы сдвигается. Настройка:
<Drawer
variant="permanent"
sx={{
width: 240,
flexShrink: 0,
'& .MuiDrawer-paper': { width: 240, boxSizing: 'border-box' }
}}
>
{list()}
</Drawer>
Persistent Drawer позволяет скрывать панель, но оставляет пространство для сдвига контента:
<Drawer
variant="persistent"
anchor="left"
open={open}
sx={{
width: 240,
flexShrink: 0,
'& .MuiDrawer-paper': { width: 240, boxSizing: 'border-box' }
}}
>
{list()}
</Drawer>
Триггер для открытия/закрытия может быть реализован кнопкой:
<Button onCl ick={() => setOpen(!open)}>
{open ? 'Закрыть меню' : 'Открыть меню'}
</Button>
Drawer автоматически поддерживает анимацию появления. Для временных панелей ключевые события:
onOpen — вызывается при открытии.onClose — вызывается при закрытии.Для дополнительной анимации содержимого можно использовать
Slide или Collapse внутри Drawer:
import Slide from '@mui/material/Slide';
<Slide direction="right" in={open}>
<div>Содержимое с анимацией</div>
</Slide>
Drawer удобно использовать с List и
ListItem, поддерживая вложенные элементы через
ListItemButton и Collapse:
import Collapse from '@mui/material/Collapse';
import ExpandLess from '@mui/icons-material/ExpandLess';
import ExpandMore from '@mui/icons-material/ExpandMore';
const [openSubMenu, setOpenSubMenu] = React.useState(false);
<List>
<ListItemButton onCl ick={() => setOpenSubMenu(!openSubMenu)}>
<ListItemText primary="Настройки" />
{openSubMenu ? <ExpandLess /> : <ExpandMore />}
</ListItemButton>
<Collapse in={openSubMenu} timeout="auto" unmountOnExit>
<List component="div" disablePadding>
<ListItemButton sx={{ pl: 4 }}>
<ListItemText primary="Профиль" />
</ListItemButton>
<ListItemButton sx={{ pl: 4 }}>
<ListItemText primary="Безопасность" />
</ListItemButton>
</List>
</Collapse>
</List>
При использовании Persistent или Permanent Drawer важно корректно управлять отступами основного контента, чтобы он не перекрывался панелью:
<Box sx={{ display: 'flex' }}>
<Drawer variant="persistent" open={open}>
{list()}
</Drawer>
<Box
component="main"
sx={{
flexGrow: 1,
p: 3,
transition: (theme) => theme.transitions.create('margin', {
easing: theme.transitions.easing.sharp,
duration: theme.transitions.duration.leavingScreen,
}),
marginLeft: open ? '240px' : '0',
}}
>
<Toolbar />
Основное содержимое страницы
</Box>
</Box>
MUI позволяет гибко настраивать Drawer через sx,
PaperProps и кастомные темы. Например, можно добавить тень,
скругления или градиент:
<Drawer
variant="temporary"
open={open}
onCl ose={toggleDrawer(false)}
PaperProps={{
sx: {
width: 280,
boxShadow: 3,
borderRadius: 2,
background: 'linear-gradient(180deg, #ffffff, #e0e0e0)'
}
}}
>
{list()}
</Drawer>
Для корректной навигации с клавиатуры и экранными читалками важно:
aria-label или
aria-labelledby для Drawer.onClose.role="presentation" для списков внутри Drawer
при временной панели.<Drawer
anchor="left"
open={open}
onCl ose={toggleDrawer(false)}
aria-label="Главное меню"
>
<Box role="presentation">
{list()}
</Box>
</Drawer>
Drawer может включать:
Collapse.AppBar и контентом.Это делает MUI Drawer мощным инструментом для построения удобных навигационных интерфейсов как на мобильных, так и на десктопных приложениях.