@mukhindev/mui-folding-menu
v1.0.2
Published
React folding menu MUI-based
Readme
@mukhindev/mui-folding-menu
Складываемое меню для React c использованием MUI
Пример использования
import { useEffect, useMemo, useRef } from "react";
import FoldingMenu, {
FoldingMenuItem,
FoldingMenuProvider,
FoldingMenuRef,
} from "@mukhindev/mui-folding-menu";
import { Button, Container } from "@mui/material";
import {
CategoryOutlined,
FavoriteOutlined,
PersonOutlined,
} from "@mui/icons-material";
export default function App() {
const ref = useRef<FoldingMenuRef>(null);
// Управление состоянием меню снаружи
useEffect(() => {
// Окрыть полный путь до элемента (раскрыв все children по пути)
ref.current?.openPathToMenuItem("2.1");
// Пометь элемент как активный
ref.current?.setActiveMenuItemId("2.1");
setTimeout(() => {
ref.current?.setActiveMenuItemId("4");
}, 7500);
}, [ref]);
// Составляем меню
const menu = useMemo<FoldingMenuItem[][]>(() => {
return [
[
// Ссылка (id будем использовать как ссылку)
{
id: "https://mukhin.dev",
icon: <FavoriteOutlined />,
label: "Первый пункт ссылка",
},
// Папка
{
id: "2",
label: "Папка",
children: [
// По onClick в extendButton понимаем, что не надо превращать в ссылку
{
id: "2.1",
icon: <PersonOutlined />,
label: "Сын",
onClick: () => console.log("Я сын"),
},
{
id: "2.2",
icon: <PersonOutlined />,
label: "Дочь",
onClick: () => console.log("Я дочь"),
},
],
},
// Асинхронно получаем папку (также можно получать элемент и даже элементы)
{
id: "3",
label: "Загрузка папки...",
loader: () =>
new Promise((resolve) => {
setTimeout(() => {
resolve({
id: "3...",
label: "Папка получена асинхронно",
children: [
{
id: "3.1",
icon: <PersonOutlined />,
label: "Вложено в папку 1",
onClick: () => console.log("3.1"),
},
{
id: "3.2",
icon: <PersonOutlined />,
label: "Вложено в папку 2",
onClick: () => console.log("3.2"),
},
],
});
}, 5000);
}),
},
],
// Тут сам создастся разделитель
[
// Проверяем, что длинный текст подрежается с помощью ...
{
id: "4",
icon: <CategoryOutlined />,
color: "success",
label:
"Пункт с каким-то ну нереально длинным названием в меню зачем-то",
onClick: () => console.log("Я id: 3, по мне кликнули"),
},
],
// Тут сам создастся разделитель
[
// Выводим полностью произвольный пункт (не будет даже <li> обёртки)
{
id: "5",
render: ({ item }) => <div>Что-то произвольное (id: {item.id})</div>,
},
],
];
}, []);
return (
<Container
sx={{
display: "flex",
flexDirection: "column",
p: 4,
gap: 3,
maxWidth: 400,
}}
>
{/** Провайдер нужен для старых проектов, где не получится стабилизировать состояние меню */}
<FoldingMenuProvider>
<FoldingMenu
ref={ref}
menu={menu}
extendButton={(item) =>
// Если элемент не содержит children и onClick ...
!("children" in item || "onClick" in item) && (
// То расширять кнопку до ссылки
<Button component="a" href={item.id} target="_blank" />
)
}
/>
</FoldingMenuProvider>
</Container>
);
}
TODO
- [ ] Поддержка
openPathToMenuItemдля асинхронных элементов меню - [ ] Сделать возможным работу без FoldingMenuProvider (нельзя его просто убрать просто так, он нужен для старых проектов, где не получится стабилизировать состояние меню)
