# SideNav

侧边导航组件，用于页面侧边栏的多级菜单导航。支持折叠、展开、链接跳转和反色模式。

## 适用场景

- 后台管理系统的侧边栏导航
- 多级菜单结构的页面导航（支持最多三层嵌套）
- 需要折叠/展开功能的侧边导航

## Props

### SideNav Props

| 名称 | 类型 | 默认值 | 必填 | 说明 |
|------|------|--------|------|------|
| className | `string` | `""` | 否 | 自定义 class |
| collapsed | `boolean` | `-` | 否 | 是否折叠控制值 |
| defaultCollapsed | `boolean` | `false` | 否 | 是否折叠默认值 |
| onChangeCollapsed | `(collapsed: boolean) => void` | `-` | 否 | 是否折叠的变化回调 |
| submenuPopperPortalContainer | `HTMLElement \| (() => HTMLElement)` | `-` | 否 | 指定 menuPopper 的 popup portal 挂载容器（默认 `document.body`） |
| reverseColor | `boolean` | `false` | 否 | 使用反色，适用于深色背景 |
| onChangeSelectedIds | `(selectedIds: MenuItemId[]) => void` | `-` | 否 | selectedIds 变化时的回调（select/deselect 均会调用） |
| onChangeExpandedIds | `(expandedIds: MenuItemId[]) => void` | `-` | 否 | expandedIds 变化时的回调（expand/collapse 均会调用） |
| menu | `SideNavMenuItemObject[]` | `-` | 否 | 菜单数据 |
| menuSelectedIds | `MenuItemId[]` | `-` | 否 | menu 已选择的 id 列表控制值 |
| menuDefaultSelectedIds | `MenuItemId[]` | `-` | 否 | menu 已选择的 id 列表默认值 |
| menuExpandedIds | `MenuItemId[]` | `-` | 否 | menu 已展开的 submenu id 列表控制值 |
| menuDefaultExpandedIds | `MenuItemId[]` | `-` | 否 | menu 已展开的 submenu id 列表默认值 |

### SideNavMenuItemObject Props

| 名称 | 类型 | 默认值 | 必填 | 说明 |
|------|------|--------|------|------|
| id | `MenuItemId` | `-` | 否 | 唯一标识 |
| label | `ReactNode` | `-` | 是 | 显示内容 |
| disabled | `boolean` | `-` | 否 | 是否禁用 |
| icon | `SvgFC` | `-` | 否 | icon，只支持第一层有 icon |
| href | `string` | `-` | 否 | 链接地址，label 将 wrap 在 `<a />` 元素内 |
| target | `string` | `-` | 否 | `<a />` 的 target |
| title | `string` | `-` | 否 | title tip |
| onClick | `MouseEventHandler<Element>` | `-` | 否 | 点击回调 |
| type | `"group" \| "folder" \| "popper"` | `-` | 否 | submenu 类型 |
| selected | `boolean` | `-` | 否 | 是否选中 |
| expanded | `boolean` | `-` | 否 | submenu 是否展开 |
| children | `MenuItemObject[]` | `-` | 否 | 子项 |

## 典型用法

### 基础用法

```tsx
import { SvgAppsDown, SvgCalendar } from '@befe/brick-icon'
import { SideNav } from '@befe/brick'

const menu = [
    {
        id: '1',
        label: '我的工作台',
        icon: SvgAppsDown,
        children: [
            { id: '11', label: '工作台1', href: 'https://www.baidu.com', target: '_blank' },
            { id: '2', label: '工作台2', selected: true },
        ],
    },
    {
        id: '3',
        label: '单据管理',
        icon: SvgCalendar,
        href: 'https://www.baidu.com',
        target: '_blank',
    },
    {
        id: '4',
        label: '运营管理',
        children: [
            { id: '41', label: '运营管理1' },
            {
                id: '42',
                label: '运营管理2',
                children: [
                    { id: '421', label: '运营管理22' },
                    { id: '422', label: '运营管理22' },
                ],
            },
        ],
    },
]

function Demo() {
    return (
        <div>
            <SideNav menu={menu} />
            <SideNav menu={menu} reverseColor />
        </div>
    )
}
```

## 注意事项

- `icon` 只支持第一层菜单项
- 使用 `menuSelectedIds` 控制选中时，须保持 `menuItem.selected` 为 `undefined`，否则两者冲突
- 使用 `menuExpandedIds` 控制展开时，须保持 `menuItem.expanded` 为 `undefined`，否则两者冲突
- 在 Page 组件的"屏边抽屉"模式下，需通过 `submenuPopperPortalContainer` 将 portal 容器指定为 `Sidebar.inner`，避免鼠标移入三级 menuPopper 时侧边栏收起
