agentcss 0.11.10 → 0.11.11

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (36) hide show
  1. package/01-tokens/page.css +71 -0
  2. package/02-primitives/button/demo.html +5 -15
  3. package/02-primitives/card/demo.html +3 -13
  4. package/02-primitives/choice/demo.html +1 -0
  5. package/02-primitives/combobox/demo.html +38 -0
  6. package/02-primitives/date-range/demo.html +36 -0
  7. package/02-primitives/input/demo.html +5 -16
  8. package/02-primitives/popover/README.md +15 -0
  9. package/02-primitives/popover/demo.html +45 -0
  10. package/02-primitives/progress/demo.html +25 -0
  11. package/02-primitives/select/demo.html +46 -0
  12. package/02-primitives/skeleton/demo.html +28 -0
  13. package/03-patterns/content/demo.html +20 -0
  14. package/03-patterns/drawer/demo.html +36 -0
  15. package/03-patterns/dropdown/demo.html +39 -0
  16. package/03-patterns/list/demo.html +48 -0
  17. package/03-patterns/nav/demo.html +34 -1
  18. package/03-patterns/pagination/demo.html +40 -0
  19. package/03-patterns/reveal/demo.html +24 -0
  20. package/03-patterns/states/demo.html +25 -1
  21. package/03-patterns/tooltip/demo.html +27 -0
  22. package/03-patterns/tree/demo.html +43 -0
  23. package/04-recipes/analysis-report/demo.html +34 -0
  24. package/04-recipes/data-showcase/README.md +1 -0
  25. package/04-recipes/data-showcase/demo.html +29 -0
  26. package/04-recipes/detail-page/demo.html +28 -0
  27. package/04-recipes/report/demo.html +24 -0
  28. package/04-recipes/table/README.md +22 -0
  29. package/04-recipes/table/demo.html +39 -0
  30. package/CHANGELOG.md +68 -0
  31. package/CONTRIBUTING.md +2 -1
  32. package/ai/components.json +38 -10
  33. package/dist/01-tokens/page.css +1 -1
  34. package/dist/COSTS.md +1 -1
  35. package/index.html +1 -1
  36. package/package.json +1 -1
@@ -14,6 +14,12 @@
14
14
  <style>
15
15
  .toolbar { display: flex; gap: var(--sp-2); margin: 0 0 var(--sp-3); flex-wrap: wrap; }
16
16
  .section-note { margin: 0 0 var(--sp-3); }
17
+ .tb-demo { width: 100%; border-collapse: collapse; font-size: var(--fs-sm); }
18
+ .tb-demo th, .tb-demo td { padding: var(--sp-2) var(--sp-3); text-align: start;
19
+ border-bottom: 1px solid var(--border-decor); }
20
+ .tb-demo th { font-weight: 500; color: var(--text-secondary); font-size: var(--fs-xs); }
21
+ /* 反例专用:把库自动生成的 +/− 关掉,只留颜色(这就是"只靠红绿") */
22
+ .tb-bad .num--pos::before, .tb-bad .num--neg::before { content: none; }
17
23
  </style>
18
24
  </head>
19
25
  <body class="page">
@@ -86,6 +92,39 @@
86
92
  </p>
87
93
  <div id="escproof"></div>
88
94
 
