@icen.ai/ui 0.10.0 → 0.11.1

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 (362) hide show
  1. package/AGENTS.md +79 -309
  2. package/LICENSE +21 -0
  3. package/README.md +43 -54
  4. package/dist/base.css +68 -22
  5. package/dist/behaviors/accordion.mjs +1 -1
  6. package/dist/behaviors/ai-branch.mjs +14 -0
  7. package/dist/behaviors/ai-chat.d.mts +2 -2
  8. package/dist/behaviors/ai-chat.mjs +66 -10
  9. package/dist/behaviors/ai-composer.d.mts +5 -5
  10. package/dist/behaviors/ai-composer.mjs +34 -10
  11. package/dist/behaviors/ai-core.mjs +14 -0
  12. package/dist/behaviors/ai-diff.mjs +14 -0
  13. package/dist/behaviors/ai-feedback.mjs +14 -0
  14. package/dist/behaviors/ai-panel.d.mts +2 -2
  15. package/dist/behaviors/ai-panel.mjs +14 -0
  16. package/dist/behaviors/ai-provider.d.mts +1 -1
  17. package/dist/behaviors/ai-provider.mjs +14 -0
  18. package/dist/behaviors/ai-threads.mjs +14 -0
  19. package/dist/behaviors/ai-tool.d.mts +1 -1
  20. package/dist/behaviors/ai-tool.mjs +299 -24
  21. package/dist/behaviors/ai-tools.mjs +1179 -28
  22. package/dist/behaviors/autocomplete.d.mts +1 -1
  23. package/dist/behaviors/autocomplete.mjs +14 -0
  24. package/dist/behaviors/back-top.mjs +14 -0
  25. package/dist/behaviors/carousel.mjs +21 -1
  26. package/dist/behaviors/cascader.mjs +27 -0
  27. package/dist/behaviors/charts.d.mts +12 -1
  28. package/dist/behaviors/charts.mjs +298 -20
  29. package/dist/behaviors/code-block.mjs +22 -1
  30. package/dist/behaviors/command-palette.mjs +3 -3
  31. package/dist/behaviors/context-menu.d.mts +2 -2
  32. package/dist/behaviors/context-menu.mjs +14 -0
  33. package/dist/behaviors/controls.d.mts +8 -8
  34. package/dist/behaviors/controls.mjs +50 -6
  35. package/dist/behaviors/copy.mjs +14 -0
  36. package/dist/behaviors/datatable.d.mts +3 -3
  37. package/dist/behaviors/datatable.mjs +89 -11
  38. package/dist/behaviors/date-picker.mjs +14 -0
  39. package/dist/behaviors/events.d.mts +10 -10
  40. package/dist/behaviors/events.mjs +11 -1
  41. package/dist/behaviors/form-validate.d.mts +10 -1
  42. package/dist/behaviors/form-validate.mjs +279 -4611
  43. package/dist/behaviors/i18n.d.mts +14 -0
  44. package/dist/behaviors/i18n.mjs +28 -0
  45. package/dist/behaviors/input.mjs +16 -0
  46. package/dist/behaviors/kb-access.d.mts +2 -2
  47. package/dist/behaviors/kb-access.mjs +21 -2
  48. package/dist/behaviors/kb-acl.d.mts +2 -2
  49. package/dist/behaviors/kb-acl.mjs +14 -0
  50. package/dist/behaviors/kb-answer.d.mts +2 -2
  51. package/dist/behaviors/kb-answer.mjs +298 -23
  52. package/dist/behaviors/kb-audit.d.mts +2 -2
  53. package/dist/behaviors/kb-audit.mjs +14 -0
  54. package/dist/behaviors/kb-canvas.d.mts +3 -3
  55. package/dist/behaviors/kb-canvas.mjs +14 -0
  56. package/dist/behaviors/kb-chain.d.mts +2 -2
  57. package/dist/behaviors/kb-chain.mjs +14 -0
  58. package/dist/behaviors/kb-checkpoint.d.mts +2 -2
  59. package/dist/behaviors/kb-checkpoint.mjs +14 -0
  60. package/dist/behaviors/kb-chunks.d.mts +2 -2
  61. package/dist/behaviors/kb-chunks.mjs +14 -0
  62. package/dist/behaviors/kb-citation.d.mts +2 -2
  63. package/dist/behaviors/kb-citation.mjs +33 -6
  64. package/dist/behaviors/kb-clarify.d.mts +2 -2
  65. package/dist/behaviors/kb-clarify.mjs +14 -0
  66. package/dist/behaviors/kb-conflict.d.mts +2 -2
  67. package/dist/behaviors/kb-conflict.mjs +14 -0
  68. package/dist/behaviors/kb-connector.d.mts +2 -2
  69. package/dist/behaviors/kb-connector.mjs +14 -0
  70. package/dist/behaviors/kb-core.d.mts +1 -1
  71. package/dist/behaviors/kb-core.mjs +14 -0
  72. package/dist/behaviors/kb-eval.d.mts +2 -2
  73. package/dist/behaviors/kb-eval.mjs +21 -2
  74. package/dist/behaviors/kb-explain.d.mts +2 -2
  75. package/dist/behaviors/kb-explain.mjs +26 -2
  76. package/dist/behaviors/kb-filter.d.mts +2 -2
  77. package/dist/behaviors/kb-filter.mjs +21 -2
  78. package/dist/behaviors/kb-gap.d.mts +2 -2
  79. package/dist/behaviors/kb-gap.mjs +14 -0
  80. package/dist/behaviors/kb-hittest.d.mts +2 -2
  81. package/dist/behaviors/kb-hittest.mjs +15 -1
  82. package/dist/behaviors/kb-metadata.mjs +19 -0
  83. package/dist/behaviors/kb-passage.d.mts +2 -2
  84. package/dist/behaviors/kb-passage.mjs +14 -0
  85. package/dist/behaviors/kb-pipeline.d.mts +2 -2
  86. package/dist/behaviors/kb-pipeline.mjs +14 -0
  87. package/dist/behaviors/kb-qa.mjs +14 -0
  88. package/dist/behaviors/kb-rerank.d.mts +2 -2
  89. package/dist/behaviors/kb-rerank.mjs +14 -0
  90. package/dist/behaviors/kb-retrieval.d.mts +2 -2
  91. package/dist/behaviors/kb-retrieval.mjs +31 -4
  92. package/dist/behaviors/kb-review.d.mts +2 -2
  93. package/dist/behaviors/kb-review.mjs +21 -2
  94. package/dist/behaviors/kb-sandbox.d.mts +2 -2
  95. package/dist/behaviors/kb-sandbox.mjs +20 -1
  96. package/dist/behaviors/kb-segment.d.mts +2 -2
  97. package/dist/behaviors/kb-segment.mjs +15 -1
  98. package/dist/behaviors/kb-select.mjs +21 -2
  99. package/dist/behaviors/kb-sources.d.mts +2 -2
  100. package/dist/behaviors/kb-sources.mjs +14 -0
  101. package/dist/behaviors/kb-sql.d.mts +2 -2
  102. package/dist/behaviors/kb-sql.mjs +14 -0
  103. package/dist/behaviors/kb-trace.d.mts +2 -2
  104. package/dist/behaviors/kb-trace.mjs +22 -3
  105. package/dist/behaviors/kb-visibility.d.mts +2 -2
  106. package/dist/behaviors/kb-visibility.mjs +14 -0
  107. package/dist/behaviors/kb-who-can.d.mts +2 -2
  108. package/dist/behaviors/kb-who-can.mjs +21 -2
  109. package/dist/behaviors/mentions.d.mts +1 -1
  110. package/dist/behaviors/mentions.mjs +14 -0
  111. package/dist/behaviors/modal.d.mts +1 -1
  112. package/dist/behaviors/modal.mjs +14 -0
  113. package/dist/behaviors/motion.d.mts +16 -0
  114. package/dist/behaviors/motion.mjs +39 -0
  115. package/dist/behaviors/notification.d.mts +2 -2
  116. package/dist/behaviors/notification.mjs +27 -3
  117. package/dist/behaviors/panel.mjs +14 -0
  118. package/dist/behaviors/scroll-area.d.mts +17 -0
  119. package/dist/behaviors/scroll-area.mjs +59 -0
  120. package/dist/behaviors/select.mjs +21 -2
  121. package/dist/behaviors/slider.mjs +3 -3
  122. package/dist/behaviors/split-pane.mjs +2 -0
  123. package/dist/behaviors/suggestions.mjs +14 -0
  124. package/dist/behaviors/tabs.mjs +10 -0
  125. package/dist/behaviors/tag-input.mjs +14 -0
  126. package/dist/behaviors/theme-switcher.d.mts +2 -2
  127. package/dist/behaviors/theme-switcher.mjs +30 -2
  128. package/dist/behaviors/theme.mjs +16 -2
  129. package/dist/behaviors/toast.d.mts +2 -2
  130. package/dist/behaviors/toast.mjs +14 -0
  131. package/dist/behaviors/tree-select.mjs +27 -0
  132. package/dist/behaviors/tree.mjs +4 -4
  133. package/dist/behaviors/upload.mjs +14 -0
  134. package/dist/behaviors/url-safety.d.mts +8 -0
  135. package/dist/behaviors/url-safety.mjs +11 -0
  136. package/dist/components/accordion.d.mts +2 -0
  137. package/dist/components/ai-branch.d.mts +2 -0
  138. package/dist/components/ai-chat.css +40 -33
  139. package/dist/components/ai-chat.d.mts +2 -0
  140. package/dist/components/ai-composer.d.mts +2 -0
  141. package/dist/components/ai-context.d.mts +2 -0
  142. package/dist/components/ai-context.mjs +1 -0
  143. package/dist/components/ai-diff.css +6 -6
  144. package/dist/components/ai-diff.d.mts +2 -0
  145. package/dist/components/ai-feedback.d.mts +2 -0
  146. package/dist/components/ai-files.d.mts +2 -0
  147. package/dist/components/ai-message.d.mts +2 -0
  148. package/dist/components/ai-panel.css +12 -10
  149. package/dist/components/ai-reasoning.d.mts +2 -0
  150. package/dist/components/ai-subagent.d.mts +2 -0
  151. package/dist/components/ai-subagent.mjs +1 -0
  152. package/dist/components/ai-threads.d.mts +2 -0
  153. package/dist/components/ai-todo.d.mts +2 -0
  154. package/dist/components/ai-todo.mjs +1 -0
  155. package/dist/components/ai-tool-call.d.mts +2 -0
  156. package/dist/components/ai-tool-call.mjs +1 -0
  157. package/dist/components/ai-tool.css +16 -16
  158. package/dist/components/ai-usage.d.mts +2 -0
  159. package/dist/components/alert.d.mts +2 -0
  160. package/dist/components/autocomplete.css +12 -12
  161. package/dist/components/autocomplete.d.mts +2 -0
  162. package/dist/components/avatar.d.mts +2 -0
  163. package/dist/components/back-top.css +47 -16
  164. package/dist/components/back-top.d.mts +2 -0
  165. package/dist/components/badge.css +1 -1
  166. package/dist/components/badge.d.mts +2 -0
  167. package/dist/components/breadcrumb.css +26 -8
  168. package/dist/components/breadcrumb.d.mts +2 -0
  169. package/dist/components/btn.css +67 -62
  170. package/dist/components/btn.d.mts +2 -0
  171. package/dist/components/card.css +22 -22
  172. package/dist/components/card.d.mts +2 -0
  173. package/dist/components/carousel.d.mts +2 -0
  174. package/dist/components/cascader.css +56 -35
  175. package/dist/components/cascader.d.mts +2 -0
  176. package/dist/components/chart-area.css +46 -0
  177. package/dist/components/chart-area.d.mts +2 -0
  178. package/dist/components/chart-bar.css +66 -19
  179. package/dist/components/chart-bar.d.mts +2 -0
  180. package/dist/components/chart-calendar.d.mts +2 -0
  181. package/dist/components/chart-gauge.css +23 -3
  182. package/dist/components/chart-gauge.d.mts +2 -0
  183. package/dist/components/chart-graph.css +15 -3
  184. package/dist/components/chart-graph.d.mts +2 -0
  185. package/dist/components/chart-heatmap.css +117 -95
  186. package/dist/components/chart-heatmap.d.mts +2 -0
  187. package/dist/components/chart-line.css +54 -0
  188. package/dist/components/chart-line.d.mts +2 -0
  189. package/dist/components/chart-map.d.mts +2 -0
  190. package/dist/components/chart-pie.css +29 -0
  191. package/dist/components/chart-pie.d.mts +2 -0
  192. package/dist/components/chart-radar.css +50 -1
  193. package/dist/components/chart-radar.d.mts +2 -0
  194. package/dist/components/chart-scatter.css +39 -2
  195. package/dist/components/chart-scatter.d.mts +2 -0
  196. package/dist/components/chart-sparkline.css +20 -0
  197. package/dist/components/chart-sparkline.d.mts +2 -0
  198. package/dist/components/chart-stack.css +16 -5
  199. package/dist/components/chart-stack.d.mts +2 -0
  200. package/dist/components/charts.css +109 -35
  201. package/dist/components/charts.d.mts +2 -0
  202. package/dist/components/code-block.css +10 -8
  203. package/dist/components/code-block.d.mts +2 -0
  204. package/dist/components/command-palette.css +45 -38
  205. package/dist/components/command-palette.d.mts +2 -0
  206. package/dist/components/content.css +62 -57
  207. package/dist/components/context-menu.d.mts +2 -0
  208. package/dist/components/copy.css +10 -10
  209. package/dist/components/copy.d.mts +2 -0
  210. package/dist/components/datatable.css +72 -59
  211. package/dist/components/datatable.d.mts +2 -0
  212. package/dist/components/date-picker.css +26 -26
  213. package/dist/components/date-picker.d.mts +2 -0
  214. package/dist/components/desc.d.mts +2 -0
  215. package/dist/components/dropdown.d.mts +2 -0
  216. package/dist/components/empty.css +16 -16
  217. package/dist/components/empty.d.mts +2 -0
  218. package/dist/components/feedback.css +31 -29
  219. package/dist/components/form-validate.css +20 -6
  220. package/dist/components/form-validate.d.mts +2 -0
  221. package/dist/components/form.css +17 -14
  222. package/dist/components/form.d.mts +2 -0
  223. package/dist/components/icon.css +21 -10
  224. package/dist/components/icon.d.mts +2 -0
  225. package/dist/components/input.css +22 -22
  226. package/dist/components/input.d.mts +2 -0
  227. package/dist/components/kb-access.d.mts +2 -0
  228. package/dist/components/kb-acl.d.mts +2 -0
  229. package/dist/components/kb-agent.css +134 -55
  230. package/dist/components/kb-answer.d.mts +2 -0
  231. package/dist/components/kb-audit.d.mts +2 -0
  232. package/dist/components/kb-canvas.d.mts +2 -0
  233. package/dist/components/kb-chain.d.mts +2 -0
  234. package/dist/components/kb-checkpoint.d.mts +2 -0
  235. package/dist/components/kb-chunks.d.mts +2 -0
  236. package/dist/components/kb-citation.d.mts +2 -0
  237. package/dist/components/kb-clarify.d.mts +2 -0
  238. package/dist/components/kb-conflict.d.mts +2 -0
  239. package/dist/components/kb-connector.d.mts +2 -0
  240. package/dist/components/kb-data.css +192 -80
  241. package/dist/components/kb-eval.d.mts +2 -0
  242. package/dist/components/kb-explain.d.mts +2 -0
  243. package/dist/components/kb-filter.d.mts +2 -0
  244. package/dist/components/kb-gap.d.mts +2 -0
  245. package/dist/components/kb-ground.css +165 -73
  246. package/dist/components/kb-hittest.d.mts +2 -0
  247. package/dist/components/kb-ingest.css +308 -113
  248. package/dist/components/kb-metadata.d.mts +2 -0
  249. package/dist/components/kb-ops.css +189 -75
  250. package/dist/components/kb-passage.d.mts +2 -0
  251. package/dist/components/kb-perm.css +158 -87
  252. package/dist/components/kb-pipeline.d.mts +2 -0
  253. package/dist/components/kb-qa.d.mts +2 -0
  254. package/dist/components/kb-rerank.d.mts +2 -0
  255. package/dist/components/kb-retrieval.d.mts +2 -0
  256. package/dist/components/kb-review.d.mts +2 -0
  257. package/dist/components/kb-sandbox.d.mts +2 -0
  258. package/dist/components/kb-search.css +353 -116
  259. package/dist/components/kb-segment.d.mts +2 -0
  260. package/dist/components/kb-sources.d.mts +2 -0
  261. package/dist/components/kb-sql.d.mts +2 -0
  262. package/dist/components/kb-trace.d.mts +2 -0
  263. package/dist/components/kb-visibility.d.mts +2 -0
  264. package/dist/components/kb-who-can.d.mts +2 -0
  265. package/dist/components/kb.css +60 -36
  266. package/dist/components/kb.d.mts +2 -0
  267. package/dist/components/kbd.d.mts +2 -0
  268. package/dist/components/layout.css +10 -10
  269. package/dist/components/layout.d.mts +2 -0
  270. package/dist/components/list.d.mts +2 -0
  271. package/dist/components/material-chinese.css +10 -0
  272. package/dist/components/material-soviet.css +10 -0
  273. package/dist/components/material.css +61 -18
  274. package/dist/components/media-card.d.mts +2 -0
  275. package/dist/components/media.css +22 -27
  276. package/dist/components/mentions.css +18 -17
  277. package/dist/components/mentions.d.mts +2 -0
  278. package/dist/components/menu.css +32 -28
  279. package/dist/components/modal.css +30 -27
  280. package/dist/components/modal.d.mts +2 -0
  281. package/dist/components/nav.css +48 -44
  282. package/dist/components/nav.d.mts +2 -0
  283. package/dist/components/notification.css +31 -25
  284. package/dist/components/notification.d.mts +2 -0
  285. package/dist/components/pagination.css +15 -13
  286. package/dist/components/pagination.d.mts +2 -0
  287. package/dist/components/panel.css +19 -20
  288. package/dist/components/panel.d.mts +2 -0
  289. package/dist/components/pill.css +8 -7
  290. package/dist/components/pill.d.mts +2 -0
  291. package/dist/components/popover.css +32 -23
  292. package/dist/components/popover.d.mts +2 -0
  293. package/dist/components/progress.d.mts +2 -0
  294. package/dist/components/rating.d.mts +2 -0
  295. package/dist/components/result.d.mts +2 -0
  296. package/dist/components/scroll-area.css +84 -112
  297. package/dist/components/scroll-area.d.mts +2 -0
  298. package/dist/components/scroll-area.mjs +1 -0
  299. package/dist/components/segmented.css +47 -29
  300. package/dist/components/segmented.d.mts +2 -0
  301. package/dist/components/select.css +80 -41
  302. package/dist/components/select.d.mts +2 -0
  303. package/dist/components/sidebar.css +42 -38
  304. package/dist/components/sidebar.d.mts +2 -0
  305. package/dist/components/skeleton.d.mts +2 -0
  306. package/dist/components/slider.css +26 -22
  307. package/dist/components/slider.d.mts +2 -0
  308. package/dist/components/spinner.d.mts +2 -0
  309. package/dist/components/split-pane.css +16 -7
  310. package/dist/components/split-pane.d.mts +2 -0
  311. package/dist/components/stat.css +17 -16
  312. package/dist/components/stat.d.mts +2 -0
  313. package/dist/components/steps.css +26 -26
  314. package/dist/components/steps.d.mts +2 -0
  315. package/dist/components/switch.css +78 -39
  316. package/dist/components/switch.d.mts +2 -0
  317. package/dist/components/table.css +54 -32
  318. package/dist/components/table.d.mts +2 -0
  319. package/dist/components/tabs.css +53 -32
  320. package/dist/components/tabs.d.mts +2 -0
  321. package/dist/components/tag-input.css +12 -8
  322. package/dist/components/tag-input.d.mts +2 -0
  323. package/dist/components/tag.css +20 -12
  324. package/dist/components/tag.d.mts +2 -0
  325. package/dist/components/theme-switcher.css +7 -7
  326. package/dist/components/theme-switcher.d.mts +2 -0
  327. package/dist/components/timeline.d.mts +2 -0
  328. package/dist/components/toast.css +34 -30
  329. package/dist/components/toast.d.mts +2 -0
  330. package/dist/components/toolbar.css +19 -18
  331. package/dist/components/toolbar.d.mts +2 -0
  332. package/dist/components/tooltip.css +9 -8
  333. package/dist/components/tooltip.d.mts +2 -0
  334. package/dist/components/tree-select.css +63 -40
  335. package/dist/components/tree-select.d.mts +2 -0
  336. package/dist/components/tree.d.mts +2 -0
  337. package/dist/components/upload.css +9 -11
  338. package/dist/components/upload.d.mts +2 -0
  339. package/dist/index.d.mts +85 -84
  340. package/dist/index.mjs +14644 -13935
  341. package/dist/react.d.mts +18 -18
  342. package/dist/react.mjs +377 -36
  343. package/dist/registry.json +797 -64
  344. package/dist/tokens/colors.css +6 -0
  345. package/dist/tokens/design.css +137 -31
  346. package/dist/tokens/dtcg.json +9592 -2008
  347. package/dist/tokens/figma.variables.json +7451 -2141
  348. package/dist/tokens/motion.css +51 -0
  349. package/dist/tokens/pixel.css +10 -0
  350. package/dist/tokens/scrollbars.css +40 -0
  351. package/dist/tokens/tokens-studio.json +8390 -1142
  352. package/dist/tokens/typography.css +33 -0
  353. package/dist/tokens.css +402 -82
  354. package/dist/ui.css +4196 -2163
  355. package/dist/vue.d.mts +17 -17
  356. package/dist/vue.mjs +371 -34
  357. package/docs/spec/charts-scale-a11y.md +115 -0
  358. package/docs/spec/design-philosophy.md +5 -5
  359. package/docs/spec/design-primitives.md +10 -10
  360. package/docs/spec/motion-typography.md +105 -0
  361. package/docs/spec/scrollbars.md +46 -0
  362. package/package.json +17 -3
