iter(g336): 表格行选择补读屏语义
This commit is contained in:
@@ -3410,6 +3410,15 @@
|
||||
"motivation": "库内 13 个组件都有 ariaLabel 入参(switchButton / pagination / jsonViewer / codeBlock …),偏偏最常用的四个输入件没有:textField 与 textarea 的控件上没有可访问名(只有清空 / 显隐按钮有),读屏进去只念「编辑框」;slider 的原生 range 无名,区间模式两个滑块更是完全同名,读屏分不出上下限;inputNumber 的「数字输入」写死,业务上没法改成「数量 / 单价」。",
|
||||
"acceptance": "① TextFieldProps / TextareaProps / InputNumberProps / SliderProps 增可选 ariaLabel,落成控件 aria-label(缺省沿用「文本输入」「多行文本」「数字输入」「数值」);② slider 区间模式自动拼「下限 / 上限」,两个 range 各有名字;③ inputNumber 的写死字符串改成可覆盖,与其余组件同一口径;④ 四份清单文档补 ariaLabel 参数行(verify 的双向字段校验要过);⑤ npm run check 全绿。",
|
||||
"notes": ""
|
||||
},
|
||||
{
|
||||
"id": "g336",
|
||||
"domain": "tune",
|
||||
"status": "open",
|
||||
"title": "表格行选择补读屏语义:复选框有名字,选中行有 aria-selected",
|
||||
"motivation": "selectable 表格里,表头全选框与每行复选框都没有可访问名,读屏连续播报「复选框、复选框、复选框」,用户不知道选的是哪一行;选中行的反馈只有一层淡底(视觉),tr 上没有 aria-selected,读屏完全听不出「这行已被选中」——批量操作前确认选对了没有,全靠眼睛。",
|
||||
"acceptance": "① 表头全选框 aria-label「全选本页」,行复选框「选择第 N 行」(与展开列的行号口径一致);② 选中行带 aria-selected(可点行按 selectable 给 true/false,不可点行只给 true),淡底仍作视觉层;③ dataTable 文档的 selectable 步骤同步说明;④ dataTable.ts 仍 ≤ 200 行(CODING.md 硬上限);⑤ npm run check 全绿。",
|
||||
"notes": ""
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
+2
-2
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"$schema": "ui-arch-registry-index/0.1",
|
||||
"generatedAt": "2026-10-26T18:08:56.364Z",
|
||||
"generatedAt": "2026-10-26T18:09:53.780Z",
|
||||
"repoRoot": ".",
|
||||
"packages": [
|
||||
{
|
||||
@@ -2181,7 +2181,7 @@
|
||||
"列展示细节用皮肤字段:align 控制表头与单元格对齐,format(value, row) 返回纯文本(走 textContent,不需要转义)",
|
||||
"数据源可以给信号或 computed(如筛选结果):变化时内核整体换源,选择状态按 rowKey 剔除已消失的行,排序与页码不被打断",
|
||||
"列宽用内核字段 width:数字(像素)固定该列,'flex' 或不设则按内容自适应",
|
||||
"selectable: true 开启行选择:表头全选框带 indeterminate 半选态,工具栏显示已选计数",
|
||||
"selectable: true 开启行选择:表头全选框带 indeterminate 半选态(aria-label「全选本页」),每行复选框读「选择第 N 行」、选中行标 aria-selected(淡底只是视觉),工具栏显示已选计数",
|
||||
"选中行用低视觉比重样式(淡色底 + 弱化文字),选择状态存 rowKey,跨页不丢失",
|
||||
"工具栏输入框即筛选,输入即时过滤并回第 1 页;无匹配时显示空状态行",
|
||||
"表头粘性固定(滚动容器 max-height 420px),斑马纹 + 悬停高亮由 CSS 提供",
|
||||
|
||||
+2
-2
@@ -1,6 +1,6 @@
|
||||
# @ui-arch 组件库 Agent 文档(无图形版)
|
||||
|
||||
> 自动生成于 2026-10-26T18:08:56.364Z,数据源:各包 ua.manifest.json,勿手改。人类版文档站:apps/docs/index.html。
|
||||
> 自动生成于 2026-10-26T18:09:53.780Z,数据源:各包 ua.manifest.json,勿手改。人类版文档站:apps/docs/index.html。
|
||||
> 组件 = 普通函数,传 props 返回 DOM;状态用 signal 双向绑定:读 signal() 写 signal(v)。
|
||||
|
||||
## 快速上手
|
||||
@@ -1060,7 +1060,7 @@ dataTable({ data: users, selectable: true, columns: [{ key: 'name', header: '姓
|
||||
4. 列展示细节用皮肤字段:align 控制表头与单元格对齐,format(value, row) 返回纯文本(走 textContent,不需要转义)
|
||||
5. 数据源可以给信号或 computed(如筛选结果):变化时内核整体换源,选择状态按 rowKey 剔除已消失的行,排序与页码不被打断
|
||||
6. 列宽用内核字段 width:数字(像素)固定该列,'flex' 或不设则按内容自适应
|
||||
7. selectable: true 开启行选择:表头全选框带 indeterminate 半选态,工具栏显示已选计数
|
||||
7. selectable: true 开启行选择:表头全选框带 indeterminate 半选态(aria-label「全选本页」),每行复选框读「选择第 N 行」、选中行标 aria-selected(淡底只是视觉),工具栏显示已选计数
|
||||
8. 选中行用低视觉比重样式(淡色底 + 弱化文字),选择状态存 rowKey,跨页不丢失
|
||||
9. 工具栏输入框即筛选,输入即时过滤并回第 1 页;无匹配时显示空状态行
|
||||
10. 表头粘性固定(滚动容器 max-height 420px),斑马纹 + 悬停高亮由 CSS 提供
|
||||
|
||||
@@ -61,7 +61,7 @@ export function dataTable<T extends { id: RowKey }>(props: DataTableProps<T>): H
|
||||
const span = (): number => shown().length + (selectable ? 1 : 0) + (props.renderDetail ? 1 : 0); // 跨列数随可见列与展开列变化
|
||||
|
||||
// —— 表头全选框:checked / indeterminate 三态跟随当页选中情况 ——
|
||||
const headCheck = h('input', { type: 'checkbox', class: 'ua-checkbox' }) as HTMLInputElement;
|
||||
const headCheck = h('input', { type: 'checkbox', class: 'ua-checkbox', 'aria-label': '全选本页' }) as HTMLInputElement; // 无名字的复选框读屏只念「复选框」
|
||||
headCheck.addEventListener('change', () => {
|
||||
if (headCheck.checked) api.selectAllVisible();
|
||||
else table.dispatch({ type: 'clearSelection' });
|
||||
@@ -137,15 +137,15 @@ export function dataTable<T extends { id: RowKey }>(props: DataTableProps<T>): H
|
||||
return h('td', { class: col.align ? `ua-align-${col.align}` : null, onclick: custom ? (e: MouseEvent) => e.stopPropagation() : null }, custom ?? (col.format ? col.format(raw, row) : String(raw))); // 无 render 退回纯文本(免注入);格内点击不触发整行回调
|
||||
});
|
||||
if (selectable) {
|
||||
const check = h('input', { type: 'checkbox', class: 'ua-checkbox' }) as HTMLInputElement; // 受控:选中态由内核 selection 决定
|
||||
const check = h('input', { type: 'checkbox', class: 'ua-checkbox', 'aria-label': `选择第 ${i + 1} 行` }) as HTMLInputElement; // 受控:选中态由内核 selection 决定;名字带行号,读屏才分得清选哪行
|
||||
check.checked = selected;
|
||||
check.addEventListener('change', () => table.dispatch({ type: 'toggleSelect', key }));
|
||||
cells.unshift(h('td', { class: 'ua-cell-check' }, check));
|
||||
}
|
||||
if (props.renderDetail) cells.unshift(expandCell(open, `第 ${i + 1} 行`, () => expanded(open ? expanded().filter((k) => k !== key) : [...expanded(), key]))); // 展开列在最前:与选择列并列但不互斥
|
||||
const rowProps = props.onRowClick // 传了才把整行做成可聚焦按钮语义(Tab 进入、Enter / 空格触发)
|
||||
? { tabindex: '0', class: `ua-row-clickable${selected ? ' ua-row-selected' : ''}`, onclick: () => props.onRowClick?.(row), onkeydown: (e: KeyboardEvent) => { if (e.key === 'Enter' || e.key === ' ') { e.preventDefault(); props.onRowClick?.(row); } } }
|
||||
: selected ? { class: 'ua-row-selected' } : null;
|
||||
? { tabindex: '0', class: `ua-row-clickable${selected ? ' ua-row-selected' : ''}`, 'aria-selected': selectable ? String(selected) : null, onclick: () => props.onRowClick?.(row), onkeydown: (e: KeyboardEvent) => { if (e.key === 'Enter' || e.key === ' ') { e.preventDefault(); props.onRowClick?.(row); } } }
|
||||
: selected ? { class: 'ua-row-selected', 'aria-selected': 'true' } : null; // 淡底是视觉,aria-selected 才是读屏能听到的「这行被选中」
|
||||
const tr = h('tr', rowProps, ...cells);
|
||||
return props.renderDetail && open ? [tr, detailRow(span(), props.renderDetail(row))] : [tr];
|
||||
});
|
||||
|
||||
@@ -2055,7 +2055,7 @@
|
||||
"列展示细节用皮肤字段:align 控制表头与单元格对齐,format(value, row) 返回纯文本(走 textContent,不需要转义)",
|
||||
"数据源可以给信号或 computed(如筛选结果):变化时内核整体换源,选择状态按 rowKey 剔除已消失的行,排序与页码不被打断",
|
||||
"列宽用内核字段 width:数字(像素)固定该列,'flex' 或不设则按内容自适应",
|
||||
"selectable: true 开启行选择:表头全选框带 indeterminate 半选态,工具栏显示已选计数",
|
||||
"selectable: true 开启行选择:表头全选框带 indeterminate 半选态(aria-label「全选本页」),每行复选框读「选择第 N 行」、选中行标 aria-selected(淡底只是视觉),工具栏显示已选计数",
|
||||
"选中行用低视觉比重样式(淡色底 + 弱化文字),选择状态存 rowKey,跨页不丢失",
|
||||
"工具栏输入框即筛选,输入即时过滤并回第 1 页;无匹配时显示空状态行",
|
||||
"表头粘性固定(滚动容器 max-height 420px),斑马纹 + 悬停高亮由 CSS 提供",
|
||||
|
||||
Reference in New Issue
Block a user