95
+
96
+
97
+ <h2 class="rule-bottom">对比:错写法 vs 本库写法</h2>
98
+ <div class="cmp">
99
+ <div class="cmp__pane cmp__bad">
100
+ <h3>❌ 常见写法:只靠红绿 + 连字符</h3>
101
+ <div class="table tb-bad" aria-hidden="true">
102
+ <table class="tb-demo">
103
+ <thead><tr><th scope="col">板块</th><th scope="col" class="num">涨跌幅</th></tr></thead>
104
+ <tbody>
105
+ <tr><td>半导体</td><td class="num num--neg">-1.05%</td></tr>
106
+ <tr><td>白酒</td><td class="num num--pos">3.21%</td></tr>
107
+ <tr><td>光伏</td><td class="num num--neg">-12.40%</td></tr>
108
+ </tbody>
109
+ </table>
110
+ </div>
111
+ <p class="cmp__why">涨的那行没有 <code>+</code>,跌的用连字符 <code>-</code>:灰度打印、色觉障碍、以及"只扫一列符号"的读法,全都不成立;连字符还比真减号窄,一列数字的个位对不齐。</p>
112
+ </div>
113
+ <div class="cmp__pane cmp__good">
114
+ <h3>✅ 本库:符号 + 真减号 <code>−</code></h3>
115
+ <div class="table" aria-hidden="true">
116
+ <table class="tb-demo">
117
+ <thead><tr><th scope="col">板块</th><th scope="col" class="num">涨跌幅</th></tr></thead>
118
+ <tbody>
119
+ <tr><td>半导体</td><td class="num num--neg">1.05%</td></tr>
120
+ <tr><td>白酒</td><td class="num num--pos">3.21%</td></tr>
121
+ <tr><td>光伏</td><td class="num num--neg">12.40%</td></tr>
122
+ </tbody>
123
+ </table>
124
+ </div>
125
+ <p class="cmp__why">颜色是<b>辅助</b>,符号才是信息(WCAG 1.4.1)。符号由 <code>.table .num--pos::before</code> / <code>.num--neg::before</code> 生成 —— 数据里不用手拼 <code>+</code>,也就不会有人漏掉;减号用的是 U+2212,不是连字符。</p>
126
+ </div>
127
+ </div>
89
128
  </main>
90
129
 
91
130
  <script>
package/CHANGELOG.md CHANGED
@@ -16,6 +16,74 @@
16
16
 
17
17
  (无)
18
18
 