@@ -0,0 +1,115 @@
1
+ # 图表:数据规模、无障碍与手势(spec)
2
+
3
+ 面向实现者与评审。现状事实源:`src/behaviors/charts.ts`(统一 ChartSpec + renderChart)、`src/components/charts.css`。本文件给出规模分级、渲染策略、读屏语义、键盘与手势模型、性能预算与测试策略。已落地项标注 ✅(含验证方式),接口草案标注 🔵(未实现,类型即合同)。
4
+
5
+ ## 1. 数据规模分级与渲染策略
6
+
7
+ | 级别 | 规模 | 渲染策略 | 现状 |
8
+ | --- | --- | --- | --- |
9
+ | S | ≤1e3 点 | 纯 SVG/DOM 直渲,无抽样 | ✅ 默认路径 |
10
+ | M | 1e3–1e5 | SVG + LTTB 降采样(默认阈值 1000,`spec.downsample`)| ✅ `lttb()` 纯函数 + `downsampleView`;抽样时头部行提示「已抽样 N→M 点」(诚实呈现,不静默) |
11
+ | L | 1e5–1e6 | LTTB + 视窗(zoom/append 窗口切片后才对视图抽样)| ✅ zoom 窗与 `append(maxPoints)` 头部淘汰已落地 |
12
+ | XL | ≥1e6 | 分层混合:Canvas raster 层 + SVG 交互层(热点/游标/焦点环)| 🔵 接口草案见 §7;当前 SVG 上限实测见 §6 |
13
+
14
+ 降采样算法选择:**LTTB**(保形状特征,极值不丢)为默认;min-max 分桶适合密度热力预览但不保峰形,作为 🔵 `sampling.method: 'minmax'` 草案保留;时序流式场景用 `append` 的窗口淘汰而非重抽样。
15
+
16
+ 渲染器选择原则:SVG 保交互与 a11y(每点是真实节点,可挂 title/焦点);Canvas 只在 XL 级引入且必须叠加 SVG 交互层——读屏语义与键盘游标不因渲染器切换而退步。
17
+
18
+ ## 2. 长列表 / 表格 / 树的虚拟滚动
19
+
20
+ | 组件 | 现状 | 方案 |
21
+ | --- | --- | --- |
22
+ | datatable | ✅ `virtual: true` 固定行高窗口化(`rowHeight` 可调,与分页互斥) | 万级行流畅;动态行高 🔵(测量缓存 + 预估高度 + 滚动锚定,见下) |
23
+ | table | 静态展示组件 | 数据量大时用 datatable;table 不引入虚拟化(职责分离) |
24
+ | tree | 无虚拟化 | 🔵 同 datatable 窗口化;展开/收起时以「首个可见节点的 key + 偏移」做滚动锚定 |
25
+
26
+ 动态行高草案(🔵):`virtual: { estimatedRowHeight: number; measure?: true }`——IntersectionObserver-free,渲染后测量真实高并写回缓存,滚动锚定 = 记录锚点 key 与其在行内的偏移,重渲后恢复。滚动锚定同样适用于 prepend(聊天/日志流)。
27
+
28
+ ## 3. 屏幕阅读器语义
29
+
30
+ 每个图形的语义三层(✅ 已落地,`tests/dom/charts-a11y.test.ts` 7 项):
31
+
32
+ 1. **可访问名**:`role="img"` + `aria-label` = 标题(图型)或图型(既有行为,axe 债已清)。
33
+ 2. **自动摘要**:sr-only `<p>` 经 `aria-describedby` 挂载——系列数、类目范围、最值及其类目、首系列趋势(升/降/平);scatter 播报 x/y 范围。`spec.a11y.summary: false` 可关。
34
+ 3. **数据表替代视图**:`spec.a11y.table: true` 追加 sr-only `<table>`(caption + thead 系列名 + tbody 类目/值行;scatter 为 x/y 两列)。读屏器按表格语义逐格导航,复制导出同源。
35
+
36
+ 各图型语义矩阵:
37
+
38
+ | 图型 | role/label | 摘要 | 键盘游标 |
39
+ | --- | --- | --- | --- |
40
+ | line/area | img + describedby ✅ | ✅ 范围/最值/趋势 | ✅ 点级(系列×点) |
41
+ | vbar/hbar | DOM 容器 img + describedby ✅ | ✅ | ✅ 柱条级 |
42
+ | scatter | img + describedby ✅ | ✅ x/y 范围 | ✅ 点级 |
43
+ | donut/radar | img ✅ | ✅ 最值 | 🔵(段导航) |
44
+ | heatmap/calendar | aria-label 网格 ✅ | ✅ 最值 | 🔵(格导航) |
45
+ | gauge/sparkline | img ✅ | ✅ 单值退化 | —(单值无导航必要) |
46
+ | graph/map | img ✅ | 🔵 节点/边计数 | 🔵 |
47
+
48
+ **不只靠颜色**:多系列折线的区分 = 颜色 + 图例文本 + tooltip/播报中的系列名 + 标记点形状(marks);键盘游标与播报完全不依赖颜色。纹理/虚线族(stroke-dasharray 轮换)作为 🔵 增强项保留(打印/单色场景)。
49
+
50
+ ## 4. 键盘导航模型与 live region
51
+
52
+ ✅ 已落地(`spec.a11y.keyboard` 默认开):
53
+
54
+ - 图形可聚焦(`tabindex=0` + `:focus-visible` 环);**←/→** 逐点、**↑/↓** 切系列(多系列)、**Home/End** 跳首尾、**Esc** 重置缩放窗。
55
+ - 游标视觉:SVG 点圆放大加粗(`r` 几何属性 + stroke-width;不支持 `r` 的浏览器退化为描边),DOM 柱条用 accent 轮廓环。
56
+ - 播报:单个 `aria-live="polite"` region 随图表存活,播报「系列 · 类目:值,第 i/n 点」;先清空再写入保证同值重报。
57
+ - 与 tooltip/事件族正交:键盘导航不触发 hover 事件,避免双通道噪音。
58
+
59
+ ## 5. 交互手势
60
+
61
+ 现状(✅):`spec.zoom: 'x'|'brush'` 指针拖选缩放(统一 pointer 事件,位移 <5px 视为点击;pointercancel 按 pointerup 收口);头部 chip 与双击 plot 复原;`icen:chart-zoom {chart,from,to}` 广播。
62
+
63
+ 本分支补齐(✅):**触屏冲突**——zoom 启用时 plot 的 `touch-action`:`'x'` 为 `pan-y`(垂直留给页面滚动,水平拦拖选),`'brush'` 为 `none`(自由框选接管)。惯性不做(类目语义图表的惯性滚动会造成定位歧义,有意拒绝)。
64
+
65
+ 键盘等价:方向键游标 = 平移/浏览等价;Esc = 重置等价;双指缩放的键盘等价 🔵(`+`/`-` 以游标为中心缩放,接口预留)。
66
+
67
+ 触屏替代:tooltip 已有点击语义;游标类在触屏上不显示(无焦点)。
68
+
69
+ ## 6. 性能预算与基准
70
+
71
+ 预算(验收口径,桌面中端机 Chrome;首绘 = renderChart 同步返回 + 一帧):
72
+
73
+ | 指标 | 预算 | 量级依据 |
74
+ | --- | --- | --- |
75
+ | LTTB 1e6→1000 | <10ms JS | 实测 5.25ms(bun,本机) |
76
+ | normalizeChartSpec 1e5 类目 | <10ms JS | 实测 3.27ms |
77
+ | renderChart line 1e4(抽样开) | <100ms JS(happy-dom 口径) | 实测 63.9ms;浏览器 DOM 低于此 |
78
+ | 交互帧(游标/图例切换) | <16ms | 类切换 + 单点重绘 |
79
+ | 内存 | 视图点数 ≤ 抽样阈值 + 窗口 | LTTB 输出 ≤1000 点 |
80
+
81
+ 基准方法:`bun scripts/bench-charts.mjs`(可重复,口径写在脚本头注释:JS 侧耗时,不含绘制/合成;绘制预算由 e2e 视觉舱与人工 DevTools Performance 抽样验收)。数字为量级参考,随硬件变——评审看量级与回归趋势,不比绝对值。
82
+
83
+ ## 7. 接口草案(🔵 未实现,类型即合同)
84
+
85
+ ```ts
86
+ /** XL 级(≥1e6)分层渲染:Canvas raster + SVG 交互层。a11y 层语义不因渲染器切换而退步。 */
87
+ interface ChartCanvasRenderer {
88
+ /** 绘制视窗内点云(OffscreenCanvas 可迁移 Worker) */
89
+ paint(view: ChartSpec, window: { from: number; to: number }): void;
90
+ /** 命中测试交给 SVG 交互层(分桶索引),本层只管画 */
91
+ destroy(): void;
92
+ }
93
+
94
+ /** Worker 降采样池:大数据 LTTB 移出主线程;返回 Promise,不阻塞首绘 */
95
+ interface ChartSamplingWorker {
96
+ sample(points: readonly { x: number; y: number }[], threshold: number): Promise<readonly number[]>;
97
+ terminate(): void;
98
+ }
99
+
100
+ /** 声音化(可选增强,默认关):逐点音高映射值域,键盘游标移动时发声 */
101
+ interface ChartSonifyOptions {
102
+ enabled: boolean; // 默认 false;开启需用户动作(音频上下文策略)
103
+ rangeHz?: [number, number]; // 默认 [220, 880]
104
+ }
105
+ ```
106
+
107
+ 落地顺序建议:Worker 降采样 > Canvas 层 > sonification。每一层都必须先过 a11y 回归(摘要/表格/键盘游标不降级)。
108
+
109
+ ## 8. 测试策略
110
+
111
+ - ✅ DOM 测试 `tests/dom/charts-a11y.test.ts`:摘要内容、describedby 接线、数据表结构、键盘全键位、边界 clamp、update 后游标保持、destroy 解绑。
112
+ - ✅ 既有 axe 基线(`tests/e2e/a11y.pw.ts` + a11y-baseline.json)覆盖组件页;本层新增的 sr-only 节点不改变像素(视觉基线无漂移)。
113
+ - ✅ LTTB 单元测试(`tests/unit/charts-lttb.test.ts`)。
114
+ - 手测矩阵(发布前人工):NVDA + Chrome(摘要/表格/游标播报)、VoiceOver + Safari(macOS/iOS 各一)、键盘-only 全流程(焦点可见、无键盘陷阱)、200% 缩放与 Windows 高对比(forced-colors 已有滚动条/焦点环兜底)。
115
+ - 视觉回归:游标类只在键盘聚焦时出现,默认截图不含;`a11y.table` 的 sr-only 表格不渲染进位图。
@@ -47,11 +47,11 @@ GitHub Primer 的语义色纪律、Radix Colors 的阶梯尺、Stripe 的"深档
47
47
  ### 2.1 圆角六档职责
