370 lines
37 KiB
JSON
370 lines
37 KiB
JSON
{
|
||
"$schema": "迭代点子库,status: open=待做 / done=已完成;按数组顺序取第一条 open 执行",
|
||
"items": [
|
||
{
|
||
"id": "b01",
|
||
"title": "新增 tooltip 组件",
|
||
"motivation": "皮肤包 16 组件缺少悬浮提示,表单与工具栏场景常用;可复用自绘弹层与微动画既有模式",
|
||
"acceptance": "packages/skin/ui 新增 tooltip.ts:content/message 简单 API,hover/focus 触发,延迟约 150ms 出场,带出入场微动画与 prefers-reduced-motion 兜底,只消费 --ua-* 令牌;导出并注册进 ua.manifest.json,文档站 props 表与 llms-full.txt 同步更新;npm run check 全绿",
|
||
"status": "done",
|
||
"notes": "API 定为 tooltip(props, trigger) 包裹式;delay 默认 150ms,Esc 立即收起,气泡 pointer-events:none 防抖,aria-describedby + role=tooltip 保证读屏可读;demo 新增 sec-tooltip 区块。顺带修复 ua style 对 https:// 的误判(先剥离字面量再定位 //)"
|
||
},
|
||
{
|
||
"id": "b02",
|
||
"title": "新增 toast 消息提示组件",
|
||
"motivation": "alert 是常驻块级元素,缺少轻量转瞬即逝的全局反馈;操作成功/失败场景刚需",
|
||
"acceptance": "新增 toast.ts:toast.success/error/warning/info 四个工厂函数,入参 {message, duration?},默认 3s 自动消失,右上角堆叠,语义色复用四档 variant,出入场微动画 + prefers-reduced-motion 兜底;导出、manifest、文档、llms-full.txt 同步;npm run check 全绿",
|
||
"status": "done",
|
||
"notes": "对外暴露 toast.info/success/warning/error(message, duration?) 四工厂 + showToast(props) 完整入参版;全局堆叠容器懒创建,role=status 无障碍;退场用 transitionend 移除并带 320ms 兜底(覆盖 reduced-motion 下 transition 不触发的情况);样式复用 alert 语义色 color-mix 模式,reduced-motion 列表已补 .ua-toast;demo 新增 sec-toast 区块"
|
||
},
|
||
{
|
||
"id": "b03",
|
||
"title": "新增 skeleton 骨架屏组件",
|
||
"motivation": "异步加载占位是数据表格与卡片的标配,配合 dataTable 空状态形成完整加载体验",
|
||
"acceptance": "新增 skeleton.ts:skeleton({variant: 'text'|'rect'|'circle', rows?}),呼吸/扫光微动画 + prefers-reduced-motion 静态化,只消费 --ua-* 令牌;导出、manifest、文档、llms-full.txt 同步;demo 页加一节演示;npm run check 全绿",
|
||
"status": "done",
|
||
"notes": "skeleton({variant, rows}):text(多行,末行缩短)/ rect / circle 三形状,扫光动画(::after 位移 + 渐变),reduced-motion 下静态灰块(动画列表已补 .ua-skeleton 与 ::after);demo 新增 sec-skeleton 卡片组合演示"
|
||
},
|
||
{
|
||
"id": "b04",
|
||
"title": "新增独立 pagination 分页器组件并与 dataTable 演示联动",
|
||
"motivation": "table-core 已有 pagination 插件,但皮肤包没有独立分页器;dataTable 演示也未展示分页联动",
|
||
"acceptance": "新增 pagination.ts:受控 API {page, pageSize, total, onChange},页码过多时折叠省略号,键盘可达,禁用态完整;demo 页 dataTable 一节增加分页联动演示;导出、manifest、文档、llms-full.txt 同步;npm run check 全绿",
|
||
"status": "done",
|
||
"notes": "pagination(props):page 信号双向绑定(受控),≤7 页全展开、更多时首尾 + 当前页 ±1 折叠省略号(renderList 重建),原生 button 键盘可达,aria-current / aria-label 完整,首末页禁用 ‹ ›;dataTable 新增可选 page 信号桥接(双向同步 + 越界钳制,防无效派发);demo sec-table 新增 pageSize 3 × 24 行的联动卡片"
|
||
},
|
||
{
|
||
"id": "b05",
|
||
"title": "文档站演示区由 manifest 驱动自动生成",
|
||
"motivation": "目前 apps/docs/index.html 手写 props 表与演示,每加组件都要人肉同步;由 manifest 单一来源驱动可消除重复维护",
|
||
"acceptance": "ua CLI 新增 docs-gen 逻辑:读取各组件 ua.manifest.json 中的 components 参数表,自动生成 props 表 HTML 片段注入文档站模板;生成结果与现有手写版信息量对齐(props 名/类型/默认值/说明);npm run check 全绿且文档站可正常打开",
|
||
"status": "done",
|
||
"notes": "核查确认 props 表/示例/步骤/演示 iframe 早已由 ua docs 从 manifest docs.components 单一来源驱动;真正的缺口是信息量不含默认值——本轮 CLI propsTable 新增「默认值」列(props 条目可选 df 字段,缺省渲染 —),llms-full.txt 参数行同步追加「默认 x」标注;16 处可机读默认值从描述文案提取进 df;check 全绿 + 文档站结构完整性校验通过"
|
||
},
|
||
{
|
||
"id": "c01",
|
||
"title": "button / checkbox / switch 补 disabled 禁用态",
|
||
"motivation": "三个基础交互组件缺禁用能力,表单只读/权限控制场景刚需",
|
||
"acceptance": "ButtonProps / CheckboxProps / SwitchProps 新增可选 disabled(boolean | Signal<boolean>):静态布尔与信号绑定都支持,禁用时事件不触发、置灰 + not-allowed 光标;demo 表单区加静态禁用与信号联动示例;manifest/文档/llms-full.txt 同步;npm run check 全绿",
|
||
"status": "done",
|
||
"notes": "零新增辅助代码:复用 frame h() 对 false/undefined 移除属性、Signal 函数走响应式绑定的既有语义,disabled 透传即可;CSS 补通用禁用态(opacity 0.45 + not-allowed,开关轨道同级置灰);demo 用同一 locked 信号绑定 switch 的 checked 与 checkbox 的 disabled 展示联动"
|
||
},
|
||
{
|
||
"id": "c02",
|
||
"title": "textField / textarea 补 disabled 禁用态",
|
||
"motivation": "输入类组件与 c01 的交互组件对齐,表单只读场景闭环",
|
||
"acceptance": "TextFieldProps / TextareaProps 新增可选 disabled(boolean | Signal<boolean>),禁用时不响应输入、置灰 + not-allowed 光标;demo 禁用示例区补一个信号绑定输入框;manifest/文档/llms-full.txt 同步;npm run check 全绿",
|
||
"status": "done",
|
||
"notes": "与 c01 同模式:disabled 透传 h() 即得布尔/信号双支持;禁用态 CSS 追加 .ua-input / .ua-textarea;demo 复用 locked 信号联动开关与输入框"
|
||
},
|
||
{
|
||
"id": "d01",
|
||
"title": "新增下拉菜单 menu 组件",
|
||
"motivation": "工具栏/行操作场景缺省可折叠的动作集合,select 只能选值不能派发动作;可复用自绘弹层与微动画既有模式",
|
||
"acceptance": "packages/skin/ui 新增 menu.ts:触发器 + 自绘弹层,items 支持 disabled / danger / divider,点条目 / 点外部 / Esc 关闭,↑↓ 环形导航(禁用项跳过),Enter/Space 选中,Esc 收起后焦点回触发器;只消费 --ua-* 令牌并带 prefers-reduced-motion 兜底;导出 + manifest + 文档 + llms-full.txt + demo 同步;npm run check 全绿",
|
||
"status": "done",
|
||
"notes": "API menu({ label, items, variant, align, onSelect });MenuItem = { value, label, disabled?, danger?, divider? };弹层 ua-open 同时挂在根与弹层(根管箭头旋转、弹层管出入场),危险条目取 danger 色;键盘 ↑↓ 环形导航 + Esc 回焦触发器;demo 新增 sec-menu 双示例(含禁用/危险/分隔线与右对齐)"
|
||
},
|
||
{
|
||
"id": "d02",
|
||
"title": "select / radioGroup 补 disabled,修复 select 箭头旋转失效",
|
||
"motivation": "c01/c02 已覆盖 button/checkbox/switch/输入类,选择类仍缺禁用;同时发现 select 的 .ua-select.ua-open 选择器永不命中(ua-open 只挂在弹层),展开时箭头不旋转",
|
||
"acceptance": "SelectProps / RadioGroupProps 新增可选 disabled(boolean | Signal<boolean>);禁用时 select 触发器置灰且不展开弹层,radioGroup 整组置灰不可选;select 箭头在展开时旋转 180°;demo 加信号禁用与静态禁用示例;manifest/文档/llms-full.txt 同步;npm run check 全绿",
|
||
"status": "done",
|
||
"notes": "disabled 仍走 h() 透传(原生 button/input 拦截交互)零辅助代码;select 根节点补 class 函数加 ua-open,箭头旋转选择器命中;CSS 通用禁用态列表并入 .ua-select-trigger 与 .ua-radio,另加 :has() 让单选行整行弱化、禁用触发器 hover 不改边框色"
|
||
},
|
||
{
|
||
"id": "d03",
|
||
"title": "新增折叠面板 accordion 组件",
|
||
"motivation": "长表单/设置页需要分区收起,皮肤包无折叠容器;grid 行高过渡可零测量实现展开动画",
|
||
"acceptance": "新增 accordion.ts:items(value/title/content/disabled)+ 单开(手风琴)与 multiple 多开,active 信号可选受控,标题为原生 button(aria-expanded/controls + region 关联),内容区 0fr→1fr 过渡且 reduced-motion 静态化;导出 / manifest / 文档 / llms-full.txt / demo 同步;npm run check 全绿",
|
||
"status": "done",
|
||
"notes": "contents 走 appendChild 既有语义,字符串/DOM/响应式函数通吃;未传 active 时内部 signal<string[]> 持有展开集合,受控模式只认 active 单开;CSS 用 grid-template-rows 0fr→1fr 过渡免测量,reduced-motion 列表补 ua-acc-*;demo 新增 sec-accordion(多开 + 禁用面板)"
|
||
},
|
||
{
|
||
"id": "d04",
|
||
"title": "dataTable 接加载态(骨架行 + 交互禁用)",
|
||
"motivation": "异步取数时表格直接闪空状态,缺少 loading 反馈;skeleton 已就位但未与表格打通",
|
||
"acceptance": "DataTableProps 新增 loading?: boolean | Signal<boolean>;为真时表体渲染骨架行(行数随 pageSize,列数含选择列)、筛选输入与上下页按钮禁用、容器 aria-busy=true;demo 加开关演示;manifest/文档/llms-full.txt 同步;npm run check 全绿",
|
||
"status": "done",
|
||
"notes": "busy() 读取器兼顾布尔与信号(信号在 renderList 内调用可被依赖收集);骨架行数量 Math.min(pageSize,6) 防过长;加载态优先于数据判断,避免闪出旧行;disabled 仍走 props 透传,零新增辅助组件"
|
||
},
|
||
{
|
||
"id": "d05",
|
||
"title": "新增面包屑 breadcrumb 组件",
|
||
"motivation": "多层级页面的位置指示缺失;顺带补齐导航类组件的语义结构(nav/ol/li + aria-current)",
|
||
"acceptance": "新增 breadcrumb.ts:nav + ol 语义结构,末项自动为当前页(不可点、aria-current=page),条目有 href 渲染 <a>、无 href 渲染 button 走 onNavigate,分隔符可配;只消费 --ua-* 令牌;导出 / manifest / 文档 / llms-full.txt / demo 同步;npm run check 全绿",
|
||
"status": "done",
|
||
"notes": "API breadcrumb({ items: {label, href?}[], separator?, onNavigate? });分隔符 aria-hidden;reduced-motion 列表补 .ua-crumb-link;demo 新增 sec-breadcrumb('›' 分隔 + toast 反馈跳转);首轮 style 门禁拦下多行 /*** 注释(检查器只认紧邻单行块),已改单行"
|
||
},
|
||
{
|
||
"id": "d06",
|
||
"title": "门禁新增 ua verify:清单 ↔ 文档 ↔ 演示锚点一致性校验",
|
||
"motivation": "新增组件靠人工同步 manifest/docs/demo,易漏(本轮已出现 badge/alert/spinner 手把手只有 2 步);把不变量机器化,防回归",
|
||
"acceptance": "CLI 新增 verify 子命令:docs.components 的 id 唯一且 api.exports 有 `${id}(` 或以 `${id}.` 开头条目、props 条目必备 n/t/d、steps ≥3、example 必填、demo 锚点必须存在于 apps/demo/main.ts;纳入 npm run check 链条;AGENTS.md 同步;npm run check 全绿",
|
||
"status": "done",
|
||
"notes": "锚点校验改看演示源码而非打包产物(demo.html 是 esbuild 产物,锚点在运行时生成);顺带补齐 badge/alert/spinner 的第 3 条手把手(说明与 button/skeleton 的分工);check 链变为 build→style→typecheck→smoke→index→verify"
|
||
},
|
||
{
|
||
"id": "d07",
|
||
"title": "新增可交互气泡卡片 popover 组件",
|
||
"motivation": "tooltip 只做纯展示(pointer-events:none),筛选面板/快捷操作需要可点击的浮层;与 tooltip 形成展示/交互分工",
|
||
"acceptance": "新增 popover.ts:popover(props, trigger) 包裹式,默认点击开合,trigger:'hover' 走延迟出场,点外部 / Esc 收起(Esc 回焦触发器),content 支持任意 DOM 且内部点击不误关,onOpenChange 回调;aria-haspopup/aria-expanded 正确;只消费 --ua-* 令牌 + reduced-motion 兜底;导出 / manifest / 文档 / llms-full.txt / demo 同步;npm run check 全绿",
|
||
"status": "done",
|
||
"notes": "触发器 click 内 stopPropagation,避免刚开就被 document 的外部点击关掉;aria-expanded 用 effect 写回(setAttribute 不吃函数值);弹层点击已阻止冒泡;demo 新增 sec-popover(含 checkbox+button 的筛选面板与 hover 触发示例)"
|
||
},
|
||
{
|
||
"id": "d08",
|
||
"title": "演示页加侧边目录与滚动高亮",
|
||
"motivation": "演示页已 14 个区块,长页滚动找区块靠手滑;目录同时给文档站 iframe 外的直接访问提供导航",
|
||
"acceptance": "demo 页改为 shell 双栏布局(左 sticky 目录 + 右内容),目录项挂载后从 .sec 自动反推(不手写清单),IntersectionObserver 高亮当前区块,窄屏(≤820px)隐藏目录,reduced-motion 下关平滑滚动;npm run check 全绿、demo 可正常构建",
|
||
"status": "done",
|
||
"notes": "目录由 buildToc 在 mount 后扫描 section.sec 生成(id + h2 文案),新增区块自动入目录无需维护;rootMargin -10%/-80% 让高亮更跟手;.page 去掉 max-width 由 .shell 统一控宽 1160"
|
||
},
|
||
{
|
||
"id": "d09",
|
||
"title": "新增滑块 slider 组件",
|
||
"motivation": "设置类场景(音量/阈值/预算)需要范围输入,皮肤包只有文本类输入;原生 range 自带键盘与触屏,接入成本低",
|
||
"acceptance": "新增 slider.ts:value 信号双向绑定(拖动写回 + 外部赋值同步),min/max/step 可配,disabled 支持布尔或信号,showValue 可关,onChange 回调;样式只消费 --ua-* 令牌(accent-color)且带聚焦光环与禁用态;导出 / manifest / 文档 / llms-full.txt / demo 同步;npm run check 全绿",
|
||
"status": "done",
|
||
"notes": "组件不持有数值,一律委托调用方信号;effect 内等值不重写 input.value,避免拖动过程被打断;轨道配色用 accent-color 令牌化,无需自绘 thumb;demo 新增 sec-slider(音量 step 5 + 与 locked 信号联动的禁用滑块)"
|
||
},
|
||
{
|
||
"id": "d10",
|
||
"title": "toast 补手动关闭与同屏堆叠上限",
|
||
"motivation": "自动消失前用户无法提前关掉(如已看清错误),且连续触发会无限堆叠淹没页面",
|
||
"acceptance": "ToastProps 新增 closable(显示 × 立即退场);同屏最多 4 条,超出挤掉最早一条;退场逻辑抽为内部 dismiss() 供自动/手动共用;is-closable 才接收指针事件,其余保持 pointer-events:none;manifest/文档/llms-full.txt/demo 同步;npm run check 全绿",
|
||
"status": "done",
|
||
"notes": "dismiss() 统一 transitionend + 320ms 双保险;超限用 firstElementChild.remove() 立即腾位(不走动画,保证硬上限);demo sec-toast 增加「可关闭」按钮演示 showToast({closable:true})"
|
||
},
|
||
{
|
||
"id": "d11",
|
||
"title": "modal 补 size 档位与 footer 操作区",
|
||
"motivation": "弹窗内容宽窄差异大(确认框 vs 表单),底部操作按钮只能塞进 body 导致分割线语义缺失",
|
||
"acceptance": "ModalProps 新增 size?: 'sm'|'md'|'lg'(340/420/640)与 footer?: unknown;footer 渲染右对齐操作区带上分割线;缺省行为与旧版一致;manifest/文档/llms-full.txt/demo 同步;npm run check 全绿",
|
||
"status": "done",
|
||
"notes": "宽度档位用 .ua-modal-sm/lg 覆盖基准 md,基础宽 min(420px,90vw) 不动;footer 仅在传入时渲染(null 分支不进 DOM);demo 的弹窗改为 size:'lg' + 取消/确定 footer 按钮"
|
||
},
|
||
{
|
||
"id": "d12",
|
||
"title": "新增可关闭标签 tag 组件",
|
||
"motivation": "badge 纯展示无法移除,筛选条件/已选关键字需要带 × 的标签;补齐 badge 的交互版",
|
||
"acceptance": "新增 tag.ts:label + variant 五档 + closable/onClose;closable 时渲染带 aria-label 的 × 按钮;只消费 --ua-* 令牌;导出 / manifest / 文档 / llms-full.txt / demo 同步;npm run check 全绿",
|
||
"status": "done",
|
||
"notes": "组件无状态:onClose 只通知,节点由调用方按信号重渲染移除(与 form/formItem 返回句柄、dataTable 委托内核的哲学一致);demo 用 signal<string[]> + renderList 演示真实删除链路,另有四档语义色静态展示"
|
||
},
|
||
{
|
||
"id": "d13",
|
||
"title": "dataTable 列定义支持对齐与单元格格式化",
|
||
"motivation": "皮肤层只能 String() 原始值,数字列无法右对齐、年龄/金额无法加单位;内核不关心展示,字段应留在皮肤层",
|
||
"acceptance": "新增皮肤层 TableColumn<T> extends ColumnDef<T>,追加 align?: left|center|right 与 format?: (value,row)=>string;DataTableProps.columns 改用它;表头与单元格共用对齐类;format 走 textContent 天然免注入;demo 表格演示年龄右对齐+单位、城市居中;manifest/文档/llms-full.txt 同步;npm run check 全绿",
|
||
"status": "done",
|
||
"notes": "严格分层:内核 ColumnDef 不动,展示字段只在 skin 的 TableColumn 上扩展(extends 而非改核心);对齐类同时作用于 th(取代原 class 函数,合并 ua-sortable);demo 首表展示 align:right + format(v=>`${v} 岁`)、城市居中"
|
||
},
|
||
{
|
||
"id": "d14",
|
||
"title": "新增抽屉 drawer 组件",
|
||
"motivation": "详情查看/编辑需要不打断主视图的侧滑容器,modal 是强打断确认;移动端尤其常用",
|
||
"acceptance": "新增 drawer.ts:open 信号驱动,placement 左右、width 可调(窄屏 92vw 上限)、footer 操作区、遮罩 / × / Esc 关闭、打开聚焦首个可交互元素;只消费 --ua-* 令牌 + reduced-motion 兜底;导出 / manifest / 文档 / llms-full.txt / demo 同步;npm run check 全绿",
|
||
"status": "done",
|
||
"notes": "遮罩开合用 opacity+visibility(与 tooltip/popover 同模式),面板靠 transform:translateX 滑入;width 走 inline style(调用方数据驱动的表现值不进 CSS);demo 新增 sec-drawer(订单详情 + footer 关闭 + tag/badge 组合)"
|
||
},
|
||
{
|
||
"id": "d15",
|
||
"title": "CLI 包补 ua.manifest.json 并修正文档里的过期组件数",
|
||
"motivation": "工具链自身不在注册表里,Agent 无法通过 MCP/llms 发现 ua 的 6 个子命令;AGENTS.md 与 ARCHITECTURE.md 仍写 17 个组件(实际 27)",
|
||
"acceptance": "packages/tools/cli/ua.manifest.json(type: tooling)描述 index/list/info/docs/style/verify/mcp 七个子命令与约定,索引包数变 5;AGENTS.md 与 ARCHITECTURE.md 的组件数改成 27;llms.txt / llms-full.txt 重新生成且 CLI 段落可读;npm run check 全绿",
|
||
"status": "done",
|
||
"notes": "tooling 类型在 ORDER 表外,排序自然落到末尾(??9 兜底),无需改 CLI 排序逻辑;CLI 清单 docs.components 留空,故不参与 verify 的组件级校验;顺带确认 docs 生成对无组件包不报错"
|
||
},
|
||
{
|
||
"id": "d16",
|
||
"title": "dataTable 落地内核已定义的列宽 width",
|
||
"motivation": "table-core 的 ColumnDef 声明了 width?: number | 'flex',但皮肤层从未消费,列宽完全靠浏览器猜;契约与实现脱节",
|
||
"acceptance": "dataTable 渲染 colgroup:数字 width 落成固定像素 <col>,'flex' 或不设交给自适应,选择列固定 44px;demo 表格演示 name 160 / age 100 / city flex;manifest 列定义说明与手把手同步;npm run check 全绿",
|
||
"status": "done",
|
||
"notes": "用 colgroup 而非逐 th 设宽,保证表头与表体一致且不入侵单元格渲染;未开 table-layout:fixed(nowrap 内容会被裁),宽高仍由内容兜底;pinned 固定列仍未消费(多列 sticky 偏移需测量),留作后续条目"
|
||
},
|
||
{
|
||
"id": "d17",
|
||
"title": "表单错误态覆盖包裹式控件并修正校验时机事件",
|
||
"motivation": "① 现有 blur 不冒泡,checkbox/select/radioGroup 这类包裹式控件失焦永远不校验;② ua-invalid 只加在控件根,自绘 select 的边框在内部触发器上,视觉上无错误提示;③ 缺 aria-invalid,读屏感知不到",
|
||
"acceptance": "formItem 用 focusout 取代 blur、补 change(select/checkbox 变更即校验);错误态同时落到控件根与内部原生控件,并同步 aria-invalid;CSS 覆盖 .ua-invalid 后代 .ua-input/.ua-textarea/.ua-select-trigger/.ua-radio/.ua-slider-input;demo 表单加必填 select 演示;manifest/文档/llms-full.txt 同步;npm run check 全绿",
|
||
"status": "done",
|
||
"notes": "marked() 统一收集控件根 + 内部 input/textarea/select/.ua-select-trigger 两处落点;.ua-invalid 后代选择器让包裹式控件描红,无需组件各自改签名(低侵入);demo formlab 新增城市必填 select,提交结果显示城市"
|
||
},
|
||
{
|
||
"id": "d18",
|
||
"title": "把「皮肤包禁止硬编码颜色」做成 ua verify 门禁",
|
||
"motivation": "AGENTS.md 写着皮肤禁硬编码颜色,但一直靠自觉;ui.css 实际残留 5 处 #fff(按钮/徽标/开关滑块),暗色下对比也不理想",
|
||
"acceptance": "checkSkinCss():skin-dom 类型包里所有 .css 出现 #hex 字面量即报错并指出文件行号;5 处 #fff 改为 var(--ua-color-bg)(信号色底上的反色,暗色自动翻转);负向测试(临时加 .ua-tmp{color:#fff})能拦下,移除后回归全绿;AGENTS.md 门禁说明同步;npm run check 全绿",
|
||
"status": "done",
|
||
"notes": "rgba(...) 未禁:仅用于阴影与遮罩透明度叠加,不承载品牌色,禁掉会逼出更难读的写法(已在函数注释写明边界);实现上先随 python 写文件把正则转义搞坏两次,改用编辑工具直写并做负向验证确认门禁真实生效"
|
||
},
|
||
{
|
||
"id": "d19",
|
||
"title": "dataTable 选中态受控(selected 信号)",
|
||
"motivation": "选中集只在内核里,外部拿不到也无法预设,批量操作/清空选择只能靠内部工具栏;与 page 受控桥接形成对称能力",
|
||
"acceptance": "DataTableProps 新增 selected?: Signal<RowKey[]>,与内核选择双向同步(内容比较避免来回派发,外部数组拷贝保护内核);demo 首表传 picked 信号,展示已选计数与「清空选择」按钮;manifest/文档/llms-full.txt 同步;npm run check 全绿",
|
||
"status": "done",
|
||
"notes": "复用 page 桥接的同一套思路:两个 effect 各管一向,sameKeys 内容比较收敛;内部写回拷贝 [...internal],防外部改动内核数组;demo 需 import type { RowKey } 才能对齐 Signal 的逆变"
|
||
},
|
||
{
|
||
"id": "d20",
|
||
"title": "progress 支持不确定态(未知时长加载)",
|
||
"motivation": "请求时长未知时只能硬编造一个假百分比,或用 spinner 但失去条状形态;不确定态是进度条的标准形态",
|
||
"acceptance": "ProgressProps.value 改为可选;缺省时渲染不确定态(35% 填充块 1.2s 往复)、不显示百分比、role=progressbar + aria-label=进行中;定量态补 aria-valuemin/max/now;reduced-motion 静态化;demo 加不确定态示例;manifest/文档/llms-full.txt 同步;npm run check 全绿",
|
||
"status": "done",
|
||
"notes": "以「不传 value」作为不确定态的开关,不新增布尔参数(少一个可矛盾的状态);定量态的 aria-valuenow 用函数属性随信号更新;reduced-motion 下靠既有 .ua-progress-fill 规则把动画归零,退化为静态 35% 条"
|
||
},
|
||
{
|
||
"id": "d21",
|
||
"title": "无障碍收尾:× 按钮 aria-label、spinner/skeleton 语义、tablist 标签",
|
||
"motivation": "审计发现 modal 的 × 按钮无 aria-label(读屏只念「×」)、spinner 无 role=status(不播报加载)、skeleton 未 aria-hidden(占位文本被读出来)、tablist 缺 aria-label 与 aria-disabled",
|
||
"acceptance": "modal 关闭按钮补 type/aria-label、spinner 补 role=status + aria-label、skeleton 全形态 aria-hidden、tabs 的 tablist 补 aria-label 且禁用页签标 aria-disabled;manifest conventions 记录无障碍基线;npm run check 全绿",
|
||
"status": "done",
|
||
"notes": "纯属性级修复,不动结构与样式;tabIndex 漫游(仅激活页签可 Tab)此前已实现,本次只补语义;分页器审计后无需改动(已有 nav aria-label、页码 aria-current、‹› aria-label)"
|
||
},
|
||
{
|
||
"id": "d22",
|
||
"title": "新增头像 avatar 组件",
|
||
"motivation": "用户列表/评论区需要头像位,缺 component 只能手拼 img + 圆角;首字占位是缺图时的标准兜底",
|
||
"acceptance": "新增 avatar.ts:name 必填(alt / title / 首字来源),src 可选(有则图片、无则首字占位),size 可调,variant 四档语义底色;只消费 --ua-* 令牌;导出 / manifest / 文档 / llms-full.txt / demo 同步;npm run check 全绿",
|
||
"status": "done",
|
||
"notes": "首字占位对中文取首字、英文大写,空名兜底 ?;flex:none 保证不被挤压;首次跑 verify 被自身新门禁拦下(声明 sec-avatar 但 demo 缺区块),补独立区块后通过——门禁有效性再次得到验证"
|
||
},
|
||
{
|
||
"id": "d23",
|
||
"title": "alert 补标题行与可关闭,并补 role=alert",
|
||
"motivation": "常驻提示无法消除(错误已处理完仍占版面),且只有单层正文放不下「结论 + 详情」;role=alert 缺失导致读屏不播报",
|
||
"acceptance": "AlertProps 新增 title? / closable? / onClose?;关闭时先退场(opacity+上移,200ms)再从 DOM 移除;容器 role=alert;只消费 --ua-* 令牌;demo 新增 sec-alert 展示无标题与可关闭带标题两种;manifest/文档/llms-full.txt 同步;npm run check 全绿",
|
||
"status": "done",
|
||
"notes": "与 toast 的分工保持:alert 常驻在页面流里、toast 全局浮动;关闭后由调用方自行决定是否重新渲染;body/title/message 三层结构让 flex 布局能把 × 对齐到首行;对现有 alert({message}) 调用完全兼容"
|
||
},
|
||
{
|
||
"id": "d24",
|
||
"title": "重写 README 并把组件清单纳入 verify 防漂移",
|
||
"motivation": "README 只有标题一行,新人/Agent 从仓库首页拿不到任何信息;而文档里的组件数此前已经漂移过(17 vs 27)",
|
||
"acceptance": "README 覆盖定位 / 快速开始 / 28 组件清单 / 目录表 / 三道门禁 / Agent 接入 / 分支流水线;新增 <!-- ua:components --> 标记区块,ua verify 校验区块 id 集合与全部清单 docs.components 完全一致(缺/多都报);负向测试(删 avatar)能拦下;AGENTS.md 同步;npm run check 全绿",
|
||
"status": "done",
|
||
"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 字体避免等宽字跳脱整体排版"
|
||
},
|
||
{
|
||
"id": "d26",
|
||
"title": "select 键盘导航:↑↓ 环形移动、Home/End 跳转、Esc 回焦触发器",
|
||
"status": "done"
|
||
},
|
||
{
|
||
"id": "d27",
|
||
"title": "modal 焦点陷阱:Tab/Shift+Tab 回绕、role=dialog/aria-modal、关闭归还焦点",
|
||
"status": "done"
|
||
},
|
||
{
|
||
"id": "d28",
|
||
"title": "drawer 焦点陷阱:Tab/Shift+Tab 回绕、关闭归还焦点(对齐 modal)",
|
||
"status": "done"
|
||
},
|
||
{
|
||
"id": "d29",
|
||
"title": "menu 补 Home/End 跳转,与 select 键盘导航对称",
|
||
"status": "done"
|
||
},
|
||
{
|
||
"id": "e01",
|
||
"title": "新增 inputNumber 数字输入组件",
|
||
"motivation": "数量、份数等离散数值输入是表单常见场景,纯 textField 缺少步进语义;加减按钮 + 键盘调节可复用既有 button 与信号双向绑定模式",
|
||
"acceptance": "packages/skin/ui 新增 inputNumber.ts:−/+ 按钮 + 输入框三段式,value 信号双向绑定,min/max/step 超界自动夹取,键盘 ↑↓ 调节,非法输入回滚,disabled 支持布尔或信号;只消费 --ua-* 令牌;导出、manifest、文档、llms-full.txt 同步;demo 加一节演示;npm run check 全绿",
|
||
"status": "done",
|
||
"notes": "inputNumber(props):−/+ 复用 ghost button(自带微动画与 disabled 透传),输入框 inputmode=decimal,change 时 parseFloat 解析、非法回滚当前值;↑↓ 步进并 preventDefault;clamp 统一夹取 min/max(缺省 ±Infinity);aria-label 三件套 + role=group;CSS 步进按钮收窄、tabular-nums;demo 新增 sec-inputnumber(与禁用态实例共用 qty 信号);manifest/docs/llms-full/README 同步为 29 组件"
|
||
},
|
||
{
|
||
"id": "e02",
|
||
"title": "新增 stepper 步骤条组件",
|
||
"motivation": "下单、注册等多步流程需要进度指示与回跳,现有导航类组件(tabs/breadcrumb/pagination)都不覆盖分步语义;纯展示 + 可选点击回跳,改动范围可控",
|
||
"acceptance": "packages/skin/ui 新增 stepper.ts:stepper({steps, active, clickable?, onChange?}),done/current/upcoming 三态视觉,clickable 时已完成步骤可点回跳并写回 active 信号,aria-current=step;只消费 --ua-* 令牌;导出、manifest、文档、llms-full.txt、README 清单同步;demo 加一节演示;npm run check 全绿",
|
||
"status": "done",
|
||
"notes": "stepper(props):active 信号变化整条重渲染(effect 首跑赋值 + replaceWith,条目少开销可忽略);done 显示 ✓、current 光环聚焦、upcoming 弱化,aria-current=step;clickable 时已完成步骤渲染为 button 回跳写回信号;连接线用 .ua-step + .ua-step::before 横向短线;demo 新增 sec-stepper(上一步/下一步按钮 computed 禁用联动);README 同步 30 组件"
|
||
},
|
||
{
|
||
"id": "e03",
|
||
"title": "新增 rate 评分组件",
|
||
"motivation": "评价、打分场景常用,现有组件无覆盖;星标交互可完整复用信号双向绑定与微动画审美约定,单文件可控",
|
||
"acceptance": "packages/skin/ui 新增 rate.ts:rate({value, max?, disabled?, onChange?}),max 缺省 5,hover 预览移出还原,键盘 ←→/↑↓ 调节,aria 星标语义;只消费 --ua-* 令牌;导出、manifest、文档、llms-full.txt、README 清单同步;demo 加一节演示;npm run check 全绿",
|
||
"status": "done",
|
||
"notes": "rate(props):hover 预览用组件内局部 hover 信号(容器 mouseleave 归零),shown = hover || value 决定点亮数;value/hover 变化整条重渲染(与 stepper 同款 effect + replaceWith 模式);键盘 →/↑ 加分 ←/↓ 减分并 clamp [1,max];role=slider + aria-valuenow;选中色取 --ua-color-warning 金黄;demo 新增 sec-rate(可交互 + 只读两实例共用 score 信号);README 同步 31 组件"
|
||
},
|
||
{
|
||
"id": "e04",
|
||
"title": "新增 empty 空状态组件",
|
||
"motivation": "列表、表格、搜索无结果时需要统一的占位提示,dataTable 内置空态样式但独立场景(卡片、面板、筛选结果)没有可复用组件",
|
||
"acceptance": "packages/skin/ui 新增 empty.ts:empty({title?, description?, action?}),居中排版,action 为可选 DOM 操作区(常见放按钮);只消费 --ua-* 令牌;导出、manifest、文档、llms-full.txt、README 清单同步;demo 加一节演示;npm run check 全绿",
|
||
"status": "done",
|
||
"notes": "empty(props):纯静态组件(无信号),role=status 由读屏播报;装饰符号 ⌀ 弱化为边框色且 aria-hidden;min-height 120px 撑留白(令牌只到 space-4);demo 新增 sec-empty(信号切换有数据/无结果对比,内容用响应式函数渲染);README 同步 32 组件"
|
||
},
|
||
{
|
||
"id": "e05",
|
||
"title": "新增 divider 分隔线组件",
|
||
"motivation": "表单分组、卡片内区块、工具栏之间需要统一分隔语义,目前只有 menu 内部私有分隔线,独立场景无组件可用",
|
||
"acceptance": "packages/skin/ui 新增 divider.ts:divider({label?, vertical?, dashed?}),水平/垂直两种方向,可带居中文案标签;只消费 --ua-* 令牌;导出、manifest、文档、llms-full.txt、README 清单同步;demo 加一节演示;npm run check 全绿",
|
||
"status": "done",
|
||
"notes": "divider(props):水平线用 ::before/::after 双线夹 label 居中文案;vertical 单线(伪元素清空,dashed 走 border-left);dashed 水平线 border-top 替代背景色;role=separator + aria-label;demo 新增 sec-divider(文案线/虚线/工具栏竖线三种用法);README 同步 33 组件"
|
||
},
|
||
{
|
||
"id": "f01",
|
||
"title": "组件数漂移治理:AGENTS/ARCHITECTURE 数字纳入 verify 门禁",
|
||
"motivation": "组件数第三次漂移(AGENTS.md 与 ARCHITECTURE.md 仍写 27,实际 33),ua verify 只锁 README 区块锁不住散文数字",
|
||
"acceptance": "ua verify 新增规则:扫描 AGENTS.md 与 ARCHITECTURE.md 中的「NN 个组件」模式数字,与 manifest docs.components 长度比对不一致即报错;当前两处 27 改为 33;npm run check 全绿",
|
||
"status": "open",
|
||
"notes": "来源:2026-10-23 第二次冷启动审计应修 #1"
|
||
},
|
||
{
|
||
"id": "f02",
|
||
"title": "check 链描述同步:AGENTS.md 与 ITERATION.md 补 verify 第六步",
|
||
"motivation": "AGENTS.md:10 与 ITERATION.md:31 写 5 步,package.json 实为 6 步(含 verify),文档与实际门禁不一致",
|
||
"acceptance": "两处描述改为 build → style → typecheck → smoke → index → verify 六步;npm run check 全绿",
|
||
"status": "open",
|
||
"notes": "来源:审计应修 #2"
|
||
},
|
||
{
|
||
"id": "f03",
|
||
"title": "新增 ua lint-iterations 门禁:留痕格式机器校验",
|
||
"motivation": "iterations.log 41 行中 36 行违规(time 字段混用、UTC 时间戳、缺 commit),靠人工反复修补,规范缺机器校验",
|
||
"acceptance": "ua 新增 lint-iterations 子命令:校验每行 JSON 字段恰为 {ts,id,result,commit,summary}、ts 为本地 +08:00 ISO 且可用 Date 解析、commit 为 7-40 位哈希或 aborted 时允许为空、result 枚举 done/aborted;并入 npm run check;历史 36 条违规行按规范修复(ts 以对应 git 提交的 author date 本地时区回填,commit 补哈希);npm run check 全绿",
|
||
"status": "open",
|
||
"notes": "来源:审计应修 #3;历史行修复用 git log --format=%cI 按条目 id 关联提交时间回填"
|
||
},
|
||
{
|
||
"id": "f04",
|
||
"title": "commit-lint 收严:chore/docs 等强制 scope,杜绝无 scope 放行",
|
||
"motivation": "COMMITTING.md 规定 <type>(<scope>) 格式,但 chore:、docs: 无 scope 被 lint 放行,历史还有 17 条 iter: 缺 scope",
|
||
"acceptance": "commit-lint 规则收严为:除 Merge 外所有 type 必须带 scope(scope 允许 cli/skin/core/backlog/留痕等枚举或条目 id);反向用例 chore: xxx / docs: xxx / iter: xxx 必须被拒;正例全部通过;npm run check 全绿",
|
||
"status": "open",
|
||
"notes": "来源:审计应修 #4;历史 iter 缺 scope 的提交不回改(已发布历史不动),只管增量"
|
||
},
|
||
{
|
||
"id": "f05",
|
||
"title": "ua index 幂等化:generatedAt 仅内容变化时更新",
|
||
"motivation": "ua index 每次重写 .ua/index.json 的 generatedAt,npm run check 必然弄脏工作区,与「提交前 check」工作流冲突",
|
||
"acceptance": "index 命令改为:若除 generatedAt 外内容与现有文件一致则不写入(或 generatedAt 改为内容哈希派生);连续两次 npm run check 后 git status 必须干净",
|
||
"status": "open",
|
||
"notes": "来源:审计应修 #5"
|
||
},
|
||
{
|
||
"id": "f06",
|
||
"title": "pnpm-lock.yaml 入库 + 目录树补全",
|
||
"motivation": "lockfile 缺失导致依赖树不可复现;ARCHITECTURE.md 目录树缺 scripts/、COMMITTING.md、ITERATION.md、.ua/ 清单等条目,新代理接手有盲区",
|
||
"acceptance": "pnpm-lock.yaml 提交入库;ARCHITECTURE.md 目录树补 scripts/(gitea.mjs/gitea-api.mjs 一句话说明)、COMMITTING.md、ITERATION.md、.ua/backlog.json、.ua/iterations.log、pnpm-workspace.yaml;npm run check 全绿",
|
||
"status": "open",
|
||
"notes": "来源:审计应修 #6 + 建议 #7"
|
||
}
|
||
]
|
||
}
|