iter: d25 menu 条目支持快捷键提示
This commit is contained in:
@@ -248,6 +248,14 @@
|
|||||||
"acceptance": "README 覆盖定位 / 快速开始 / 28 组件清单 / 目录表 / 三道门禁 / Agent 接入 / 分支流水线;新增 <!-- ua:components --> 标记区块,ua verify 校验区块 id 集合与全部清单 docs.components 完全一致(缺/多都报);负向测试(删 avatar)能拦下;AGENTS.md 同步;npm run check 全绿",
|
"acceptance": "README 覆盖定位 / 快速开始 / 28 组件清单 / 目录表 / 三道门禁 / Agent 接入 / 分支流水线;新增 <!-- ua:components --> 标记区块,ua verify 校验区块 id 集合与全部清单 docs.components 完全一致(缺/多都报);负向测试(删 avatar)能拦下;AGENTS.md 同步;npm run check 全绿",
|
||||||
"status": "done",
|
"status": "done",
|
||||||
"notes": "不做自动写入(避免工具偷偷改文档),只做一致性校验:新增组件时 verify 报「README 组件区块缺少 xxx」,由人补一行;标记区块用 · 分隔便于人读与机器切分"
|
"notes": "不做自动写入(避免工具偷偷改文档),只做一致性校验:新增组件时 verify 报「README 组件区块缺少 xxx」,由人补一行;标记区块用 · 分隔便于人读与机器切分"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "d25",
|
||||||
|
"title": "menu 条目支持快捷键提示",
|
||||||
|
"motivation": "菜单里展示快捷键是桌面级体验的标配;缺字段时调用方只能把快捷键拼进 label,文案与对齐都失控",
|
||||||
|
"acceptance": "MenuItem 新增 shortcut?: string;条目改为 flex 两端对齐,label 单行省略,右侧 kbd 灰字提示(不绑定按键);demo 文件操作菜单加 F2 / ⌘D;manifest/文档/llms-full.txt 同步;npm run check 全绿",
|
||||||
|
"status": "done",
|
||||||
|
"notes": "明确边界:快捷键只做展示,实际按键仍需调用方全局监听(组件不做全局键盘陷阱);两端对齐让长文案截断而快捷键始终可见;kbd 用 inherit 字体避免等宽字跳脱整体排版"
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|||||||
+3
-2
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"$schema": "ui-arch-registry-index/0.1",
|
"$schema": "ui-arch-registry-index/0.1",
|
||||||
"generatedAt": "2026-10-23T09:05:40.038Z",
|
"generatedAt": "2026-10-23T09:06:10.925Z",
|
||||||
"repoRoot": ".",
|
"repoRoot": ".",
|
||||||
"packages": [
|
"packages": [
|
||||||
{
|
{
|
||||||
@@ -517,7 +517,7 @@
|
|||||||
"n": "items",
|
"n": "items",
|
||||||
"t": "MenuItem[]",
|
"t": "MenuItem[]",
|
||||||
"r": 1,
|
"r": 1,
|
||||||
"d": "菜单条目:{ value, label, disabled?, danger?, divider? }"
|
"d": "菜单条目:{ value, label, disabled?, danger?, divider?, shortcut? }"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"n": "variant",
|
"n": "variant",
|
||||||
@@ -543,6 +543,7 @@
|
|||||||
"准备 items 数组:value 是回调标识、label 是展示文案,插一条 { divider: true } 即可分出条目组",
|
"准备 items 数组:value 是回调标识、label 是展示文案,插一条 { divider: true } 即可分出条目组",
|
||||||
"传 label 决定触发器文案;默认 ghost 轻量样式,主操作用 variant: 'primary'",
|
"传 label 决定触发器文案;默认 ghost 轻量样式,主操作用 variant: 'primary'",
|
||||||
"点触发器展开弹层,点条目收起并触发 onSelect;点外部或按 Esc 也会收起(Esc 后焦点回到触发器)",
|
"点触发器展开弹层,点条目收起并触发 onSelect;点外部或按 Esc 也会收起(Esc 后焦点回到触发器)",
|
||||||
|
"条目要给快捷键提示时传 shortcut(如 '⌘K'):右侧灰字展示,组件不绑定按键,实际快捷键由调用方在全局监听",
|
||||||
"键盘:Tab 聚焦触发器,↑↓ 展开并在可用条目间环形移动,Enter / Space 选中;disabled 项自动跳过",
|
"键盘:Tab 聚焦触发器,↑↓ 展开并在可用条目间环形移动,Enter / Space 选中;disabled 项自动跳过",
|
||||||
"靠右对齐避免溢出时传 align: 'end';危险操作给条目加 danger: true"
|
"靠右对齐避免溢出时传 align: 'end';危险操作给条目加 danger: true"
|
||||||
]
|
]
|
||||||
|
|||||||
@@ -29,3 +29,4 @@
|
|||||||
{"time": "2026-10-23T17:03:49+08:00", "id": "d22", "result": "done", "summary": "新增头像 avatar(src 图片 / 首字占位 + size + 四档语义底色),demo 独立 sec-avatar;中途被 verify 的 demo 锚点检查拦下已补;check 全绿"}
|
{"time": "2026-10-23T17:03:49+08:00", "id": "d22", "result": "done", "summary": "新增头像 avatar(src 图片 / 首字占位 + size + 四档语义底色),demo 独立 sec-avatar;中途被 verify 的 demo 锚点检查拦下已补;check 全绿"}
|
||||||
{"time": "2026-10-23T17:04:27+08:00", "id": "d23", "result": "done", "summary": "alert 新增 title / closable / onClose 与 role=alert,关闭走 200ms 退场后摘除;demo 独立 sec-alert;manifest/llms 同步,check 全绿"}
|
{"time": "2026-10-23T17:04:27+08:00", "id": "d23", "result": "done", "summary": "alert 新增 title / closable / onClose 与 role=alert,关闭走 200ms 退场后摘除;demo 独立 sec-alert;manifest/llms 同步,check 全绿"}
|
||||||
{"time": "2026-10-23T17:05:46+08:00", "id": "d24", "result": "done", "summary": "重写 README(定位/快速开始/28 组件/目录/门禁/Agent 接入/流水线),组件清单做成标记区块并由 ua verify 校验防漂移;负向测试通过,check 全绿"}
|
{"time": "2026-10-23T17:05:46+08:00", "id": "d24", "result": "done", "summary": "重写 README(定位/快速开始/28 组件/目录/门禁/Agent 接入/流水线),组件清单做成标记区块并由 ua verify 校验防漂移;负向测试通过,check 全绿"}
|
||||||
|
{"time": "2026-10-23T17:06:17+08:00", "id": "d25", "result": "done", "summary": "menu 条目新增 shortcut 快捷键提示(右侧 kbd 灰字,两端对齐 + 单行省略,不绑按键);demo/manifest/llms 同步,check 全绿"}
|
||||||
|
|||||||
+2
-2
@@ -337,8 +337,8 @@ const content = h(
|
|||||||
menu({
|
menu({
|
||||||
label: '文件操作',
|
label: '文件操作',
|
||||||
items: [
|
items: [
|
||||||
{ value: 'rename', label: '重命名' },
|
{ value: 'rename', label: '重命名', shortcut: 'F2' },
|
||||||
{ value: 'copy', label: '创建副本' },
|
{ value: 'copy', label: '创建副本', shortcut: '⌘D' },
|
||||||
{ value: 'archive', label: '归档', disabled: true },
|
{ value: 'archive', label: '归档', disabled: true },
|
||||||
{ divider: true, value: '', label: '' },
|
{ divider: true, value: '', label: '' },
|
||||||
{ value: 'delete', label: '删除', danger: true },
|
{ value: 'delete', label: '删除', danger: true },
|
||||||
|
|||||||
+5
-4
@@ -1,6 +1,6 @@
|
|||||||
# @ui-arch 组件库 Agent 文档(无图形版)
|
# @ui-arch 组件库 Agent 文档(无图形版)
|
||||||
|
|
||||||
> 自动生成于 2026-10-23T09:05:40.038Z,数据源:各包 ua.manifest.json,勿手改。人类版文档站:apps/docs/index.html。
|
> 自动生成于 2026-10-23T09:06:10.925Z,数据源:各包 ua.manifest.json,勿手改。人类版文档站:apps/docs/index.html。
|
||||||
> 组件 = 普通函数,传 props 返回 DOM;状态用 signal 双向绑定:读 signal() 写 signal(v)。
|
> 组件 = 普通函数,传 props 返回 DOM;状态用 signal 双向绑定:读 signal() 写 signal(v)。
|
||||||
|
|
||||||
## 快速上手
|
## 快速上手
|
||||||
@@ -224,7 +224,7 @@ const city = signal(''); select({ options: [{ value: 'bj', label: '北京' }], v
|
|||||||
参数:
|
参数:
|
||||||
|
|
||||||
- label(必填):string —— 触发器文案
|
- label(必填):string —— 触发器文案
|
||||||
- items(必填):MenuItem[] —— 菜单条目:{ value, label, disabled?, danger?, divider? }
|
- items(必填):MenuItem[] —— 菜单条目:{ value, label, disabled?, danger?, divider?, shortcut? }
|
||||||
- variant(默认 ghost):'primary' | 'ghost' —— 触发器视觉强度;缺省 ghost
|
- variant(默认 ghost):'primary' | 'ghost' —— 触发器视觉强度;缺省 ghost
|
||||||
- align(默认 start):'start' | 'end' —— 弹层对齐方向;缺省 start(与触发器左对齐)
|
- align(默认 start):'start' | 'end' —— 弹层对齐方向;缺省 start(与触发器左对齐)
|
||||||
- onSelect(回调):(value: string) => void —— 选中回调,禁用项不触发
|
- onSelect(回调):(value: string) => void —— 选中回调,禁用项不触发
|
||||||
@@ -240,8 +240,9 @@ menu({ label: '操作', items: [{ value: 'edit', label: '编辑' }, { value: 'de
|
|||||||
1. 准备 items 数组:value 是回调标识、label 是展示文案,插一条 { divider: true } 即可分出条目组
|
1. 准备 items 数组:value 是回调标识、label 是展示文案,插一条 { divider: true } 即可分出条目组
|
||||||
2. 传 label 决定触发器文案;默认 ghost 轻量样式,主操作用 variant: 'primary'
|
2. 传 label 决定触发器文案;默认 ghost 轻量样式,主操作用 variant: 'primary'
|
||||||
3. 点触发器展开弹层,点条目收起并触发 onSelect;点外部或按 Esc 也会收起(Esc 后焦点回到触发器)
|
3. 点触发器展开弹层,点条目收起并触发 onSelect;点外部或按 Esc 也会收起(Esc 后焦点回到触发器)
|
||||||
4. 键盘:Tab 聚焦触发器,↑↓ 展开并在可用条目间环形移动,Enter / Space 选中;disabled 项自动跳过
|
4. 条目要给快捷键提示时传 shortcut(如 '⌘K'):右侧灰字展示,组件不绑定按键,实际快捷键由调用方在全局监听
|
||||||
5. 靠右对齐避免溢出时传 align: 'end';危险操作给条目加 danger: true
|
5. 键盘:Tab 聚焦触发器,↑↓ 展开并在可用条目间环形移动,Enter / Space 选中;disabled 项自动跳过
|
||||||
|
6. 靠右对齐避免溢出时传 align: 'end';危险操作给条目加 danger: true
|
||||||
|
|
||||||
现场演示:apps/docs/demo.html#sec-menu
|
现场演示:apps/docs/demo.html#sec-menu
|
||||||
|
|
||||||
|
|||||||
@@ -24,7 +24,8 @@ export function menu(props: MenuProps): HTMLElement {
|
|||||||
disabled: item.disabled ? true : undefined,
|
disabled: item.disabled ? true : undefined,
|
||||||
onClick: () => pick(item),
|
onClick: () => pick(item),
|
||||||
},
|
},
|
||||||
item.label,
|
h('span', { class: 'ua-menu-label' }, item.label),
|
||||||
|
item.shortcut ? h('kbd', { class: 'ua-menu-key' }, item.shortcut) : null, // 快捷键只做提示,不拦截按键
|
||||||
) as HTMLButtonElement;
|
) as HTMLButtonElement;
|
||||||
if (!item.disabled) focusables.push(btn); // 禁用项不参与导航
|
if (!item.disabled) focusables.push(btn); // 禁用项不参与导航
|
||||||
return btn;
|
return btn;
|
||||||
|
|||||||
@@ -103,6 +103,7 @@ export interface MenuItem {
|
|||||||
label: string; // 条目文案
|
label: string; // 条目文案
|
||||||
disabled?: boolean; // 禁用该条目:置灰且不参与键盘导航
|
disabled?: boolean; // 禁用该条目:置灰且不参与键盘导航
|
||||||
danger?: boolean; // 危险操作条目:文案取 danger 语义色
|
danger?: boolean; // 危险操作条目:文案取 danger 语义色
|
||||||
|
shortcut?: string; // 右侧快捷键提示(仅展示,不绑定按键),如 '⌘K'
|
||||||
divider?: boolean; // 该条目渲染为分隔线(忽略 value / label)
|
divider?: boolean; // 该条目渲染为分隔线(忽略 value / label)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -388,7 +388,7 @@
|
|||||||
"n": "items",
|
"n": "items",
|
||||||
"t": "MenuItem[]",
|
"t": "MenuItem[]",
|
||||||
"r": 1,
|
"r": 1,
|
||||||
"d": "菜单条目:{ value, label, disabled?, danger?, divider? }"
|
"d": "菜单条目:{ value, label, disabled?, danger?, divider?, shortcut? }"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"n": "variant",
|
"n": "variant",
|
||||||
@@ -414,6 +414,7 @@
|
|||||||
"准备 items 数组:value 是回调标识、label 是展示文案,插一条 { divider: true } 即可分出条目组",
|
"准备 items 数组:value 是回调标识、label 是展示文案,插一条 { divider: true } 即可分出条目组",
|
||||||
"传 label 决定触发器文案;默认 ghost 轻量样式,主操作用 variant: 'primary'",
|
"传 label 决定触发器文案;默认 ghost 轻量样式,主操作用 variant: 'primary'",
|
||||||
"点触发器展开弹层,点条目收起并触发 onSelect;点外部或按 Esc 也会收起(Esc 后焦点回到触发器)",
|
"点触发器展开弹层,点条目收起并触发 onSelect;点外部或按 Esc 也会收起(Esc 后焦点回到触发器)",
|
||||||
|
"条目要给快捷键提示时传 shortcut(如 '⌘K'):右侧灰字展示,组件不绑定按键,实际快捷键由调用方在全局监听",
|
||||||
"键盘:Tab 聚焦触发器,↑↓ 展开并在可用条目间环形移动,Enter / Space 选中;disabled 项自动跳过",
|
"键盘:Tab 聚焦触发器,↑↓ 展开并在可用条目间环形移动,Enter / Space 选中;disabled 项自动跳过",
|
||||||
"靠右对齐避免溢出时传 align: 'end';危险操作给条目加 danger: true"
|
"靠右对齐避免溢出时传 align: 'end';危险操作给条目加 danger: true"
|
||||||
]
|
]
|
||||||
|
|||||||
+18
-1
@@ -360,8 +360,11 @@
|
|||||||
visibility: visible;
|
visibility: visible;
|
||||||
}
|
}
|
||||||
.ua-menu-item {
|
.ua-menu-item {
|
||||||
display: block;
|
display: flex;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: space-between;
|
||||||
|
gap: var(--ua-space-4);
|
||||||
text-align: left;
|
text-align: left;
|
||||||
padding: 6px 10px;
|
padding: 6px 10px;
|
||||||
border: none;
|
border: none;
|
||||||
@@ -381,6 +384,20 @@
|
|||||||
.ua-menu-item.is-danger:hover:not(:disabled) {
|
.ua-menu-item.is-danger:hover:not(:disabled) {
|
||||||
background: color-mix(in srgb, var(--ua-color-danger) 10%, transparent);
|
background: color-mix(in srgb, var(--ua-color-danger) 10%, transparent);
|
||||||
}
|
}
|
||||||
|
.ua-menu-label {
|
||||||
|
flex: 1;
|
||||||
|
min-width: 0;
|
||||||
|
overflow: hidden;
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
white-space: nowrap;
|
||||||
|
}
|
||||||
|
.ua-menu-key {
|
||||||
|
flex: none;
|
||||||
|
color: var(--ua-color-text-muted);
|
||||||
|
font-family: inherit;
|
||||||
|
font-size: var(--ua-font-size-sm);
|
||||||
|
opacity: 0.8;
|
||||||
|
}
|
||||||
.ua-menu-item:disabled {
|
.ua-menu-item:disabled {
|
||||||
opacity: 0.45;
|
opacity: 0.45;
|
||||||
cursor: not-allowed;
|
cursor: not-allowed;
|
||||||
|
|||||||
Reference in New Issue
Block a user