48
48
  | 档 | 现代默认值(随 design-radius 联动) | 职责 |
49
49
  |---|---|---|
50
- | `xs` | 4px | 微型件内角:芯片、徽标、小标签 |
51
- | `sm` | 8px | 控件内嵌:按钮、输入框、小卡 |
52
- | `md` | 10px | 默认容器:卡片、面板、浮层 |
53
- | `lg` | 16px | 大容器:modal、工作台卡 |
54
- | `xl` | 24px | 页面级容器/展示面 |
50
+ | `xs` | 5px | 微型件内角:复选框、菜单项、日期格、小标签 |
51
+ | `sm` | 8px | 控件:按钮、输入框、选择器 |
52
+ | `md` | 10px | 内嵌块、大控件 |
53
+ | `lg` | 14px | 卡片、面板、菜单与 popover |
54
+ | `xl` | 20px | 弹窗与页面级展示面 |
55
55
  | `full` | 999px | **胶囊语义专用**(跑道形) |
56
56
 
57
57
  ### 2.2 同心圆法则(Concentric Corners,取法 Apple HIG)
@@ -22,7 +22,7 @@
22
22
 
23
23
  1. **作者种子** `--icen-design-*`:品牌色、表面、文字、几何、节奏、字体、材料参数。
24
24
  2. **语义映射**:推导已有 `--icen-token-* / --icen-radius-* / --icen-density-*`,让现有组件受益。
