From 4012923ff11550495aed64ccd959e832e5d2dc33 Mon Sep 17 00:00:00 2001 From: ui-arch-bot Date: Fri, 23 Oct 2026 17:00:55 +0800 Subject: [PATCH] =?UTF-8?q?iter:=20d18=20=E7=A1=AC=E7=BC=96=E7=A0=81?= =?UTF-8?q?=E9=A2=9C=E8=89=B2=E9=97=A8=E7=A6=81=20+=20=E6=B8=85=E6=8E=89?= =?UTF-8?q?=20ui.css=20=E6=AE=8B=E7=95=99=20#fff?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .ua/backlog.json | 8 ++++++++ .ua/index.json | 2 +- .ua/iterations.log | 1 + AGENTS.md | 2 +- llms-full.txt | 2 +- packages/skin/ui/ui.css | 10 +++++----- packages/tools/cli/bin/ua.js | 19 ++++++++++++++++++- 7 files changed, 35 insertions(+), 9 deletions(-) diff --git a/.ua/backlog.json b/.ua/backlog.json index df04310..3c64d07 100644 --- a/.ua/backlog.json +++ b/.ua/backlog.json @@ -192,6 +192,14 @@ "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 写文件把正则转义搞坏两次,改用编辑工具直写并做负向验证确认门禁真实生效" } ] } diff --git a/.ua/index.json b/.ua/index.json index d8660c5..4cf45bf 100644 --- a/.ua/index.json +++ b/.ua/index.json @@ -1,6 +1,6 @@ { "$schema": "ui-arch-registry-index/0.1", - "generatedAt": "2026-10-23T08:59:45.207Z", + "generatedAt": "2026-10-23T09:00:48.440Z", "repoRoot": ".", "packages": [ { diff --git a/.ua/iterations.log b/.ua/iterations.log index 0246e0c..ea33f86 100644 --- a/.ua/iterations.log +++ b/.ua/iterations.log @@ -22,3 +22,4 @@ {"time": "2026-10-23T16:57:22+08:00", "id": "d15", "result": "done", "summary": "CLI 包补 ua.manifest.json(type: tooling,七个子命令 + 约定),注册表 5 包;修正 AGENTS/ARCHITECTURE 过期组件数 17→27;check 全绿"} {"time": "2026-10-23T16:58:51+08:00", "id": "d16", "result": "done", "summary": "dataTable 消费内核列宽 width:colgroup 固定像素 / flex 自适应,选择列 44px;demo 三列演示宽档;manifest/llms 同步,check 全绿"} {"time": "2026-10-23T16:59:46+08:00", "id": "d17", "result": "done", "summary": "表单错误态打通包裹式控件:focusout/change 取代 blur + aria-invalid + .ua-invalid 后代选择器覆盖 select/radio/slider;demo 加必填 select;check 全绿"} +{"time": "2026-10-23T17:00:55+08:00", "id": "d18", "result": "done", "summary": "ua verify 新增皮肤硬编码颜色门禁(#hex 禁止,rgba 仅限阴影/遮罩),清掉 ui.css 5 处 #fff 改令牌;负向测试确认能拦;check 全绿"} diff --git a/AGENTS.md b/AGENTS.md index 47eebe2..19c82c0 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -27,7 +27,7 @@ - `apps/demo`(@ui-arch/demo):交互演示,产物 apps/demo/dist/demo.html - `apps/docs`:文档站,纯产物(ua docs 生成) -**门禁一条龙**:`npm run check` = build + style + typecheck + smoke + index + verify,提交前必过。`ua verify` 校验清单 ↔ 文档 ↔ 演示锚点一致(docs.components 的 id 必须在 api.exports 有对应条目、props 必须带 n/t/d、demo 锚点必须在 `apps/demo/main.ts` 中存在)。 +**门禁一条龙**:`npm run check` = build + style + typecheck + smoke + index + verify,提交前必过。`ua verify` 校验清单 ↔ 文档 ↔ 演示一致(docs.components 的 id 必须在 api.exports 有对应条目、props 必须带 n/t/d、demo 锚点必须在 `apps/demo/main.ts` 中存在),并检查皮肤包样式表无硬编码颜色(`#hex` 一律禁止,必须走 `--ua-*` 令牌)。 ## Agent 查询组件库的三种方式 diff --git a/llms-full.txt b/llms-full.txt index 7a66a54..81ed03d 100644 --- a/llms-full.txt +++ b/llms-full.txt @@ -1,6 +1,6 @@ # @ui-arch 组件库 Agent 文档(无图形版) -> 自动生成于 2026-10-23T08:59:45.207Z,数据源:各包 ua.manifest.json,勿手改。人类版文档站:apps/docs/index.html。 +> 自动生成于 2026-10-23T09:00:48.440Z,数据源:各包 ua.manifest.json,勿手改。人类版文档站:apps/docs/index.html。 > 组件 = 普通函数,传 props 返回 DOM;状态用 signal 双向绑定:读 signal() 写 signal(v)。 ## 快速上手 diff --git a/packages/skin/ui/ui.css b/packages/skin/ui/ui.css index 3e9ffed..8bdd687 100644 --- a/packages/skin/ui/ui.css +++ b/packages/skin/ui/ui.css @@ -28,7 +28,7 @@ .ua-btn-danger { background: var(--ua-color-danger); border-color: var(--ua-color-danger); - color: #fff; + color: var(--ua-color-bg); } .ua-input { min-width: 200px; @@ -207,7 +207,7 @@ width: 16px; height: 16px; border-radius: 50%; - background: #fff; + background: var(--ua-color-bg); transition: left 0.2s; } .ua-switch-input:checked + .ua-switch-track { @@ -652,15 +652,15 @@ } .ua-badge-success { background: var(--ua-color-success); - color: #fff; + color: var(--ua-color-bg); } .ua-badge-warning { background: var(--ua-color-warning); - color: #fff; + color: var(--ua-color-bg); } .ua-badge-danger { background: var(--ua-color-danger); - color: #fff; + color: var(--ua-color-bg); } /* —— 提示条 —— */ diff --git a/packages/tools/cli/bin/ua.js b/packages/tools/cli/bin/ua.js index e7c5b0b..127ee68 100644 --- a/packages/tools/cli/bin/ua.js +++ b/packages/tools/cli/bin/ua.js @@ -560,6 +560,22 @@ function cmdStyle() { console.log(`style OK (${files.length} files)`); } +/*** 皮肤包硬编码颜色检查:#hex 字面量一律禁止,颜色必须走 --ua-* 令牌(rgba 仅限阴影/遮罩的透明度叠加) ***/ +function checkSkinCss(pkg) { + const issues = []; + const dir = path.join(ROOT, pkg.dir); + if (!fs.existsSync(dir)) return issues; + for (const name of fs.readdirSync(dir)) { + if (!name.endsWith('.css')) continue; // 只查样式表 + const file = path.join(dir, name); + const lines = fs.readFileSync(file, 'utf8').split(/\r?\n/); + lines.forEach((line, i) => { + if (/#[0-9a-fA-F]{3,8}\b/.test(line)) issues.push(`${pkg.dir}/${name}:${i + 1} 皮肤包禁止硬编码颜色,改用 --ua-* 令牌`); + }); + } + return issues; +} + /*** 清单一致性校验:组件文档块的 id / props 说明 / demo 锚点必须与代码和演示产物对齐 ***/ function cmdVerify() { const issues = []; @@ -571,6 +587,7 @@ function cmdVerify() { for (const pkg of collectManifests()) { const comps = pkg.docs?.components ?? []; // 清单已被 collectManifests 摊平 const exports = pkg.api?.exports ?? []; + if (pkg.type === 'skin-dom') issues.push(...checkSkinCss(pkg)); if (comps.length && !exports.length) issues.push(`${pkg.name}: docs.components 有 ${comps.length} 项但 api.exports 为空`); const seen = new Set(); // 组件 id 去重(同一清单内不允许重复) @@ -598,7 +615,7 @@ function cmdVerify() { console.error(`${issues.length} violation(s)`); process.exit(1); } - console.log('verify OK (manifest ↔ docs ↔ demo 一致)'); + console.log('verify OK (manifest ↔ docs ↔ demo 一致,皮肤无硬编码颜色)'); } // ---- 入口 ----