|
| 1 | +<div align="center"> |
| 2 | + <h1>@rc-component/menu</h1> |
| 3 | + <p><sub>Ant Design 生态的一部分。</sub></p> |
| 4 | + <img alt="Ant Design" height="32" src="https://gw.alipayobjects.com/zos/rmsportal/KDpgvguMpGfqaHPjicRK.svg" /> |
| 5 | + <p>🧭 React 菜单组件,支持水平、垂直、内联、分组和子菜单。</p> |
| 6 | +</div> |
| 7 | + |
| 8 | +<p align="center"><a href="./README.md">English</a> | 简体中文</p> |
| 9 | + |
| 10 | + |
| 11 | +<div align="center"> |
| 12 | + |
| 13 | +[![NPM version][npm-image]][npm-url] [![npm download][download-image]][download-url] [![build status][github-actions-image]][github-actions-url] [![Codecov][codecov-image]][codecov-url] [![bundle size][bundlephobia-image]][bundlephobia-url] [![dumi][dumi-image]][dumi-url] |
| 14 | + |
| 15 | +</div> |
| 16 | + |
| 17 | + |
| 18 | +## 特性 |
| 19 | + |
| 20 | +- Horizontal, vertical, and inline menu modes. |
| 21 | +- Controlled and uncontrolled selection, open keys, and active key state. |
| 22 | +- `items` configuration API with legacy children support. |
| 23 | +- Sub menus, item groups, dividers, icons, overflow, popup rendering, and keyboard focus helpers. |
| 24 | +- 提供 TypeScript 类型定义和语义化 `classNames` / `styles` 插槽。 |
| 25 | +- 被 Ant Design 用作共享的 menu 基础能力。 |
| 26 | + |
| 27 | +## 安装 |
| 28 | + |
| 29 | +```bash |
| 30 | +npm install @rc-component/menu |
| 31 | +``` |
| 32 | + |
| 33 | +## 使用 |
| 34 | + |
| 35 | +```tsx | pure |
| 36 | +import Menu, { type MenuProps } from '@rc-component/menu'; |
| 37 | + |
| 38 | +const items: MenuProps['items'] = [ |
| 39 | + { key: 'home', label: 'Home' }, |
| 40 | + { |
| 41 | + key: 'docs', |
| 42 | + label: 'Docs', |
| 43 | + children: [ |
| 44 | + { key: 'quick-start', label: 'Quick start' }, |
| 45 | + { key: 'api', label: 'API' }, |
| 46 | + ], |
| 47 | + }, |
| 48 | +]; |
| 49 | + |
| 50 | +export default () => ( |
| 51 | + <Menu mode="inline" items={items} defaultSelectedKeys={['home']} defaultOpenKeys={['docs']} /> |
| 52 | +); |
| 53 | +``` |
| 54 | + |
| 55 | +```tsx | pure |
| 56 | +import Menu, { MenuItem, SubMenu } from '@rc-component/menu'; |
| 57 | + |
| 58 | +export default () => ( |
| 59 | + <Menu> |
| 60 | + <MenuItem key="1">Item 1</MenuItem> |
| 61 | + <SubMenu key="2" title="More"> |
| 62 | + <MenuItem key="2-1">Item 2-1</MenuItem> |
| 63 | + </SubMenu> |
| 64 | + </Menu> |
| 65 | +); |
| 66 | +``` |
| 67 | + |
| 68 | +## 示例 |
| 69 | + |
| 70 | +本地运行示例: |
| 71 | + |
| 72 | +```bash |
| 73 | +npm install |
| 74 | +npm start |
| 75 | +``` |
| 76 | + |
| 77 | +然后在浏览器中打开 dumi 开发服务地址。 |
| 78 | + |
| 79 | +## API |
| 80 | + |
| 81 | +### Menu |
| 82 | + |
| 83 | +| 参数 | 类型 | 默认值 | 说明 | |
| 84 | +| --- | --- | --- | --- | |
| 85 | +| activeKey | `string` | - | Controlled active item key. | |
| 86 | +| builtinPlacements | `Record<string, any>` | - | Popup alignment placements for sub menus. | |
| 87 | +| className | `string` | - | Class name for the root menu. | |
| 88 | +| classNames | `Partial<Record<'list' \| 'listTitle', string>>` | - | Semantic class names for menu slots. | |
| 89 | +| defaultActiveFirst | `boolean` | `false` | Focus the first enabled item when active key is absent. | |
| 90 | +| defaultOpenKeys | `string[]` | `[]` | Initial open sub menu keys. | |
| 91 | +| defaultSelectedKeys | `string[]` | `[]` | Initial selected item keys. | |
| 92 | +| defaultMotions | `Partial<Record<MenuMode \| 'other', CSSMotionProps>>` | - | Motion config by menu mode. | |
| 93 | +| direction | `'ltr' \| 'rtl'` | - | Layout direction. | |
| 94 | +| disabled | `boolean` | `false` | Disable all menu interactions. | |
| 95 | +| disabledOverflow | `boolean` | `false` | Disable overflow measurement. | |
| 96 | +| expandIcon | `ReactNode \| (props: RenderIconInfo) => ReactNode` | - | Custom sub menu expand icon. | |
| 97 | +| forceSubMenuRender | `boolean` | `false` | Render popup sub menus before they are opened. | |
| 98 | +| getPopupContainer | `(node: HTMLElement) => HTMLElement` | - | Container for popup sub menus. | |
| 99 | +| inlineCollapsed | `boolean` | - | Collapse inline menu layout. | |
| 100 | +| inlineIndent | `number` | `24` | Indent width for inline mode. | |
| 101 | +| itemIcon | `ReactNode \| (props: RenderIconInfo) => ReactNode` | - | Custom item icon. | |
| 102 | +| items | `ItemType[]` | - | Menu item configuration. | |
| 103 | +| mode | `'horizontal' \| 'vertical' \| 'inline'` | `vertical` | Menu display mode. | |
| 104 | +| motion | `CSSMotionProps` | - | Motion config for menu transitions. | |
| 105 | +| multiple | `boolean` | `false` | Allow multiple selected items. | |
| 106 | +| openKeys | `string[]` | - | Controlled open sub menu keys. | |
| 107 | +| overflowedIndicator | `ReactNode` | `"..."` | Indicator rendered for overflowed items. | |
| 108 | +| popupRender | `(node, info) => ReactNode` | - | Customize popup menu rendering. | |
| 109 | +| prefixCls | `string` | `rc-menu` | Class name prefix. | |
| 110 | +| rootClassName | `string` | - | Class name for the root wrapper. | |
| 111 | +| selectable | `boolean` | `true` | Allow item selection. | |
| 112 | +| selectedKeys | `string[]` | - | Controlled selected item keys. | |
| 113 | +| styles | `Partial<Record<'list' \| 'listTitle', CSSProperties>>` | - | Semantic styles for menu slots. | |
| 114 | +| subMenuCloseDelay | `number` | `0.1` | Delay in seconds before closing popup sub menus. | |
| 115 | +| subMenuOpenDelay | `number` | `0.1` | Delay in seconds before opening popup sub menus. | |
| 116 | +| triggerSubMenuAction | `'click' \| 'hover'` | `hover` | Interaction that opens sub menus. | |
| 117 | +| onClick | `(info: MenuInfo) => void` | - | Triggered when an item is clicked. | |
| 118 | +| onDeselect | `(info: SelectInfo) => void` | - | Triggered when an item is deselected. | |
| 119 | +| onOpenChange | `(openKeys: string[]) => void` | - | Triggered when open keys change. | |
| 120 | +| onSelect | `(info: SelectInfo) => void` | - | Triggered when an item is selected. | |
| 121 | + |
| 122 | +### ItemType |
| 123 | + |
| 124 | +```ts |
| 125 | +type ItemType = |
| 126 | + | { |
| 127 | + type?: 'item'; |
| 128 | + // Item keys accept React.Key and are normalized to strings in event info. |
| 129 | + key: React.Key; |
| 130 | + label?: React.ReactNode; |
| 131 | + disabled?: boolean; |
| 132 | + itemIcon?: RenderIconType; |
| 133 | + extra?: React.ReactNode; |
| 134 | + } |
| 135 | + | { |
| 136 | + type?: 'submenu'; |
| 137 | + // Sub menu keys are strings to match openKeys/defaultOpenKeys. |
| 138 | + key: string; |
| 139 | + label?: React.ReactNode; |
| 140 | + children: ItemType[]; |
| 141 | + disabled?: boolean; |
| 142 | + } |
| 143 | + | { |
| 144 | + type: 'group'; |
| 145 | + label?: React.ReactNode; |
| 146 | + children?: ItemType[]; |
| 147 | + } |
| 148 | + | { |
| 149 | + type: 'divider'; |
| 150 | + }; |
| 151 | +``` |
| 152 | + |
| 153 | +### Ref |
| 154 | + |
| 155 | +| Method | 类型 | 说明 | |
| 156 | +| --- | --- | --- | |
| 157 | +| `focus` | `(options?: FocusOptions) => void` | Focus the active item or first enabled item. | |
| 158 | +| `findItem` | `({ key: string }) => HTMLElement \| null` | Find the DOM element for an item key. | |
| 159 | +| `list` | `HTMLUListElement` | Root menu list element. | |
| 160 | + |
| 161 | +## 本地开发 |
| 162 | + |
| 163 | +```bash |
| 164 | +npm install |
| 165 | +npm start |
| 166 | +npm test |
| 167 | +npm run tsc |
| 168 | +npm run compile |
| 169 | +npm run build |
| 170 | +``` |
| 171 | + |
| 172 | +## 发布 |
| 173 | + |
| 174 | +```bash |
| 175 | +npm run prepublishOnly |
| 176 | +``` |
| 177 | + |
| 178 | +The release flow is handled by `@rc-component/np` through the `rc-np` command after the package build. |
| 179 | + |
| 180 | +## 许可证 |
| 181 | + |
| 182 | +@rc-component/menu is released under the [MIT](./LICENSE.md) license. |
| 183 | + |
| 184 | +[npm-image]: https://img.shields.io/npm/v/@rc-component/menu.svg?style=flat-square |
| 185 | +[npm-url]: https://npmjs.org/package/@rc-component/menu |
| 186 | +[github-actions-image]: https://github.com/react-component/menu/actions/workflows/react-component-ci.yml/badge.svg |
| 187 | +[github-actions-url]: https://github.com/react-component/menu/actions/workflows/react-component-ci.yml |
| 188 | +[codecov-image]: https://img.shields.io/codecov/c/github/react-component/menu/master.svg?style=flat-square |
| 189 | +[codecov-url]: https://app.codecov.io/gh/react-component/menu |
| 190 | +[download-image]: https://img.shields.io/npm/dm/@rc-component/menu.svg?style=flat-square |
| 191 | +[download-url]: https://npmjs.org/package/@rc-component/menu |
| 192 | +[bundlephobia-url]: https://bundlephobia.com/package/@rc-component/menu |
| 193 | +[bundlephobia-image]: https://img.shields.io/bundlephobia/minzip/@rc-component/menu?style=flat-square |
| 194 | +[dumi-url]: https://github.com/umijs/dumi |
| 195 | +[dumi-image]: https://img.shields.io/badge/docs%20by-dumi-blue?style=flat-square |
0 commit comments