25
- 3. **材料角色**:content / chrome / floating,共享边缘、模糊和阴影配方。
25
+ 3. **材料角色**:content / chrome / floating,共享边缘、实面和阴影配方。
26
26
  4. **组件适配**:按钮、输入、分段选择、菜单、弹窗等,处理仅靠变量无法表达的细节。
27
27
 
28
28
  现代主题为中性瓷白+冷蓝,独立校准,不继承其它主题的配色。
@@ -40,12 +40,12 @@
40
40
  | 角色 | 背景 | 光与影 | 用途 |
41
41
  | --- | --- | --- | --- |
42
42
  | content | 不透明 | 轻边界,不投影 | 阅读与编辑 |
43
- | chrome | 条件启用透光 | 顶部微光 | 导航与操作 |
44
- | floating | 条件启用透光 | 接触影+环境影+顶部微光 | 临时面板 |
43
+ | chrome | 不透明 | 顶部微光 | 导航与操作 |
44
+ | floating | 不透明 | 接触影+环境影+顶部微光 | 临时面板 |
45
45
 
46
46
  布局、定位和内边距归业务页面。材料不携带固定宽高,不强行让所有内容成为卡片。`data-icen-material` 的通用外轮廓使用 lg 圆角;需要贴边的站栏可由布局覆盖。
