91 lines
2.5 KiB
TypeScript

import { HomeOutlined, LeftOutlined, RightOutlined } from '@ant-design/icons';
import { Divider, Layout, Tooltip } from 'antd';
import { type ReactNode, memo, useState } from 'react';
import { NavLink } from 'react-router-dom';
import styles from './styles.module.css';
type NavItem = {
link: string;
label: string;
icon: ReactNode;
};
type Group = {
title: string;
key: string;
children: NavItem[];
};
// Каркас: разделы меню — по карте экранов docs/context/10-user-journey.md, добавляются срезами.
const config: Group[] = [
{
title: 'Главная',
key: 'home',
children: [{ link: '/', icon: <HomeOutlined />, label: 'Главная' }],
},
];
function CollapsedIcon({ icon, title, to }: { icon: ReactNode; title: string; to: string }) {
return (
<Tooltip placement='right' title={title}>
<NavLink to={to} className={({ isActive }) => `${styles.iconBtn} ${isActive ? styles.iconBtnActive : styles.iconBtnNav}`}>
{icon}
</NavLink>
</Tooltip>
);
}
function NavLinkStyled({ to, children }: { to: string; children: ReactNode }) {
return (
<NavLink className={({ isActive }) => `${styles.linkBase} ${isActive ? styles.linkActive : ''}`} to={to}>
{children}
</NavLink>
);
}
const Section = memo(function Section({ isCollapsed, group }: { isCollapsed: boolean; group: Group }) {
return !isCollapsed ? (
<div className={styles.section}>
<div className={styles.sectionTitle}>{group.title}</div>
{group.children.map((i) => (
<NavLinkStyled key={i.link} to={i.link}>
{i.icon}
{i.label}
</NavLinkStyled>
))}
<Divider size='small' />
</div>
) : (
<>
{group.children.map((i) => (
<CollapsedIcon key={i.link} icon={i.icon} to={i.link} title={i.label} />
))}
</>
);
});
export function Sidebar() {
const [isCollapsed, setIsCollapsed] = useState(false);
return (
<Layout.Sider
collapsed={isCollapsed}
style={{ height: 'auto', margin: '10px', borderRadius: 10 }}
width={280}
collapsedWidth={64}
collapsible
trigger={null}>
<div className={`${styles.wrapper} ${isCollapsed ? styles.wrapperCollapsed : ''}`}>
<div className={styles.topbar}>
<button type='button' className={styles.collapseBtn} onClick={() => setIsCollapsed(!isCollapsed)}>
{isCollapsed ? <RightOutlined /> : <LeftOutlined />}
</button>
</div>
{config.map((g) => (
<Section key={g.key} group={g} isCollapsed={isCollapsed} />
))}
</div>
</Layout.Sider>
);
}