19
+ ## [0.11.11] - 2026-10-29
20
+
21
+ **反例从"写着"走到"看得见"**。0.11.10 让 33 个组件都写清了「什么时候不该用」,
22
+ 但那 196 条只存在于 README 的文字里 —— 读者得自己在脑子里把"错的样子"还原出来,
23
+ 还原不出来的那部分就等于没写。这一版把反例摆进示例页:**带 demo 的 32 个组件里,
24
+ 24 个现在是左右并排的「错写法 / 本库写法」**,每块底下跟一句为什么。
25
+ 改之前这个数字是 **10 / 32**(数出来的是 22 个页面缺可见反例)。
26
+
27
+ ### Added
28
+
29
+ - **22 个组件页新增可见对照块**,覆盖 `02-primitives` 6 个、`03-patterns` 10 个、
30
+ `04-recipes` 5 个,另有 `choice` 的旧反例块补上了标题(没有标题,读者不知道那块在演示什么)。
31
+ 现在带 demo 的 32 个组件里,**24 个是并排两栏**(`02-primitives` 9 / `03-patterns` 10 /
32
+ `04-recipes` 5),**8 个沿用既有的 `.box.bad`**(badge / choice / separator / switch /
33
+ accordion / form-validation / overlay / tabs)。每一块的理由都能指回本库的具体位置:
34
+ `button.css` 的一条注释、`combobox.js` 的一个分支、某道门禁守的一条规则
35
+ —— 没有一条是"看起来不专业"这种正确但学不到东西的话。
36
+ - `05-audit/demo-counterexample-gate.py` —— 判「反例能不能被看见」。它和 0.11.10 的
37
+ `do-dont-gate.py` 守的是两层:那边判**写没写**(README 里有没有章节、条目够不够、
38
+ 有没有编造标识符),这边判**看不看得见**(demo 里有没有反例块、有没有被 `hidden` 藏起来、
39
+ 块后面有没有标题说明它在演示什么)。7 条自检,5 条必须红。
40
+ 它的组件名单不另写一份,`importlib` 读 `coverage-gate.py` 的 `LAYOUT_PAGES`
41
+ —— 同一个事实写在两处,早晚有一天两处不一样。
42
+
43
+ ### Changed
44
+
45
+ - **`.cmp` 收编进 `01-tokens/page.css`**(此前 `button` / `card` / `input` 三页各写一遍)。
46
+ 判据是"语义相同才收":那三页的栅格意图一致(`1.55fr 1fr`)、gap 与断点却三种写法,
47
+ 是同一个东西的无意分叉;而 `.row` 15 页 14 种写法**不收** —— 那些是语义不同的东西
48
+ (工具条 / 按钮排 / 元信息行)。不收的理由写在 `page.css` 的注释里,免得下一个人再问一遍。
49
+ - 对照块断点定在 **640px 而不是 720px**:文档页里的活标本 iframe 实测只有 734px 宽,
50
+ 720 的断点等于"再窄一点就叠成单栏",而叠成单栏,"并排"这件事本身就不存在了。
51
+ - **栅格改用 `minmax(0, 1fr)`**:第一版照旧三页抄了 `1fr`,结果 4 个页面在 320px /
52
+ 834px / RTL 阿拉伯语膨胀后横向溢出 81–155px。`1fr` 的下限是 `auto`(内容最小宽度),
53
+ 一栏里有不换行的长串就顶破整页 —— 这条恰恰是 `04-recipes/analysis-report` 那一页
54
+ 正在教别人的东西。
55
+ - `a11y-scan.js` 扫描期间跳过 `.cmp__bad`。漏掉这一条的后果不是"少报一个错",
56
+ 而是**故意写坏的那一栏会把整页判红** —— 于是没人再敢写反例。
57
+ 正例栏不隐藏:它示范的就是"该怎么写",必须能正常操作;反例栏里可交互的元素
58
+ 加了 `tabindex="-1"`(`aria-hidden` 只移出无障碍树,**不移出 Tab 序列**)。
59
+
60
+ ### 跟着改的门禁(判据本身有问题,不是演示块有问题)
61
+
62
+ - `pagination` 的 ⑤/⑨ 从"全页取样"收紧到 `[data-pagination]`:判「每个页码都有
63
+ aria-label」「槽位数 ≤7」时,那两块**静态**页码条(12 个 vs 6 个槽位)被当成了被测对象
64
+ —— 而它们正是拿来演示这两个数字的。
65
+ - `states-check` 的「空状态给出下一步」:排除反例区,并顺手把"只看第一个空状态"
66
+ 改成"看全部"(原来页面里第二个空状态没出口也照样过关,那才是这条判据的真漏洞)。
67
+ - `refs` 的报错行原来只给 `demo.html` —— 库里 6 个同名文件,认不出是哪一个。
68
+ 根因是 `commonpath` 在参数含仓库根的 `index.html` 时返回空串、被当成假值,
69
+ 于是"显示父目录"那段代码**从来没生效过**。
70
+
71
+ ### 性能
72
+
73
+ - CSS 合计预算 124 → **125 KB**(实测 +0.83 KB,剥注释后)。
74
+ 这次上调**没有"规定动作"级别的理由**,就是一次功能采购,所以 `perf-gate.py`
75
+ 里写明了:下次撞线先删等量未引用规则,再来改这个数字。
76
+
77
+ ### 已知未解(写在这里,不假装解决了)
78
+
79
+ - **同一页能看到两套相反的涨跌配色**:`04-recipes/table` 用会计约定(正绿负红),
80
+ `03-patterns/list` 用 A 股约定(涨红跌绿)。这一版**没有改** —— 改颜色语义是破坏性变更,
81
+ 得单独一版做迁移说明。现状如实记在 `04-recipes/table/README.md` 里。
82
+ - **真机读屏(NVDA / VoiceOver)仍未执行**。自动化能证明"每个控件有可访问名",
83
+ 证明不了"念出来听得懂" —— 后者只能人听。这一项在 `docs/ACCESSIBILITY.md` 里就是那么写的。
84
+
85
+ ---
86
+
19
87
  ## [0.11.10] - 2026-10-29
20
88
 
