Skip to content
通用组件

下拉菜单Dropdown

点按钮拉下一列动作 / 链接。左 2px 青条 + 淡底的高亮与侧栏当前项同一语言;键盘按 WAI-ARIA 菜单按钮。

Vue
实验import { AkDropdown } from "@mooncellwiki/prts-design-vue"Storybook ↗源码 ↗

点一枚按钮拉下一列动作或链接:页面动作簇的「更多」、用户菜单、排序 / 语种切换。白底卡片、1px 边、投影;悬停 / 键盘移到的项是左 2px 青条 + 淡底,与侧栏当前项、搜索面板高亮行同一语言;危险项红字;组之间一条分隔线。

基本用法 ​

写法同 Naive UI 的 n-dropdown:默认插槽放触发元素(一般是 AkButton),options 给菜单项,选中触发 select(key, option),之后菜单收起、焦点回到触发按钮。菜单项 { key, label, icon?, disabled?, danger?, href? },{ type: "divider" } 是分隔线。

给了 value 就是单选菜单:当前项高亮(.is-active)、role="menuitemradio" + aria-checked,打开时焦点落在它上面。

分组 · 链接项 ​

{ type: "group", label, children } 是带小标题的一组,相邻两组之间自动一条线——对应 MW 门户(#p-cactions / #p-tb)塞进卡片的写法。有 href 的项渲染成 <a>(照常跳转,也触发 select)。触发按钮靠右时用 placement="bottom-end" 让菜单右对齐。

键盘 ​

按 WAI-ARIA 菜单按钮:

焦点在键行为
触发按钮Enter / 空格 / ↓打开,焦点到第一项(单选菜单到当前项)
触发按钮↑打开,焦点到最后一项
菜单↓ / ↑下一项 / 上一项(首尾循环;禁用项也停,但选不了)
菜单Home / End第一项 / 最后一项
菜单字母 / 汉字跳到下一个以它开头的项
菜单Enter / 空格选中(链接项跳转),收起,焦点回到按钮
菜单Esc收起,焦点回到按钮
菜单Tab收起,焦点照常移到后面的元素

鼠标点菜单外面也会收起。菜单是 role="menu",名字默认取触发按钮的文字(aria-labelledby),label 可另给;组是 role="group" + aria-label(小标题只给眼睛看)。

Vue API ​

属性类型默认说明
options必填DropdownMixedOption[]—菜单项:{ key, label, icon?, disabled?, danger?, href? };{ type: "divider" } 分隔线;{ type: "group", label, children } 带小标题的一组
placement"bottom-start""bottom-end""bottom-start"菜单对齐:bottom-start 与触发元素左对齐(默认)· bottom-end 右对齐(靠页面右边的触发元素用)
valueDropdownKey—当前选中项的 key:该项高亮,菜单变成单选菜单(menuitemradio + aria-checked),打开时落在它上面
labelstring—读屏用的菜单名;不写时用触发元素的文字
disabledbooleanfalse禁用:触发元素点了不展开
modelValuebooleanfalse菜单是否展开
事件参数说明
update:modelValue[value: boolean]
select[key: DropdownKey, option: DropdownOption]选了一项(点击 / Enter / 空格);之后菜单收起、焦点回到触发元素。有 href 的项照常跳转
插槽说明
default触发元素:取第一个元素 / 组件,自动补 aria-haspopup / aria-expanded / aria-controls 与键盘;id 它自己写了就沿用,没写才补一个(菜单的 aria-labelledby 指向它)

options 的类型 DropdownMixedOption / DropdownOption 从 @mooncellwiki/prts-design-vue 导出。

CSS 实现 ​

无 JS 的写法:.ak-dropdown > details > summary + .ak-menu(原生 <details> 开合,皮肤的用户菜单 / 「更多」就是这样);有 JS 时在 .ak-dropdown 上切 .is-open(Vue 版就是这样)。菜单可以是 ul.ak-menu > li > a,也可以是 div.ak-menu > nav.ak-menu__group( .ak-menu__label + ul ) 分组卡片,.ak-menu__head 是卡片抬头(用户名);抬头本身是入口时写成 a.ak-menu__head( .ak-avatar + .ak-menu__head-name ),右端带箭头(皮肤的用户菜单:点抬头去用户页)。放在正文里时外层标 ak-not-prose,免得吃正文的列表符与链接色。

块元素 __修饰 --

文本 CC BY-NC-SA 4.0 · 游戏素材版权归鹰角网络所有