#Menu 菜单
按层级组织页面导航。
#基本用法
basic.tsx
import { Menu } from '@ifhover/leaf-ui';
import { FolderKanban, House, Palette, Rocket, Settings, Users } from 'lucide-react';
export function MenuBasic() {
return (
<Menu
mode="inline"
defaultSelectedKey="design"
defaultOpenKeys={['projects']}
items={[
{ key: 'home', label: '工作台', icon: <House /> },
{
key: 'projects',
label: '项目管理',
icon: <FolderKanban />,
children: [
{ key: 'design', label: '设计资源', icon: <Palette /> },
{ key: 'release', label: '发布管理', icon: <Rocket /> },
],
},
{ key: 'team', label: '团队成员', icon: <Users /> },
{ key: 'settings', label: '设置', icon: <Settings /> },
]}
/>
);
}
#更多用法
横向导航
可折叠侧栏
advanced.tsx
import type { MenuItem } from '@ifhover/leaf-ui';
import { Button, Flex, Menu, Text } from '@ifhover/leaf-ui';
import { BookOpen, Folder, House, Palette, Settings } from 'lucide-react';
import { useState } from 'react';
const items: MenuItem[] = [
{ key: 'home', label: '概览', icon: <House /> },
{
key: 'resources',
label: '资源',
icon: <Folder />,
children: [
{ key: 'components', label: '组件', icon: <BookOpen /> },
{ key: 'themes', label: '主题', icon: <Palette /> },
],
},
{ key: 'settings', label: '设置', icon: <Settings /> },
];
export function MenuHorizontal() {
const [collapsed, setCollapsed] = useState(false);
return (
<Flex direction="column" gap={20}>
<Flex direction="column" gap="sm" align="center">
<Text tone="muted">横向导航</Text>
<Menu mode="horizontal" items={items} defaultSelectedKey="home" />
</Flex>
<Flex direction="column" gap="sm" align="center">
<Text tone="muted">可折叠侧栏</Text>
<Button variant="ghost" size="sm" onClick={() => setCollapsed((value) => !value)}>
切换折叠
</Button>
<Menu collapsed={collapsed} items={items} defaultSelectedKey="home" />
</Flex>
</Flex>
);
}
#受控导航与路由
selectedKey 跟随当前路由。linkRender 可替换默认链接,例如 React Router 或 Next.js 的 Link;保留传入链接的事件、类名和 ARIA 属性。
当前页面:overview。示例切换本地状态;接入路由时使用自己的 Link,并保留传入属性。
capabilities.tsx
import type { MenuItem } from '@ifhover/leaf-ui';
import { Menu, Space, Text } from '@ifhover/leaf-ui';
import { BookOpen, House, Settings } from 'lucide-react';
import { type AnchorHTMLAttributes, cloneElement, isValidElement, type ReactElement, useState } from 'react';
export function MenuRouting() {
const [selected, setSelected] = useState('overview');
const items: MenuItem[] = [
{ key: 'overview', label: '概览', href: '#overview', icon: <House /> },
{
key: 'resources',
label: '资源',
icon: <BookOpen />,
children: [
{ key: 'guides', label: '使用指南', href: '#guides' },
{
key: 'settings',
label: '设置',
href: '#settings',
icon: <Settings />,
},
],
},
];
return (
<Space direction="vertical" align="center">
<Menu
aria-label={'应用导航'}
items={items}
selectedKey={selected}
defaultOpenKeys={['resources']}
onSelect={setSelected}
linkRender={(_item, link) => {
if (!isValidElement(link)) return link;
const element = link as ReactElement<AnchorHTMLAttributes<HTMLAnchorElement>>;
return cloneElement(element, {
onClick: (event) => {
element.props.onClick?.(event);
event.preventDefault();
},
});
}}
/>
<Text tone="muted">
{`当前页面:${selected}。示例切换本地状态;接入路由时使用自己的 Link,并保留传入属性。`}
</Text>
</Space>
);
}
#使用说明
纵向菜单默认 240px,折叠时 60px,可通过 style.width 调整。items 支持嵌套、分组、分隔线与链接。selectedKey 管理当前选中项,openKeys 管理展开项;横向模式与折叠模式使用浮层展示子菜单。
子菜单展开、收起以及侧栏宽度变化均带有过渡。收起的子项不会参与键盘导航;系统开启减少动态效果时,过渡会自动关闭。
菜单项、悬停背景和选中高亮与按钮共用基础圆角。通过 ConfigProvider 的 theme.borderRadius 统一调整,也可用 theme.components.Menu.borderRadius 单独设置菜单圆角。
#类型
组装数据、定义回调和使用 ref 时,可以导入这些类型。
import type { MenuItem, MenuProps } from '@ifhover/leaf-ui';#MenuItem API
| 属性 | 类型 | 默认值 | 说明 |
|---|---|---|---|
key | string | 必填 | 必需。唯一且稳定的标识 |
label | ReactNode | 必填 | 必需。显示内容 |
icon | ReactNode | — | 自定义图标 |
href | string | — | 目标链接 |
disabled | boolean | — | 禁用交互。 |
danger | boolean | — | 危险操作颜色 |
children | readonly MenuItem[] | — | 内容或下级项目 |
type | 'item' | 'group' | 'divider' | — | 显示或选项类型 |
#MenuProps API
| 属性 | 类型 | 默认值 | 说明 |
|---|---|---|---|
items | readonly MenuItem[] | 必填 | 必需。数据项目,保持 key 唯一且稳定 |
mode | 'vertical' | 'horizontal' | 'inline' | 'vertical' | 菜单排列方式 |
selectedKey | string | — | 受控选中项目 |
defaultSelectedKey | string | '' | 初始选中项目 |
onSelect | (key: string, item: MenuItem) => void | — | 选择项目 |
openKeys | readonly string[] | — | 受控展开项目 |
defaultOpenKeys | readonly string[] | [] | 初始展开项目 |
onOpenChange | (keys: string[]) => void | — | 展开状态变化 |
collapsed | boolean | false | 受控收起状态 |
itemRender | (item: MenuItem, content: ReactNode) => ReactNode | — | 自定义条目内容。 |
linkRender | (item: MenuItem, link: ReactNode) => ReactNode | — | 接入路由链接时保留传入的可访问性和事件属性。 |
itemClassName | string | ((item: MenuItem) => string) | — | 条目类名或按条目计算的类名。 |