21
89
  ### Added
package/CONTRIBUTING.md CHANGED
@@ -8,7 +8,8 @@ npm run gate # 全量:含浏览器类
8
8
  npm run gate:fast # 只跑静态层,不用装浏览器
9
9
  ```
10
10
 
11
- 全量是 **192 道门禁**(本机约 12 分钟)。
11
+ 全量是 **194 道门禁**(本机约 15–20 分钟:组件层要起浏览器,还要逐张比 95 张视觉截图)。
12
+ 只想确认没改坏静态契约的话用 `gate:fast`,几秒到几分钟。
12
13
 
13
14
  环境依赖只有一套(Node + Chromium),缺了对应的门禁会**跳过**(跳过不算通过):
14
15
 
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "schemaVersion": "1.0.0",
3
3
  "generatedBy": "05-audit/gen-ai-contract.py",
4
- "libraryVersion": "0.11.10",
4
+ "libraryVersion": "0.11.11",
5
5
  "$comment": "机器可读的组件契约。slots = BEM 元素名(在本库里元素名就是插槽名),states.enum = 组件会在 DOM 上写出的 data-* 取值,states.legacyClass = 仍未收敛到 data 属性的历史状态类(INVARIANT I-8 未达标)。",
6
6
  "maturityCriteria": {
7
7
  "alpha": "缺 demo.html 或缺 05-audit 下的专属门禁 ⇒ 还没被机器验证过,不要用",
@@ -330,7 +330,9 @@
330
330
  },
331
331
  "aria": {
332
332
  "roles": [],
333
- "attrs": []
333
+ "attrs": [
334
+ "hidden"
335
+ ]
334
336
  },
335
337
  "usesOtherNamespaces": [],
336
338
  "global": null,
@@ -384,7 +386,10 @@
384
386
  },
385
387
  "aria": {
386
388
  "roles": [],
387
- "attrs": []
389
+ "attrs": [
390
+ "hidden",
391
+ "label"
392
+ ]
388
393
  },
389
394
  "usesOtherNamespaces": [],
390
395
  "global": "Drawer",
@@ -442,7 +447,8 @@
442
447
  ],
443
448
  "attrs": [
444
449
  "disabled",
445
- "expanded"
450
+ "expanded",
451
+ "hidden"
446
452
  ]
447
453
  },
448
454
  "usesOtherNamespaces": [],
@@ -605,6 +611,7 @@
605
611
  "controls",
606
612
  "current",
607
613
  "expanded",
614
+ "hidden",
608
615
  "label"
609
616
  ]
610
617
  },
@@ -731,6 +738,7 @@
731
738
  "controls",
732
739
  "current",
733
740
  "disabled",
741
+ "hidden",
734
742
  "label",
735
743
  "live"
736
744
  ]
@@ -784,7 +792,9 @@
784
792
  },
785
793
  "aria": {
786
794
  "roles": [],
787
- "attrs": []
795
+ "attrs": [
796
+ "hidden"
797
+ ]
788
798
  },
789
799
  "usesOtherNamespaces": [],
790
800
  "global": "Reveal",
@@ -947,7 +957,9 @@
947
957
  "roles": [
948
958
  "tooltip"
949
959
  ],
950
- "attrs": []
960
+ "attrs": [
961
+ "hidden"
962
+ ]
951
963
  },
952
964
  "usesOtherNamespaces": [],
953
965
  "global": "Tooltip",
@@ -991,10 +1003,13 @@
991
1003
  "aria": {
992
1004
  "roles": [
993
1005
  "group",
1006
+ "tree",
994
1007
  "treeitem"
995
1008
  ],
996
1009
  "attrs": [
997
1010
  "expanded",
1011
+ "hidden",
1012
+ "label",
998
1013
  "selected"
999
1014
  ]
1000
1015
  },
@@ -1270,6 +1285,7 @@
1270
1285
  ],
1271
1286
  "attrs": [
1272
1287
  "disabled",
1288
+ "hidden",
1273
1289
  "label",
1274
1290
  "selected"
1275
1291
  ]
@@ -1559,6 +1575,7 @@
1559
1575
  "attrs": [
1560
1576
  "disabled",
1561
1577
  "expanded",
1578
+ "hidden",
1562
1579
  "selected"
1563
1580
  ]
1564
1581
  },
@@ -1647,11 +1664,16 @@
1647
1664
  },
1648
1665
  "aria": {
1649
1666
  "roles": [
1650
- "main"
1667
+ "main",
1668
+ "progressbar"
1651
1669
  ],
1652
1670
  "attrs": [
1653
1671
  "busy",
1654
- "hidden"
1672
+ "hidden",
1673
+ "label",
1674
+ "valuemax",
1675
+ "valuemin",
1676
+ "valuenow"
1655
1677
  ]
1656
1678
  },
1657
1679
  "usesOtherNamespaces": [
@@ -1753,6 +1775,7 @@
1753
1775
  "region"
1754
1776
  ],
1755
1777
  "attrs": [
1778
+ "hidden",
1756
1779
  "label"
1757
1780
  ]
1758
1781
  },
@@ -1794,7 +1817,9 @@
1794
1817
  },
1795
1818
  "aria": {
1796
1819
  "roles": [],
1797
- "attrs": []
1820
+ "attrs": [
1821
+ "hidden"
1822
+ ]
1798
1823
  },
1799
1824
  "usesOtherNamespaces": [
1800
1825
  "detail-body__heading",
@@ -1871,7 +1896,9 @@
1871
1896
  },
1872
1897
  "aria": {
1873
1898
  "roles": [],
1874
- "attrs": []
1899
+ "attrs": [
1900
+ "hidden"
1901
+ ]
1875
1902
  },
1876
1903
  "usesOtherNamespaces": [],
1877
1904
  "global": null,
@@ -1926,6 +1953,7 @@
1926
1953
  "status"
1927
1954
  ],
1928
1955
  "attrs": [
1956
+ "hidden",
1929
1957
  "label",
1930
1958
  "live",
1931
1959
  "sort"
@@ -1 +1 @@
1
- .page {margin:0;min-height:100vh;min-height:100dvh;background:var(--paper);color:var(--text-primary);font-family:var(--sans);font-size:var(--fs-base);line-height:var(--lh-base);-webkit-text-size-adjust:100%;padding-block:calc(env(safe-area-inset-top, 0px) + var(--sp-6)) calc(env(safe-area-inset-bottom, 0px) + var(--sp-6));padding-inline:max(env(safe-area-inset-right, 0px), var(--sp-4)) max(env(safe-area-inset-left, 0px), var(--sp-4));}.page *, .page *::before, .page *::after {box-sizing:border-box;}.page .wrap {margin-inline:auto;max-width:min(var(--measure-page), 100%);}.page .wrap--prose {max-width:min(var(--measure-prose), 100%);}.page h1 {font-family:var(--sans);font-size:var(--fs-2xl);font-weight:500;letter-spacing:var(--tracking-title);line-height:var(--lh-tight);margin:0 0 var(--sp-3);max-width:var(--measure-title);}.page h2 {font-size:var(--fs-lg);margin:var(--sp-7) 0 var(--sp-3);}.page .rule-top {border-top:1px solid var(--border-decor);padding-top:var(--sp-4);}.page .rule-bottom {border-bottom:1px solid var(--border-decor);padding-bottom:var(--sp-2);margin-bottom:var(--sp-4);}.page code {font-family:var(--mono);font-size:0.9em;background:var(--surface-sunken);padding:1px 4px;border-radius:var(--r-xs);}.page .box {background:var(--surface);border:1px solid var(--border-decor);border-radius:var(--r-md);padding:var(--sp-5);}.page .box.bad {background:var(--surface-sunken);}
1
+ .page {margin:0;min-height:100vh;min-height:100dvh;background:var(--paper);color:var(--text-primary);font-family:var(--sans);font-size:var(--fs-base);line-height:var(--lh-base);-webkit-text-size-adjust:100%;padding-block:calc(env(safe-area-inset-top, 0px) + var(--sp-6)) calc(env(safe-area-inset-bottom, 0px) + var(--sp-6));padding-inline:max(env(safe-area-inset-right, 0px), var(--sp-4)) max(env(safe-area-inset-left, 0px), var(--sp-4));}.page *, .page *::before, .page *::after {box-sizing:border-box;}.page .wrap {margin-inline:auto;max-width:min(var(--measure-page), 100%);}.page .wrap--prose {max-width:min(var(--measure-prose), 100%);}.page h1 {font-family:var(--sans);font-size:var(--fs-2xl);font-weight:500;letter-spacing:var(--tracking-title);line-height:var(--lh-tight);margin:0 0 var(--sp-3);max-width:var(--measure-title);}.page h2 {font-size:var(--fs-lg);margin:var(--sp-7) 0 var(--sp-3);}.page .rule-top {border-top:1px solid var(--border-decor);padding-top:var(--sp-4);}.page .rule-bottom {border-bottom:1px solid var(--border-decor);padding-bottom:var(--sp-2);margin-bottom:var(--sp-4);}.page code {font-family:var(--mono);font-size:0.9em;background:var(--surface-sunken);padding:1px 4px;border-radius:var(--r-xs);}.page .box {background:var(--surface);border:1px solid var(--border-decor);border-radius:var(--r-md);padding:var(--sp-5);}.page .box.bad {background:var(--surface-sunken);}.page .cmp {display:grid;grid-template-columns:minmax(0, 1fr) minmax(0, 1fr);gap:var(--sp-4);}.page .cmp--wide-first {grid-template-columns:minmax(0, 1.55fr) minmax(0, 1fr);}@media (max-width:640px) {.page .cmp, .page .cmp--wide-first, .page .cmp--clip {grid-template-columns:minmax(0, 1fr);}}.page .cmp__pane {padding:var(--sp-4);border:1px solid var(--border-decor);border-radius:var(--r-md);background:var(--surface-sunken);min-width:0;}.page .cmp--clip .cmp__pane {overflow:hidden;}.page .cmp__pane > h3 {margin:0 0 var(--sp-3);font-size:var(--fs-sm);font-weight:500;}.page .cmp__bad > h3 {color:var(--danger);}.page .cmp__good > h3 {color:var(--success);}.page .cmp__why {margin:var(--sp-3) 0 0;font-size:var(--fs-xs);line-height:1.6;color:var(--text-secondary);}
package/dist/COSTS.md CHANGED
@@ -49,7 +49,7 @@
49
49
  ## 三、全库
50
50
 
51
51
  - 全部组件都用上(min,含 tokens 一份):**60.0 KB**
52
- - 源码版(带注释)全库 gzip:289.0 KB
52
+ - 源码版(带注释)全库 gzip:290.6 KB
53
53
 
54
54
  > ⚠️ 源码版那个数字**不是**要付的钱:它包含我们的注释(全库 CSS 有 66% 是注释,字节口径)。
55
55
  > 它的用途只有一个 —— 让人看清"dist 到底省了多少"。
package/index.html CHANGED
@@ -92,7 +92,7 @@ li a:active { background: var(--surface-sunken); }
92
92
  </p>
93
93
  </main>
94
94
  <footer class="wrap">
95
- <p class="note">0.11.10 · 零第三方运行时依赖</p>
95
+ <p class="note">0.11.11 · 零第三方运行时依赖</p>
96
96
  </footer>
97
97
  </body>
98
98
  </html>
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "agentcss",
3
- "version": "0.11.10",
3
+ "version": "0.11.11",
4
4
  "description": "移动 Web 组件库:CSS + 可选行为脚本,零第三方运行时依赖。样式用 bundler 引入,交互行为用 script 标签引入。",
5
5
  "keywords": [
6
6
  "css",