iter(g44): accordion 标题行方向键导航

This commit is contained in:
HIsheR
2026-10-26 12:00:19 +08:00
parent c42eb4b33c
commit b50315bb86
2 changed files with 23 additions and 1 deletions
+21 -1
View File
@@ -51,5 +51,25 @@ export function accordion(props: AccordionProps): HTMLElement {
),
);
return h('div', { class: 'ua-accordion' }, ...rows);
const root = h('div', { class: 'ua-accordion' }, ...rows);
// —— 键盘导航:↑↓ 行间环形移动、Home/End 首尾直达,均跳过禁用行(对齐 tabs/tree 约定) ——
const heads = (): HTMLButtonElement[] => rows.map((r) => r.firstElementChild as HTMLButtonElement); // 各行标题按钮
const focusFrom = (start: number, dir: 1 | -1): void => {
const len = heads().length;
for (let n = 1; n <= len; n++) {
const cand = heads()[(((start + dir * n) % len) + len) % len]; // 环形取候选:越界回绕保证落在 [0, len)
if (!cand.disabled) { cand.focus(); return; } // 跳过禁用行,绕满一圈即止
}
};
root.addEventListener('keydown', (e: KeyboardEvent) => {
const list = heads();
const idx = list.indexOf(document.activeElement as HTMLButtonElement);
if (idx < 0) return; // 卫语句:焦点不在标题行
if (e.key === 'ArrowDown' || e.key === 'ArrowUp') { e.preventDefault(); focusFrom(idx, e.key === 'ArrowDown' ? 1 : -1); }
else if (e.key === 'Home') { e.preventDefault(); focusFrom(-1, 1); } // 从头正向找第一个可用
else if (e.key === 'End') { e.preventDefault(); focusFrom(0, -1); } // 从尾反向找最后一个可用
});
return root;
}