Files
CNWei 5eb1506650 feat(ui): 新增 Caret / SortableList,箭头画法收成一份
- Caret:6px CSS 折角(open 切朝向,size 可调),Menu 与 Select 改为复用它,
  两处各自的画法删掉,全库只剩一份
- SortableList:可拖拽排序的条目列表(items / activeKey / onSelect / onReorder),
  拖拽位置计算从应用里挪进组件,顺序没变不回调
- 展示页:菜单补「折叠箭头」,新增 #sortable 一节并挂到导航
- COMPONENTS.md 契约 3.48 / 3.49、组件地图、README 清单、变更记录同步
2026-11-01 22:07:31 +08:00

123 lines
4.0 KiB
TypeScript
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import { useState } from 'react'
import { Card, Caret, Icon, Menu, Space, Text } from '../../src'
import { Demo } from '../components/Demo'
import { PropsTable } from '../components/PropsTable'
import { Section } from '../components/Section'
const ITEMS = [
{
key: 'content',
label: '内容',
icon: <Icon name="folder_more_line" />,
children: [
{ key: 'recommend', label: '常用推荐' },
{ key: 'movie', label: '推荐电影' },
{ key: 'ces', label: 'CES 现场报道' },
],
},
{
key: 'system',
label: '系统',
icon: <Icon name="settings_1_line" />,
children: [
{ key: 'profile', label: '资料' },
{ key: 'data', label: '内容库' },
],
},
{ key: 'about', label: '关于', icon: <Icon name="question_line" /> },
]
export function MenuSection() {
const [active, setActive] = useState('recommend')
return (
<Section
id="menu"
title="菜单"
api="Menu"
desc="侧栏菜单:一层折叠 + 两级结构,数据无关——业务树由页面转成 items。含 activeKey 的父级会自动展开。"
>
<Demo
title="基础用法"
desc="父级是折叠按钮(aria-expanded),子项是导航项(aria-current=page)。"
code={`const [active, setActive] = useState('recommend')
<Menu items={ITEMS} activeKey={active} onSelect={setActive} />`}
>
<Card padding="sm" style={{ width: 240 }}>
<Menu items={ITEMS} activeKey={active} onSelect={setActive} />
</Card>
<Text size="sm" tone="muted">
当前:{active}
</Text>
</Demo>
<Demo
title="默认展开"
desc="defaultOpenKeys 指定初始展开的父级;用户手动折叠后以用户操作为准。"
code={`<Menu items={ITEMS} activeKey="data" onSelect={() => {}} defaultOpenKeys={['system']} />`}
>
<Card padding="sm" style={{ width: 240 }}>
<Menu items={ITEMS} activeKey="data" onSelect={() => undefined} defaultOpenKeys={['system']} />
</Card>
</Demo>
<Demo
title="行高"
desc="默认 36px;需要更松的密度(如资料较多、点击目标更大)时传 itemHeight。"
layout="column"
code={`<Menu items={ITEMS} activeKey="data" onSelect={() => {}} itemHeight={44} />`}
>
<Card padding="sm" style={{ width: 240 }}>
<Menu
items={ITEMS}
activeKey="data"
onSelect={() => undefined}
defaultOpenKeys={['system']}
itemHeight={44}
/>
</Card>
</Demo>
<Demo
title="折叠箭头"
desc="Caret 是菜单、下拉、可折叠表格行共用的 6px 折角:收起朝下、展开朝上,纯装饰,无障碍状态由外层按钮的 aria-expanded 承担。"
code={`<Caret />
<Caret open />`}
>
<Space gap="lg">
<Space gap="sm" align="center">
<Caret />
<Text size="sm" tone="muted">
收起
</Text>
</Space>
<Space gap="sm" align="center">
<Caret open />
<Text size="sm" tone="muted">
展开
</Text>
</Space>
</Space>
</Demo>
<PropsTable
rows={[
{ name: 'items', type: 'MenuItem[]', required: true, desc: '{ key, label, icon?, children? }' },
{ name: 'activeKey', type: 'string', desc: '当前选中项' },
{ name: 'onSelect', type: '(key: string) => void', required: true, desc: '选中回调' },
{ name: 'defaultOpenKeys', type: 'string[]', desc: '初始展开的父级 key' },
{ name: 'itemHeight', type: 'number', defaultValue: '36', desc: '一级菜单行高(px)' },
]}
/>
<PropsTable
rows={[
{ name: 'open', type: 'boolean', defaultValue: 'false', desc: '展开状态(决定箭头朝向)' },
{ name: 'size', type: 'number', defaultValue: '6', desc: '折角边长(px)' },
]}
/>
</Section>
)
}