47
47
 
48
- 透明度只在支持 backdrop-filter 的浏览器中启用,否则自动使用不透明表面。`prefers-reduced-transparency: reduce` 与 `<html data-icen-transparency="reduced">` 都强制不透明。透明表面的实际对比度依赖背后内容,仍需实屏验证。
48
+ modern 的内容、操作与临时面板始终使用不透明表面,不启用背景模糊。`glass-*` 参数保留供自有材料和既有品牌配方兼容使用;不会让 modern 的标准操作面变成玻璃。`prefers-reduced-transparency: reduce` 与 `<html data-icen-transparency="reduced">` 继续提供跨原语的实面降级。
49
49
 
50
50
  ## 修改与新增品牌
51
51
 
@@ -115,9 +115,9 @@ setDesign(brand.name);
115
115
  | success / warning / error / info | 明暗各有独立值,见源码 | 语义色 |
116
116
  | radius | 10px | 六档轮廓的共同起点 |
117
117
  | space | 4px | 布局节奏单位 |
118
- | control-height | 40px | 标准操作高度 |
119
- | font-size / font | 14px / 系统无衬线 | 界面阅读基准 |
120
- | glass-opacity / glass-blur | 82% / 20px;88% / 20px | 操作层材料 |
118
+ | control-height | 34px | 标准操作高度(density compact 28 / comfortable 38) |
119
+ | font-size / font | 13px / 系统无衬线 | 界面阅读基准;中文下限 12px |
120
+ | glass-opacity / glass-blur | 84% / 24px;90% / 24px | 自有材料的兼容参数,modern 标准组件不消费模糊 |
121
121
  | shadow-color / shadow-strength | 中性灰 11%;黑 28% | 接触影与环境影 |
