import { Button, DisclosureIcon, DropdownMenu, DropdownMenuItem } from '@hina-ui/react'
export default function Demo() {
return (
<DropdownMenu
label="排序方式"
content={
<>
<DropdownMenuItem>按更新时间</DropdownMenuItem>
<DropdownMenuItem>按发行日期</DropdownMenuItem>
<DropdownMenuItem>按收藏数</DropdownMenuItem>
</>
}
>
<Button variant="outline" tone="neutral" trailing={<DisclosureIcon />}>
按更新时间
</Button>
</DropdownMenu>
)
}
tsx
用法
import { DisclosureIcon } from '@hina-ui/react'
ts
指示物是展开控件上随开合旋转的那个箭头,各展开类组件共用同一个组件。多数情况下无需手动放置:Collapsible 的触发器已经自带,将来的 Accordion、Select、Tree 同样如此。
需要手动放置的情形只有一种,即触发器由调用方提供。DropdownMenu 的触发器可以是任意控件,Collapsible 使用 asChild 时亦然。
置入触发器即可,无需编写类名,也无需处理过渡:触发器携带识别标记,指示物据此获取状态。
示例
方向
down 静止时朝下,展开时旋转半圈,适用于下拉菜单、手风琴等向下展开的场景;end 静止时朝向行末,展开时旋转四分之一圈,适用于侧栏分组、树形节点等展开层级的场景。
import { Button, DisclosureIcon, DropdownMenu, DropdownMenuItem, Inline } from '@hina-ui/react'
export default function Demo() {
return (
<Inline>
<DropdownMenu
label="向下展开"
content={
<>
<DropdownMenuItem>静止时朝下</DropdownMenuItem>
<DropdownMenuItem>展开时旋转半圈</DropdownMenuItem>
</>
}
>
<Button variant="outline" tone="neutral" trailing={<DisclosureIcon />}>
down
</Button>
</DropdownMenu>
<DropdownMenu
label="向层级展开"
content={
<>
<DropdownMenuItem>静止时朝向行末</DropdownMenuItem>
<DropdownMenuItem>展开时旋转四分之一圈</DropdownMenuItem>
</>
}
>
<Button variant="outline" tone="neutral" trailing={<DisclosureIcon direction="end" />}>
end
</Button>
</DropdownMenu>
</Inline>
)
}
tsx
此处使用 end 而非 right,是为了在从右向左的语言中能够整体翻转。
更换字形
children 用于替换字形,旋转仍由组件负责。加号旋转四分之一圈后恰好成为叉号。
import { Plus } from 'lucide-react'
import { Button, DisclosureIcon, DropdownMenu, DropdownMenuItem } from '@hina-ui/react'
export default function Demo() {
return (
<DropdownMenu
label="添加"
content={
<>
<DropdownMenuItem>想读</DropdownMenuItem>
<DropdownMenuItem>在读</DropdownMenuItem>
<DropdownMenuItem>读过</DropdownMenuItem>
</>
}
>
<Button
variant="outline"
tone="neutral"
trailing={
<DisclosureIcon direction="end">
<Plus />
</DisclosureIcon>
}
>
添加到
</Button>
</DropdownMenu>
)
}
tsx
状态由外部持有时
当状态不在祖先触发器上,而由外部变量持有时,传入 open。传入之后,指示物不再读取祖先的状态。
open:false
'use client'
import { useState } from 'react'
import { Button, DisclosureIcon, Inline, Text } from '@hina-ui/react'
export default function Demo() {
const [open, setOpen] = useState(false)
return (
<Inline>
<Button
variant="soft"
tone="neutral"
onClick={() => setOpen(!open)}
trailing={<DisclosureIcon open={open} />}
>
状态由外部持有
</Button>
<Text tone="muted" size="sm">
open:{String(open)}
</Text>
</Inline>
)
}
tsx
边界
该组件表达的是状态,而非方向。面包屑之间的 >、子菜单末尾的箭头都不随状态变化,它们不属于该组件的职责,各自保持静态图标即可。
无障碍
- 指示物始终带有
aria-hidden。开合状态已由触发器的aria-expanded播报,重复播报属于冗余信息。 - 指示物不可聚焦,键盘焦点不会停留其上。
API
Props
| 属性 | 类型 | 默认值 | 说明 |
|---|---|---|---|
direction | 'down' | 'end' | 'down' | 静止朝向,同时决定旋转半圈还是四分之一圈 |
open | boolean | — | 自行指定状态;不传则读取祖先触发器 |
className | string | — | 追加至根元素的类名 |
内容属性
| 属性 | 说明 |
|---|---|
children | 替换字形,旋转仍由组件负责 |