122
122
  | light / highlight-strength | 白 70%;白 9% | 表面边缘光 |
123
123
  | edge-strength | 12% / 14% | 材料边界 |
@@ -128,8 +128,8 @@ CSS 作者可以直接覆盖全部种子;类型 API 暴露常用旋钮,并
128
128
  ## 现代的具体判断
129
129
 
130
130
  - **文字**:界面系统无衬线;代码单独等宽;数据才使用 tabular-nums。取消全局 Numeric Math 混排。正文阅读可在业务排版中提高到 16px。
131
- - **几何**:xs/sm/md/lg/xl 从共同控件半径推导;贴合内外轮廓同心,独立控件保留自身半径。分段选择内角扣掉外壳 padding 与边框。
132
- - **密度**:normal / compact / comfortable 改变间距和控件高度,不缩小文字;嵌套密度可恢复 normal。触摸环境控件至少 44px。
131
+ - **几何**:xs/sm/md/lg/xl 为 5/8/10/14/20px,从共同基准推导。控件 8px、卡片与面板 14px、弹窗 20px;贴合内外轮廓同心,独立控件保留自身半径。分段选择内角扣掉外壳 padding 与边框。
132
+ - **密度**:normal / compact / comfortable 改变间距和控件高度,不缩小文字;嵌套密度可恢复 normal。触摸环境控件至少 44px。KB 行内操作使用 `--icen-density-item-height`(normal 28 / compact 24 / comfortable 32px),嵌套密度重新计算字号角色。
133
133
  - **反馈**:hover 以中性变化为主,主要动作用品牌色;键盘焦点始终明确。按压轻缩放,减少位置漂移。
134
134
  - **选择**:分段选择使用中性表面和接触影,不把每次选择都变成品牌强调。
135
135
  - **光照**:暗色保留遮挡阴影,降低高光并重新设置边缘,避免照搬亮色投影。
@@ -149,7 +149,7 @@ CSS 作者可以直接覆盖全部种子;类型 API 暴露常用旋钮,并
149
149
 
150
150
  运行时使用 `setPrimitive("pixel")`;自建原语先 `registerPrimitive("brand-shape")`,再用 `[data-icen-style="brand-shape"]` 覆盖几何、字体、光影参数。主题仍单独由 setTheme({preset:...}) 选择。
151
151
 
152
- Apple 研究参考:[Materials](https://developer.apple.com/design/human-interface-guidelines/materials)、[Meet Liquid Glass](https://developer.apple.com/videos/play/wwdc2025/219/)。现代实现以内容/操作分层、同心几何、文字可读性为准则;Web 材料不是系统 Liquid Glass 的光学模拟。
152
+ 现代实现以内容/操作分层、同心几何、文字可读性为准则;使用稳定实面、细边与接触影建立空间。
153
153
 
154
154
  ## 中式与苏式原语
155
155
 
@@ -0,0 +1,105 @@
1
+ # 动效令牌与排版尺度(spec)
2
+
3
+ 面向实现者与评审。令牌定义在 `src/tokens/motion.css` 与 `src/tokens/typography.css`;运行时口径在 `src/behaviors/motion.ts`;DTCG 导出经 `scripts/dtcg.mjs`(`dist/tokens/dtcg.json`)。组件只消费令牌与语义别名,不写死时长、曲线、字号。
4
+
5
+ ## 1. 动效令牌
6
+
7
+ ### 1.1 时长阶梯
8
+
9
+ | 令牌 | 值 | 场景 | 反例 |
10
+ | --- | --- | --- | --- |
11
+ | `--icen-motion-duration-instant` | 0ms | 像素原语全量;状态复位 | 用它"省掉"必要的过渡反馈 |
12
+ | `--icen-motion-duration-fast` | 110ms | hover / press / 焦点环微反馈 | 浮层进出场(太短促) |
13
+ | `--icen-motion-duration-base` | 180ms | 展开收起、淡入淡出、勾选 | 页面级转场 |
14
+ | `--icen-motion-duration-slow` | 260ms | 浮层进出、modal、面板滑入 | 高频 hover 反馈(拖沓) |
15
+ | `--icen-motion-duration-deliberate` | 420ms | 页面级转场、强调入场 | 常规控件(必须克制,>420ms 需评审) |
16
+
17
+ 消费口径:组件读语义别名 `--icen-duration-fast/normal/slow/deliberate`(design.css 映射 = 基值 × `--icen-design-motion`);`instant` 同样有别名。新组件可直接读 `--icen-motion-duration-*` 基值(不缩放,用于设计工具对齐场景)。
18
+
19
+ ### 1.2 缓动集
20
+
21
+ | 令牌 | 值 | 场景 | 反例 |
22
+ | --- | --- | --- | --- |
23
+ | `--icen-motion-ease-standard` | cubic-bezier(.45,0,.25,1) | 持续类状态变化(颜色、宽度) | 入场(缺加速初速感) |
24
+ | `--icen-motion-ease-enter` | cubic-bezier(.16,1,.3,1) | 入场:快出慢归 | 离场(会显犹豫) |
25
+ | `--icen-motion-ease-exit` | cubic-bezier(.4,0,1,1) | 离场:快进加速 | 入场(像被弹开) |
26
+ | `--icen-motion-ease-emphasized` | cubic-bezier(.22,.8,.24,1) | 强调:长减速弧(hero、落板) | 高频微交互 |
27
+ | `--icen-motion-ease-spring` | linear() 阻尼弹簧近似(过冲 ≈8%);不支持 linear() 的浏览器回退 emphasized | 抽屉、卡片回弹 | 表单控件状态变化(过冲多余) |
28
+
29
+ 回退声明在 `motion.css` 的 `@supports (transition-timing-function: linear(0,1))` 块——可降级增强,不 polyfill。`linear()` / `steps()` 超出 DTCG 经典版标量,导出时明示跳过(`dtcg.json` 的 `ai.icen.skipped`)。
30
+
31
+ ### 1.3 幅度与编排
32
+
33
+ | 令牌 | 值 | 场景 | 反例 |
34
+ | --- | --- | --- | --- |
35
+ | `--icen-motion-shift-sm` | 2px | 行内微移(列表项 hover) | 弹层入场(幅度不足) |
36
+ | `--icen-motion-shift-md` | 6px | 浮层/气泡入场位移 | 抽屉 |
37
+ | `--icen-motion-shift-lg` | 12px | 抽屉/面板入场位移 | 行内微移(晃眼) |
38
+ | `--icen-motion-scale-enter` | .96 | 弹层入场起始缩放 | 大于 .96 的夸张缩放入场 |
39
+ | `--icen-motion-scale-press` | .985 | 按下形变 | 持续缩放循环 |
40
+ | `--icen-motion-stagger-step` | 24ms | 列表/卡片瀑布入场相邻延迟 | 超过 40ms 的排队(显卡顿) |
41
+ | `--icen-motion-stagger-count` | 5 | 级联上限,超出同拍 | 全列表逐项延迟(长尾等待) |
42
+
43
+ ### 1.4 与预设、原语的联动
44
+
45
+ - 配色预设(themes.json 六套)不动效:动效与色彩正交。
46
+ - 原语:pixel 原语把 `--icen-motion-ease-*` 全部改写为 `steps(1, end)`,且 `--icen-design-motion: 0` 使时长归零(点阵逐帧美学);chinese / soviet 沿用现代动效曲线,仅在其自有块覆盖排版与几何。
47
+ - 明暗:不动效。
48
+
49
+ ## 2. reduced-motion 策略
50
+
51
+ 降级链(实现于 `base.css`,运行时口径 `behaviors/motion.ts`):
52
+
53
+ 1. **默认遵循系统**:`@media (prefers-reduced-motion: reduce)` 时 `--icen-design-motion: 0` → 全部 `--icen-duration-*` 过渡瞬时完成;循环/环境动画(spinner、skeleton、脉冲)单次瞬时;平滑滚动关闭。(Chromium 实测:reduce 下 0s 被钳制为 0.01ms 序列化,语义等同瞬时,保证 transitionend 派发。)
54
+ 2. **手动覆盖**:`<html data-icen-motion="reduce">` 无需系统设置即可降级;`"full"` 在系统降级时显式恢复(演示机、用户显式选择)。属性优先级高于系统偏好。
55
+ 3. **降级而非移除**:状态变化仍然可见,只是瞬时完成;一次性的状态表达保留。组件编写约定:入场动画应同时含 opacity 与 transform——顺畅时是"移动+淡入",降级时是瞬时呈现,不会出现"什么都没发生"。
56
+ 4. **JS 同口径**:`icenMotionReduced()` 读取与 CSS 相同的判定(属性 > 系统);`onIcenMotionChange(cb)` 统一订阅 matchMedia 与属性改写,返回销毁函数;`setIcenMotion(mode|null)` 写覆盖。JS 驱动的视差、autoplay、canvas 循环必须走此口径停止运动、保留状态。
57
+
58
+ 反模式(守卫/评审拦截):组件内写死 `transition-duration` 毫秒值;用 `!important` 自创降级块;JS 动画只读 matchMedia 不看手动覆盖。
59
+
60
+ ## 3. 排版尺度
61
+
62
+ ### 3.1 内容排版尺度(typography.css)
63
+
64
+ 模块比例 1.250(大三度),`clamp()` 流体插值;面向内容/文档排版。控件字号仍由 `--icen-density-font-size-*` 驱动——**两套尺度解耦:密度档只压缩控件,不挤压阅读**。
65
+
66
+ | 令牌 | 区间(min→max) | 场景 |
67
+ | --- | --- | --- |
68
+ | `--icen-type-xs` | 11→12px | 角标、时间戳 |
69
+ | `--icen-type-sm` | 12.5→14.4px | 辅助说明、表注 |
70
+ | `--icen-type-md` | 14→16px | 正文基准 |
71
+ | `--icen-type-lg` | 16→20px | 小节标题、导语 |
72
+ | `--icen-type-xl` | 20→25px | 页标题 |
73
+ | `--icen-type-2xl` | 25→31.25px | 区块主标 |
74
+ | `--icen-type-3xl` | 31.25→39px | hero(克制使用) |
75
+
76
+ 行高:`--icen-leading-tight` 1.3(大标题)/ `-base` 1.6(正文,CJK 混排安全下限)/ `-loose` 1.8(长文)。字距:`--icen-tracking-tight` -.02em(大号拉丁标题)/ `-base` 0 / `-wide` .04em(眉标)。字重:`--icen-weight-regular/medium/semibold/bold` = 400/500/600/700。
77
+
78
+ ### 3.2 CJK 与拉丁混排
79
+
80
+ - 字体栈:`--icen-font-cjk` 默认跟随标题字体,栈内含 PingFang SC / Hiragino Sans GB / Microsoft YaHei(design.css);像素原语整体替换为点阵字体。
81
+ - 标点挤压:`text-spacing-trim: trim-start` 渐进增强(Chrome 123+,`@supports` 守卫;不支持即浏览器默认,不 polyfill)。
82
+ - 数字:数据密集区用 `font-variant-numeric: lining-nums tabular-nums`(`.icen-numeric` / `.icen-font-math` 已消费;新增 `--icen-feature-data` 令牌供新组件)。
83
+ - CJK 字距一律 0(`--icen-tracking-tight` 仅拉丁大标题;不对 CJK 正文加字距)。
84
+
85
+ ### 3.3 紧凑密度
86
+
87
+ `data-icen-density="compact|comfortable"` 只作用于 `--icen-density-*`(控件高度/间距/控件字号,style-profiles.css),不影响 `--icen-type-*` 内容尺度。数据密集界面应开密度档而不是缩小正文字号。
88
+
89
+ ## 4. DTCG 导出
90
+
91
+ `bun run dtcg` 导出时长(duration)、缓动(cubicBezier)、位移(dimension)、缩放/行高/字重/级联数(number)各族;clamp()、`linear()`、`steps()`、font-feature-settings 字符串超出经典版标量,逐条记录在 `ai.icen.skipped` 并注明原因——不猜不静默。
92
+
93
+ ## 5. 文档页信息结构(tokens 页扩展建议)
94
+
95
+ 1. 动效族:时长阶梯演示条(同曲线五档并排播放)→ 缓动曲线卡(SVG 曲线 + 用途/反例)→ 幅度尺(shift/scale 对照)→ stagger 演示列表。
96
+ 2. 降级演示:开关 `data-icen-motion="reduce|full|系统"`(调 `setIcenMotion`),同一块动画区实时对照。
97
+ 3. 排版族:尺度阶梯表(实际渲染字号 + 区间)→ 行高/字距对照 → CJK 混排样张 → 密度档对照(控件 vs 内容)。
98
+ 4. 每令牌一行:名称 / 值 / 一句话场景 / 反例(与本 spec 表格同源)。
99
+
100
+ ## 验收
101
+
102
+ - `bun run guard` 全绿(token 引用、meta、契约快照含新增变量与 motion.ts 导出)。
103
+ - `bun test tests/unit/motion.test.ts` 5/5:覆盖优先级、订阅销毁、非法值回退。
104
+ - `bun scripts/dtcg.mjs` 导出 motion-duration/motion-ease 等族,linear()/clamp() 记入 skipped。
105
+ - reduced-motion e2e:系统 reduce 下 `--icen-duration-fast` 计算值 0ms;`data-icen-motion="full"` 恢复 110ms;手动 reduce 无需系统设置。
@@ -0,0 +1,46 @@
1
+ # 滚动条
2
+
3
+ 全局使用原生滚动条,不替换滚动容器、不拦截滚轮、不模拟滑块。Chromium/WebKit 使用统一无箭头样式;Firefox 使用标准细滚动条,具体几何由浏览器和系统控制。浏览器、系统或强制颜色模式的可访问性设置可覆盖皮肤。
4
+
5
+ 标准 `scrollbar-color` / `scrollbar-width` 的非 auto 值会覆盖 WebKit 伪元素皮肤,因此支持伪元素的浏览器使用 auto 值以保留无箭头规则;其余浏览器使用标准属性回退。参考 [MDN scrollbar-color](https://developer.mozilla.org/en-US/docs/Web/CSS/Reference/Properties/scrollbar-color) 与 [WebKit 滚动条说明](https://webkit.org/blog/363/styling-scrollbars/)。
6
+
7
+ 全量引入 `@icen.ai/ui/ui.css` 即包含样式。按需引入时使用 `tokens.css` + `base.css`,再加需要的组件 CSS;`kit/scroll-area` 导出行为和容器样式,仍需上述全局底座。只引 CSS 时保持可见。启用闲置策略:
8
+
9
+ ```ts
10
+ import { initScrollArea } from '@icen.ai/ui/behaviors/scroll-area';
11
+ const dispose = initScrollArea(); // 文档委托,接管之后插入的原生滚动区与 portal
12
+ // 或 initScrollArea({ root: element, idleDelay: 1200 })
13
+ // 卸载时 dispose():移除监听、清理定时器并恢复状态属性
14
+ ```
15
+
16
+ | `data-icen-scrollbars` | 滚动时 | 悬停时 | 聚焦时 | 闲置后 |
17
+ | --- | --- | --- | --- | --- |
18
+ | `auto` | 显示 | 容器悬停时显示 | 显示 | 指针离开且失焦后隐藏 |
19
+ | `scroll`(启用行为后的默认) | 显示 | 不唤醒 | 显示 | 未聚焦时隐藏 |
20
+ | `visible` | 显示 | 显示 | 显示 | 显示 |
21
+ | `hidden` | 隐藏 | 隐藏 | 隐藏 | 隐藏,仍可滚动 |
22
+
23
+ 策略在子树继承,嵌套组件可另设模式。默认 scroll 下,指针停在内容区不阻止闲置隐藏;菜单等需要悬停时保持可见的区域可显式使用 auto。文档根滚动条不因整页悬停一直亮起。无溢出时浏览器不绘制滑块。闲置策略只改变颜色,不反复增减宽度,因此停止滚动时不会造成内容跳动。`hidden` 会取消滚动条占位,适合已有其他导航提示的区域。需要持续位置提示时用 visible。需要直接键盘滚动的普通容器应提供 `tabindex="0"` 和名称。
24
+
25
+ ```html
26
+ <div class="icen-scroll-area" tabindex="0" aria-label="运行日志"
27
+ data-icen-scrollbars="scroll" data-icen-scrollbar-delay="1200"
28
+ data-icen-scrollbar-gutter="stable"
29
+ style="max-height:20rem; --icen-token-scrollbar-size:10px">
30
+ …
31
+ </div>
32
+ ```
33
+
34
+ | 局部控制槽 | 默认 | 用途 |
35
+ | --- | --- | --- |
36
+ | `--icen-token-scrollbar-size` | 8px | 双轴尺寸;`--sm` 6px、`--lg` 12px |
37
+ | `--icen-token-scrollbar-inset` | 2px | 滑块与槽边的透明内距 |
38
+ | `--icen-token-scrollbar-track` | transparent | 轨道颜色 |
39
+ | `--icen-token-scrollbar-thumb` / `-thumb-hover` | 当前主题墨色混合 | 默认/悬停滑块颜色 |
40
+ | `--icen-token-scrollbar-idle-delay` | 900ms | 停止滚动多久后隐藏 |
41
+ | `--icen-token-scrollbar-fade-duration` | normal 动效时长 | 支持原生滑块颜色过渡的浏览器使用;其他环境直接隐藏 |
42
+ | `--icen-token-scrollbar-gutter` | auto | 原生留槽策略 |
43
+
44
+ 延时优先级:最近祖先的 `data-icen-scrollbar-delay`(毫秒)→ `idleDelay` 参数 → CSS token。运行时读取当前值,修改后下一次滚动生效。非法延时回退 900ms,范围限制为 0–60000ms。留槽也可用 `data-icen-scrollbar-gutter="auto|stable|both-edges"`,与是否显示滑块独立。
45
+
46
+ 减少动效时禁用颜色过渡,保留延时显示/隐藏;强制颜色模式恢复系统可见滚动条。原生控件内部、跨源 iframe 与 Shadow DOM 的封闭内部由其宿主控制;如需开放影子树内的滚动活动跟踪,应在内部容器单独初始化。
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@icen.ai/ui",
3
- "version": "0.10.0",
4
- "description": "Icen Design System — 设计 tokens(8 主题 × 4 原语 × 明暗)+ 无框架组件 CSS/行为 JS + AI 原生组件族(7 态状态机/多模态/定价审计)+ 图表通用层(ChartSpec 纯 JSON)+ AI 工具体系",
3
+ "version": "0.11.1",
4
+ "description": "Icen Design System — 设计 tokens(6 主题 × 4 原语 × 明暗)+ 无框架组件 CSS/行为 JS + AI 原生组件族(7 态状态机/多模态/定价审计)+ 图表通用层(ChartSpec 纯 JSON)+ AI 工具体系",
5
5
  "repository": {
6
6
  "type": "git",
7
7
  "url": "git+https://github.com/icen-ai/ui.git"
@@ -28,6 +28,10 @@
28
28
  "sideEffects": [
29
29
  "**/*.css"
30
30
  ],
31
+ "engines": {
32
+ "node": ">=18"
33
+ },
34
+ "packageManager": "bun@1.3.5",
31
35
  "peerDependencies": {
32
36
  "react": ">=18",
33
37
  "react-dom": ">=18",
@@ -58,14 +62,23 @@
58
62
  "dtcg": "bun scripts/dtcg.mjs",
59
63
  "design-tokens": "bun scripts/design-tokens.mjs",
60
64
  "guard": "bun scripts/guard/index.ts",
65
+ "meta": "bun scripts/meta.mjs",
66
+ "contracts": "bun scripts/contracts.ts --check",
67
+ "contracts:update": "bun scripts/contracts.ts --write",
68
+ "contracts:diff": "bun scripts/contracts.ts --diff",
69
+ "size": "bun scripts/size.ts",
70
+ "check:pkg": "bunx publint && bunx @arethetypeswrong/cli --pack . --ignore-rules no-resolution cjs-resolves-to-esm",
61
71
  "prepublishOnly": "bun run build",
62
72
  "pretest:e2e": "cd site && bun run build",
63
73
  "test": "bun test",
74
+ "test:coverage": "bun scripts/coverage.ts",
64
75
  "test:e2e": "playwright test",
65
- "verify": "bunx tsc --noEmit && bun run guard && bun test && bun run build",
76
+ "test:e2e:update": "playwright test --update-snapshots",
77
+ "verify": "bunx tsc --noEmit && bun run guard && bun test && bun run build && bun run size",
66
78
  "colors": "bun scripts/theme-colors.mjs"
67
79
  },
68
80
  "devDependencies": {
81
+ "@arethetypeswrong/cli": "^0.18.5",
69
82
  "@happy-dom/global-registrator": "^20.14.5",
70
83
  "@playwright/test": "^1.63.0",
71
84
  "@types/node": "^20.14.0",
@@ -73,6 +86,7 @@
73
86
  "@types/react-dom": "^19.3.0",
74
87
  "axe-core": "^4.14.0",
75
88
  "happy-dom": "^20.14.5",
89
+ "publint": "^0.3.25",
76
90
  "react": "^19.3.0",
77
91
  "react-dom": "^19.3.0",
78
92
  "tsup": "^8.3.0",