@icen.ai/ui 0.9.0 → 0.10.0

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 (281) hide show
  1. package/AGENTS.md +138 -80
  2. package/README.md +66 -91
  3. package/dist/base.css +208 -179
  4. package/dist/behaviors/accordion.mjs +8 -8
  5. package/dist/behaviors/ai-branch.d.mts +1 -1
  6. package/dist/behaviors/ai-branch.mjs +1010 -94
  7. package/dist/behaviors/ai-chat.d.mts +7 -7
  8. package/dist/behaviors/ai-chat.mjs +1071 -161
  9. package/dist/behaviors/ai-composer.d.mts +44 -12
  10. package/dist/behaviors/ai-composer.mjs +1997 -524
  11. package/dist/behaviors/ai-core.d.mts +1 -1
  12. package/dist/behaviors/ai-core.mjs +1016 -107
  13. package/dist/behaviors/ai-diff.mjs +1019 -127
  14. package/dist/behaviors/ai-feedback.d.mts +1 -1
  15. package/dist/behaviors/ai-feedback.mjs +1035 -126
  16. package/dist/behaviors/ai-panel.d.mts +8 -8
  17. package/dist/behaviors/ai-panel.mjs +1284 -266
  18. package/dist/behaviors/ai-provider.mjs +1003 -101
  19. package/dist/behaviors/ai-threads.d.mts +1 -1
  20. package/dist/behaviors/ai-threads.mjs +1068 -154
  21. package/dist/behaviors/ai-tool.d.mts +2 -2
  22. package/dist/behaviors/ai-tool.mjs +2037 -396
  23. package/dist/behaviors/ai-tools.d.mts +89 -16
  24. package/dist/behaviors/ai-tools.mjs +4448 -372
  25. package/dist/behaviors/autocomplete.d.mts +53 -0
  26. package/dist/behaviors/autocomplete.mjs +1600 -0
  27. package/dist/behaviors/back-top.d.mts +1 -1
  28. package/dist/behaviors/back-top.mjs +951 -14
  29. package/dist/behaviors/carousel.d.mts +1 -1
  30. package/dist/behaviors/carousel.mjs +906 -11
  31. package/dist/behaviors/cascader.d.mts +48 -0
  32. package/dist/behaviors/cascader.mjs +1853 -0
  33. package/dist/behaviors/charts.d.mts +72 -8
  34. package/dist/behaviors/charts.mjs +1901 -256
  35. package/dist/behaviors/code-block.d.mts +36 -0
  36. package/dist/behaviors/code-block.mjs +1611 -0
  37. package/dist/behaviors/command-palette.d.mts +9 -6
  38. package/dist/behaviors/command-palette.mjs +161 -59
  39. package/dist/behaviors/context-menu.d.mts +9 -8
  40. package/dist/behaviors/context-menu.mjs +1112 -44
  41. package/dist/behaviors/controls.d.mts +13 -13
  42. package/dist/behaviors/controls.mjs +989 -130
  43. package/dist/behaviors/copy.d.mts +21 -2
  44. package/dist/behaviors/copy.mjs +1206 -42
  45. package/dist/behaviors/datatable.d.mts +53 -3
  46. package/dist/behaviors/datatable.mjs +1963 -207
  47. package/dist/behaviors/date-picker.d.mts +0 -1
  48. package/dist/behaviors/date-picker.mjs +1340 -293
  49. package/dist/behaviors/design.d.mts +54 -0
  50. package/dist/behaviors/design.mjs +109 -0
  51. package/dist/behaviors/dropdown.d.mts +5 -6
  52. package/dist/behaviors/dropdown.mjs +262 -110
  53. package/dist/behaviors/events.d.mts +120 -3
  54. package/dist/behaviors/events.mjs +47 -2
  55. package/dist/behaviors/feedback.d.mts +30 -0
  56. package/dist/behaviors/feedback.mjs +296 -0
  57. package/dist/behaviors/focus.d.mts +8 -0
  58. package/dist/behaviors/focus.mjs +24 -0
  59. package/dist/behaviors/form-validate.d.mts +102 -0
  60. package/dist/behaviors/form-validate.mjs +6091 -0
  61. package/dist/behaviors/i18n.d.mts +789 -0
  62. package/dist/behaviors/i18n.mjs +1711 -0
  63. package/dist/behaviors/icons.d.mts +93 -0
  64. package/dist/behaviors/icons.mjs +113 -0
  65. package/dist/behaviors/input.d.mts +9 -1
  66. package/dist/behaviors/input.mjs +1056 -60
  67. package/dist/behaviors/kb-access.d.mts +1 -1
  68. package/dist/behaviors/kb-access.mjs +2129 -239
  69. package/dist/behaviors/kb-acl.d.mts +6 -6
  70. package/dist/behaviors/kb-acl.mjs +1119 -179
  71. package/dist/behaviors/kb-answer.mjs +2070 -418
  72. package/dist/behaviors/kb-audit.d.mts +1 -1
  73. package/dist/behaviors/kb-audit.mjs +1076 -154
  74. package/dist/behaviors/kb-canvas.mjs +1100 -177
  75. package/dist/behaviors/kb-chain.mjs +1022 -100
  76. package/dist/behaviors/kb-checkpoint.d.mts +1 -1
  77. package/dist/behaviors/kb-checkpoint.mjs +1319 -169
  78. package/dist/behaviors/kb-chunks.mjs +1152 -213
  79. package/dist/behaviors/kb-citation.d.mts +1 -1
  80. package/dist/behaviors/kb-citation.mjs +1201 -179
  81. package/dist/behaviors/kb-clarify.mjs +1058 -130
  82. package/dist/behaviors/kb-conflict.mjs +1041 -119
  83. package/dist/behaviors/kb-connector.mjs +1104 -176
  84. package/dist/behaviors/kb-core.d.mts +6 -1
  85. package/dist/behaviors/kb-core.mjs +1077 -162
  86. package/dist/behaviors/kb-eval.mjs +1971 -144
  87. package/dist/behaviors/kb-explain.d.mts +1 -1
  88. package/dist/behaviors/kb-explain.mjs +1024 -102
  89. package/dist/behaviors/kb-filter.mjs +2008 -178
  90. package/dist/behaviors/kb-gap.d.mts +1 -1
  91. package/dist/behaviors/kb-gap.mjs +1043 -121
  92. package/dist/behaviors/kb-hittest.d.mts +1 -1
  93. package/dist/behaviors/kb-hittest.mjs +1093 -150
  94. package/dist/behaviors/kb-metadata.mjs +1052 -130
  95. package/dist/behaviors/kb-passage.d.mts +2 -2
  96. package/dist/behaviors/kb-passage.mjs +1101 -161
  97. package/dist/behaviors/kb-pipeline.d.mts +2 -2
  98. package/dist/behaviors/kb-pipeline.mjs +1082 -162
  99. package/dist/behaviors/kb-qa.mjs +1088 -160
  100. package/dist/behaviors/kb-rerank.mjs +1047 -114
  101. package/dist/behaviors/kb-retrieval.mjs +2063 -224
  102. package/dist/behaviors/kb-review.mjs +1990 -159
  103. package/dist/behaviors/kb-sandbox.d.mts +1 -1
  104. package/dist/behaviors/kb-sandbox.mjs +1026 -104
  105. package/dist/behaviors/kb-segment.mjs +1111 -179
  106. package/dist/behaviors/kb-select.d.mts +24 -0
  107. package/dist/behaviors/kb-select.mjs +1989 -0
  108. package/dist/behaviors/kb-sources.d.mts +1 -1
  109. package/dist/behaviors/kb-sources.mjs +1084 -170
  110. package/dist/behaviors/kb-sql.d.mts +1 -1
  111. package/dist/behaviors/kb-sql.mjs +1143 -226
  112. package/dist/behaviors/kb-trace.d.mts +1 -1
  113. package/dist/behaviors/kb-trace.mjs +1042 -128
  114. package/dist/behaviors/kb-visibility.mjs +1086 -158
  115. package/dist/behaviors/kb-who-can.mjs +1974 -137
  116. package/dist/behaviors/mentions.d.mts +93 -0
  117. package/dist/behaviors/mentions.mjs +2152 -0
  118. package/dist/behaviors/modal.d.mts +4 -3
  119. package/dist/behaviors/modal.mjs +1055 -33
  120. package/dist/behaviors/nav.d.mts +1 -1
  121. package/dist/behaviors/nav.mjs +6 -6
  122. package/dist/behaviors/notification.d.mts +16 -8
  123. package/dist/behaviors/notification.mjs +1615 -265
  124. package/dist/behaviors/panel.d.mts +4 -0
  125. package/dist/behaviors/panel.mjs +994 -0
  126. package/dist/behaviors/popover.d.mts +28 -5
  127. package/dist/behaviors/popover.mjs +225 -24
  128. package/dist/behaviors/select.d.mts +5 -2
  129. package/dist/behaviors/select.mjs +1410 -117
  130. package/dist/behaviors/sidebar.d.mts +1 -1
  131. package/dist/behaviors/sidebar.mjs +13 -13
  132. package/dist/behaviors/slider.d.mts +1 -1
  133. package/dist/behaviors/slider.mjs +9 -9
  134. package/dist/behaviors/split-pane.d.mts +1 -1
  135. package/dist/behaviors/split-pane.mjs +7 -7
  136. package/dist/behaviors/suggestions.d.mts +27 -0
  137. package/dist/behaviors/suggestions.mjs +1089 -0
  138. package/dist/behaviors/svg-parse.d.mts +14 -0
  139. package/dist/behaviors/svg-parse.mjs +37 -0
  140. package/dist/behaviors/tabs.d.mts +2 -2
  141. package/dist/behaviors/tabs.mjs +25 -25
  142. package/dist/behaviors/tag-input.d.mts +23 -5
  143. package/dist/behaviors/tag-input.mjs +1359 -104
  144. package/dist/behaviors/theme-switcher.d.mts +24 -0
  145. package/dist/behaviors/theme-switcher.mjs +1981 -0
  146. package/dist/behaviors/theme.d.mts +15 -8
  147. package/dist/behaviors/theme.mjs +390 -28
  148. package/dist/behaviors/toast.d.mts +24 -25
  149. package/dist/behaviors/toast.mjs +1266 -88
  150. package/dist/behaviors/tooltip.d.mts +4 -0
  151. package/dist/behaviors/tooltip.mjs +378 -0
  152. package/dist/behaviors/tree-select.d.mts +69 -0
  153. package/dist/behaviors/tree-select.mjs +1907 -0
  154. package/dist/behaviors/tree.d.mts +1 -1
  155. package/dist/behaviors/tree.mjs +15 -15
  156. package/dist/behaviors/upload.d.mts +3 -2
  157. package/dist/behaviors/upload.mjs +1076 -66
  158. package/dist/cli.mjs +5 -6
  159. package/dist/components/ai-chat.css +666 -573
  160. package/dist/components/ai-diff.css +153 -132
  161. package/dist/components/ai-panel.css +351 -343
  162. package/dist/components/ai-tool.css +393 -238
  163. package/dist/components/autocomplete.css +61 -0
  164. package/dist/components/autocomplete.mjs +3 -0
  165. package/dist/components/back-top.css +34 -31
  166. package/dist/components/badge.css +44 -41
  167. package/dist/components/breadcrumb.css +67 -46
  168. package/dist/components/btn.css +80 -74
  169. package/dist/components/card.css +117 -106
  170. package/dist/components/cascader.css +311 -0
  171. package/dist/components/cascader.mjs +3 -0
  172. package/dist/components/chart-area.css +8 -2
  173. package/dist/components/chart-bar.css +95 -33
  174. package/dist/components/chart-gauge.css +14 -11
  175. package/dist/components/chart-graph.css +20 -17
  176. package/dist/components/chart-heatmap.css +96 -90
  177. package/dist/components/chart-line.css +8 -3
  178. package/dist/components/chart-pie.css +9 -6
  179. package/dist/components/chart-radar.css +8 -5
  180. package/dist/components/chart-scatter.css +9 -6
  181. package/dist/components/chart-sparkline.css +5 -2
  182. package/dist/components/chart-stack.css +14 -11
  183. package/dist/components/charts.css +164 -73
  184. package/dist/components/code-block.css +418 -0
  185. package/dist/components/code-block.mjs +4 -0
  186. package/dist/components/command-palette.css +138 -117
  187. package/dist/components/content.css +257 -251
  188. package/dist/components/copy.css +72 -44
  189. package/dist/components/datatable.css +423 -181
  190. package/dist/components/date-picker.css +135 -104
  191. package/dist/components/empty.css +68 -65
  192. package/dist/components/feedback.css +201 -183
  193. package/dist/components/form-validate.css +120 -0
  194. package/dist/components/form-validate.mjs +3 -0
  195. package/dist/components/form.css +150 -127
  196. package/dist/components/icon.css +102 -0
  197. package/dist/components/icon.mjs +3 -0
  198. package/dist/components/input.css +159 -104
  199. package/dist/components/kb-agent.css +188 -173
  200. package/dist/components/kb-data.css +257 -253
  201. package/dist/components/kb-ground.css +197 -185
  202. package/dist/components/kb-ingest.css +334 -350
  203. package/dist/components/kb-ops.css +265 -259
  204. package/dist/components/kb-perm.css +260 -271
  205. package/dist/components/kb-search.css +317 -360
  206. package/dist/components/kb.css +120 -109
  207. package/dist/components/layout.css +85 -82
  208. package/dist/components/material-chinese.css +73 -0
  209. package/dist/components/material-soviet.css +76 -0
  210. package/dist/components/material.css +275 -0
  211. package/dist/components/media.css +220 -166
  212. package/dist/components/mentions.css +189 -0
  213. package/dist/components/mentions.mjs +3 -0
  214. package/dist/components/menu.css +113 -105
  215. package/dist/components/modal.css +107 -112
  216. package/dist/components/nav.css +118 -115
  217. package/dist/components/notification.css +238 -174
  218. package/dist/components/pagination.css +56 -53
  219. package/dist/components/panel.css +66 -63
  220. package/dist/components/panel.mjs +1 -0
  221. package/dist/components/pill.css +81 -71
  222. package/dist/components/popover.css +67 -53
  223. package/dist/components/scroll-area.css +113 -110
  224. package/dist/components/segmented.css +146 -143
  225. package/dist/components/select.css +206 -186
  226. package/dist/components/sidebar.css +137 -127
  227. package/dist/components/slider.css +117 -114
  228. package/dist/components/split-pane.css +112 -109
  229. package/dist/components/stat.css +112 -106
  230. package/dist/components/steps.css +109 -103
  231. package/dist/components/switch.css +138 -134
  232. package/dist/components/table.css +131 -107
  233. package/dist/components/tabs.css +114 -108
  234. package/dist/components/tag-input.css +48 -133
  235. package/dist/components/tag.css +81 -71
  236. package/dist/components/theme-switcher.css +105 -0
  237. package/dist/components/theme-switcher.mjs +3 -0
  238. package/dist/components/toast.css +100 -86
  239. package/dist/components/toolbar.css +45 -42
  240. package/dist/components/tooltip.css +102 -43
  241. package/dist/components/tooltip.mjs +1 -0
  242. package/dist/components/tree-select.css +416 -0
  243. package/dist/components/tree-select.mjs +3 -0
  244. package/dist/components/upload.css +135 -92
  245. package/dist/fonts/LICENSES/ark-pixel/OFL.txt +96 -0
  246. package/dist/fonts/LICENSES/cubic-11/OFL.txt +108 -0
  247. package/dist/fonts/LICENSES/galmuri/LICENSE.txt +93 -0
  248. package/dist/fonts/OFL.txt +96 -0
  249. package/dist/fonts/README.md +14 -0
  250. package/dist/fonts/fusion-pixel-12px-zh-hans.woff2 +0 -0
  251. package/dist/index.d.mts +28 -14
  252. package/dist/index.mjs +20705 -9601
  253. package/dist/react.d.mts +91 -0
  254. package/dist/react.mjs +8208 -0
  255. package/dist/registry.json +130 -13
  256. package/dist/tokens/chinese.css +44 -0
  257. package/dist/tokens/colors.css +365 -1222
  258. package/dist/tokens/design.css +109 -0
  259. package/dist/tokens/dtcg.json +11198 -0
  260. package/dist/tokens/figma.variables.json +7017 -0
  261. package/dist/tokens/icon-masks.css +78 -0
  262. package/dist/tokens/pixel.css +50 -0
  263. package/dist/tokens/soviet.css +44 -0
  264. package/dist/tokens/style-profiles.css +36 -547
  265. package/dist/tokens/themes.json +308 -0
  266. package/dist/tokens/tokens-studio.json +6728 -0
  267. package/dist/tokens/typography.css +21 -18
  268. package/dist/tokens.css +1555 -1801
  269. package/dist/ui.css +11975 -9831
  270. package/dist/vue.d.mts +344 -0
  271. package/dist/vue.mjs +7781 -0
  272. package/docs/spec/ai-input-experience.md +75 -0
  273. package/docs/spec/ai-native.md +238 -147
  274. package/docs/spec/design-philosophy.md +189 -0
  275. package/docs/spec/design-primitives.md +196 -0
  276. package/docs/spec/kb-family.md +147 -115
  277. package/package.json +43 -8
  278. package/dist/retro-effects.css +0 -255
  279. package/dist/tokens/retro-effects.css +0 -255
  280. package/docs/research/2026-10-03-ai-kb-components.md +0 -392
  281. package/docs/research/2026-10-03-kb-permissions.md +0 -992
@@ -1,44 +1,45 @@
1
+ @layer icen.components {
1
2
  /*
2
3
  * @icen.ai/ui — Component: btn(按钮)
3
4
  *
4
5
  * 完整契约:
5
- * <button class="btn [.btn-primary|.btn-danger|.btn-ghost|.btn-link] [.btn-sm|.btn-lg] [.btn-block] [.btn-icon]
6
- * [.is-loading] [.is-error] [disabled]|[aria-disabled=true]|[data-disabled]>
7
- * [<svg class="btn-icon-start">…</svg>] 可选前置图标(与 .btn-icon 不同:.btn-icon 是纯图标钮)
6
+ * <button class="icen-btn [.icen-btn-primary|.icen-btn-danger|.icen-btn-ghost|.icen-btn-link] [.icen-btn-sm|.icen-btn-lg] [.icen-btn-block] [.icen-btn-icon]
7
+ * [.is-loading] [.is-error] [disabled]|[aria-disabled=true]|[data-icen-disabled]>
8
+ * [<svg class="icen-btn-icon-start">…</svg>] 可选前置图标(与 .icen-btn-icon 不同:.icen-btn-icon 是纯图标钮)
8
9
  * <span class="btn-text">文本</span>
9
- * [<svg class="btn-icon-end">…</svg>] 可选后置图标
10
+ * [<svg class="icen-btn-icon-end">…</svg>] 可选后置图标
10
11
  * </button>
11
12
  *
12
13
  * 变体:
13
- * .btn 默认(surface 底 + outline-soft 描边)
14
- * .btn-primary 实心 accent
15
- * .btn-danger 透明底 + error 描边(hover 实心)
16
- * .btn-ghost 全透明,hover 浮起 fill-2
17
- * .btn-link link 文本按钮(无背景、underline on hover)
14
+ * .icen-btn 默认(surface 底 + outline-soft 描边)
15
+ * .icen-btn-primary 实心 accent
16
+ * .icen-btn-danger 透明底 + error 描边(hover 实心)
17
+ * .icen-btn-ghost 全透明,hover 浮起 fill-2
18
+ * .icen-btn-link link 文本按钮(无背景、underline on hover)
18
19
  *
19
- * 尺寸:默认 / .btn-sm / .btn-lg / .btn-icon(正方形)
20
- * 状态:.is-loading 加 spinner + aria-busy;.is-error error 边;disabled/aria-disabled/data-disabled
20
+ * 尺寸:默认 / .icen-btn-sm / .icen-btn-lg / .icen-btn-icon(正方形)
21
+ * 状态:.is-loading 加 spinner + aria-busy;.is-error error 边;disabled/aria-disabled/data-icen-disabled
21
22
  */
22
23
 
23
- .btn {
24
- --btn-bg: var(--token-surface);
25
- --btn-fg: var(--token-text);
26
- --btn-border: var(--token-line-soft);
27
- --btn-bg-hover: var(--token-surface-hover);
28
- --btn-border-hover: var(--token-accent);
24
+ .icen-btn {
25
+ --btn-bg: var(--icen-token-surface);
26
+ --btn-fg: var(--icen-token-text);
27
+ --btn-border: var(--icen-token-line-soft);
28
+ --btn-bg-hover: var(--icen-token-surface-hover);
29
+ --btn-border-hover: var(--icen-token-accent);
29
30
 
30
31
  display: inline-flex;
31
32
  align-items: center;
32
33
  justify-content: center;
33
34
  gap: 6px;
34
- padding: 0 var(--density-space-md);
35
- height: var(--density-input-height-md);
35
+ padding: 0 var(--icen-density-space-md);
36
+ height: var(--icen-density-input-height-md);
36
37
  background: var(--btn-bg);
37
38
  color: var(--btn-fg);
38
39
  border: 1px solid var(--btn-border);
39
- border-radius: var(--radius-md);
40
- font-family: var(--font-body);
41
- font-size: var(--density-font-size-md);
40
+ border-radius: var(--icen-radius-md);
41
+ font-family: var(--icen-font-body);
42
+ font-size: var(--icen-density-font-size-md);
42
43
  font-weight: 500;
43
44
  letter-spacing: 0.01em;
44
45
  white-space: nowrap;
@@ -53,19 +54,19 @@
53
54
  box-shadow var(--icen-tx-fast),
54
55
  transform var(--icen-tx-fast);
55
56
  }
56
- .btn:hover {
57
+ .icen-btn:hover {
57
58
  background: var(--btn-bg-hover);
58
59
  border-color: var(--btn-border-hover);
59
60
  }
60
- .btn:active { transform: var(--icen-press-soft); }
61
- .btn:focus-visible {
61
+ .icen-btn:active { transform: var(--icen-press-soft); }
62
+ .icen-btn:focus-visible {
62
63
  outline: none;
63
64
  box-shadow: var(--icen-ring);
64
65
  }
65
- .btn:disabled,
66
- .btn[aria-disabled='true'],
67
- .btn[data-disabled],
68
- .btn.is-loading {
66
+ .icen-btn:disabled,
67
+ .icen-btn[aria-disabled='true'],
68
+ .icen-btn[data-icen-disabled],
69
+ .icen-btn.is-loading {
69
70
  cursor: not-allowed;
70
71
  opacity: var(--icen-disabled-opacity);
71
72
  transform: none;
@@ -73,37 +74,40 @@
73
74
  }
74
75
 
75
76
  /* ── 变体 ── */
76
- .btn-primary {
77
- --btn-bg: var(--token-accent);
78
- --btn-fg: var(--token-on-accent);
79
- --btn-border: var(--token-accent);
80
- --btn-bg-hover: var(--token-accent-deep, color-mix(in srgb, var(--token-accent) 85%, black));
81
- --btn-border-hover: var(--token-accent-deep, var(--token-accent));
82
- }
83
- .btn-primary:hover {
84
- box-shadow: var(--token-shadow-elevated);
77
+ .icen-btn-primary {
78
+ --btn-bg: var(--icen-token-accent-strong);
79
+ --btn-fg: var(--icen-token-on-accent);
80
+ --btn-border: var(--icen-token-accent-strong);
81
+ --btn-bg-hover: color-mix(in srgb, var(--icen-token-accent-strong) 88%, black);
82
+ --btn-border-hover: color-mix(in srgb, var(--icen-token-accent-strong) 88%, black);
83
+ }
84
+ /* hover 阴影抬升仅可悬停设备生效(触屏关闭,AGENTS 动效守卫) */
85
+ @media (hover: hover) and (pointer: fine) {
86
+ .icen-btn-primary:hover {
87
+ box-shadow: var(--icen-token-shadow-elevated);
88
+ }
85
89
  }
86
90
 
87
- .btn-danger {
88
- --btn-fg: var(--token-error);
89
- --btn-border: color-mix(in srgb, var(--token-error) 35%, transparent);
91
+ .icen-btn-danger {
92
+ --btn-fg: var(--icen-token-error);
93
+ --btn-border: color-mix(in srgb, var(--icen-token-error) 35%, transparent);
90
94
  --btn-bg: transparent;
91
- --btn-bg-hover: var(--token-error);
92
- --btn-border-hover: var(--token-error);
95
+ --btn-bg-hover: var(--icen-token-error);
96
+ --btn-border-hover: var(--icen-token-error);
93
97
  }
94
- .btn-danger:hover { color: var(--token-on-accent); }
98
+ .icen-btn-danger:hover { color: var(--icen-token-on-accent); }
95
99
 
96
- .btn-ghost {
100
+ .icen-btn-ghost {
97
101
  --btn-bg: transparent;
98
102
  --btn-border: transparent;
99
- --btn-bg-hover: var(--token-fill-2);
103
+ --btn-bg-hover: var(--icen-token-fill-2);
100
104
  --btn-border-hover: transparent;
101
105
  }
102
106
 
103
- .btn-link {
107
+ .icen-btn-link {
104
108
  --btn-bg: transparent;
105
109
  --btn-border: transparent;
106
- --btn-fg: var(--token-accent);
110
+ --btn-fg: var(--icen-token-accent);
107
111
  --btn-bg-hover: transparent;
108
112
  --btn-border-hover: transparent;
109
113
  height: auto;
@@ -112,69 +116,71 @@
112
116
  border-radius: 0;
113
117
  text-decoration: none;
114
118
  }
115
- .btn-link:hover {
119
+ .icen-btn-link:hover {
116
120
  text-decoration: underline;
117
121
  text-underline-offset: 3px;
118
122
  background: transparent;
119
123
  }
120
124
 
121
125
  /* ── 尺寸 ── */
122
- .btn-sm {
123
- height: var(--density-input-height-sm);
124
- padding: 0 var(--density-space-sm);
125
- font-size: var(--density-font-size-sm);
126
+ .icen-btn-sm {
127
+ height: var(--icen-density-input-height-sm);
128
+ padding: 0 var(--icen-density-space-sm);
129
+ font-size: var(--icen-density-font-size-sm);
126
130
  gap: 4px;
127
131
  }
128
- .btn-lg {
129
- height: var(--density-input-height-lg);
130
- padding: 0 var(--density-space-lg);
131
- font-size: var(--density-font-size-lg);
132
+ .icen-btn-lg {
133
+ height: var(--icen-density-input-height-lg);
134
+ padding: 0 var(--icen-density-space-lg);
135
+ font-size: var(--icen-density-font-size-lg);
132
136
  gap: 8px;
133
137
  }
134
- .btn-icon {
135
- width: var(--density-input-height-md);
138
+ .icen-btn-icon {
139
+ width: var(--icen-density-input-height-md);
136
140
  padding: 0;
137
141
  gap: 0;
138
142
  }
139
- .btn-icon.btn-sm { width: var(--density-input-height-sm); }
140
- .btn-icon.btn-lg { width: var(--density-input-height-lg); }
143
+ .icen-btn-icon.icen-btn-sm { width: var(--icen-density-input-height-sm); }
144
+ .icen-btn-icon.icen-btn-lg { width: var(--icen-density-input-height-lg); }
141
145
 
142
- .btn-block {
146
+ .icen-btn-block {
143
147
  display: flex;
144
148
  width: 100%;
145
149
  }
146
150
 
147
151
  /* ── 状态 ── */
148
- .btn.is-error {
149
- --btn-border: var(--token-error);
150
- --btn-border-hover: var(--token-error);
152
+ .icen-btn.is-error {
153
+ --btn-border: var(--icen-token-error);
154
+ --btn-border-hover: var(--icen-token-error);
151
155
  }
152
156
 
153
- /* 加载态:左侧 spinner 占位 + 文本保留(避免重排)。
157
+ /* 加载态:居中 spinner 占位 + 文本保留(避免重排)。
154
158
  behavior 在挂 .is-loading 时把 [aria-busy=true] 也挂上。 */
155
- .btn.is-loading { position: relative; color: transparent; }
156
- .btn.is-loading::after {
159
+ .icen-btn.is-loading { position: relative; color: transparent; }
160
+ .icen-btn.is-loading::after {
157
161
  content: '';
158
162
  position: absolute;
159
- top: 50%; left: 50%;
163
+ top: 50%; left: 50%; /* guard:allow-physical 圆心居中:left 50% + 负边距 任意方向下均为中心 */
160
164
  width: 14px; height: 14px;
161
- margin: -7px 0 0 -7px;
165
+ margin: -7px 0 0 -7px; /* guard:allow-physical 居中负边距与 left 50% 配套(物理坐标对),RTL 下同样居中 */
162
166
  border: 2px solid color-mix(in srgb, currentColor 35%, transparent);
163
167
  border-top-color: currentColor;
164
168
  border-radius: 50%;
165
- animation: icen-spin var(--btn-spin-duration, var(--duration-slow)) linear infinite;
166
- opacity: 1; /* 覆盖 .pressable::after 渐变(若与 .pressable 同用) */
169
+ animation: icen-spin var(--btn-spin-duration, var(--icen-duration-slow)) linear infinite;
170
+ opacity: 1; /* 覆盖 .icen-pressable::after 渐变(若与 .icen-pressable 同用) */
167
171
  background: none;
168
172
  pointer-events: none;
169
173
  }
170
174
 
171
175
  /* 图标按钮内部 svg 默认尺寸对齐字号 */
172
- .btn-icon-start, .btn-icon-end {
176
+ .icen-btn-icon-start, .icen-btn-icon-end {
173
177
  width: 1.1em;
174
178
  height: 1.1em;
175
179
  flex-shrink: 0;
176
180
  }
177
181
 
178
182
  @media (prefers-reduced-motion: reduce) {
179
- .btn.is-loading::after { --btn-spin-duration: 1.2s; }
183
+ .icen-btn.is-loading::after { --btn-spin-duration: 1.2s; }
184
+ }
185
+
180
186
  }
@@ -1,221 +1,232 @@
1
+ @layer icen.components {
1
2
  /*
2
3
  * @icen.ai/ui — Component: card(组合卡片容器)
3
4
  *
4
5
  * 完整契约:
5
- * <div class="card [.card--elevated|.card--outlined|.card--glass|.card--flat|.card--interactive] [.is-selected]">
6
- * <div class="card-media"> ← 可选:封面图区
6
+ * <div class="icen-card [.icen-card--elevated|.icen-card--outlined|.icen-card--glass|.icen-card--flat|.icen-card--interactive] [.is-selected]">
7
+ * <div class="icen-card-media"> ← 可选:封面图区
7
8
  * <img src="…" />
8
- * <span class="card-tag">置顶</span> ← 可选:图上徽标
9
+ * <span class="icen-card-tag">置顶</span> ← 可选:图上徽标
9
10
  * </div>
10
- * <div class="card-head">
11
+ * <div class="icen-card-head">
11
12
  * <div>
12
- * <h3 class="card-title">标题</h3>
13
- * <p class="card-desc">副标题(可选)</p>
13
+ * <h3 class="icen-card-title">标题</h3>
14
+ * <p class="icen-card-desc">副标题(可选)</p>
14
15
  * </div>
15
- * <div class="card-action"><button>…</button></div>
16
+ * <div class="icen-card-action"><button>…</button></div>
16
17
  * </div>
17
- * <div class="card-body">…</div>
18
- * <div class="card-foot">
19
- * <div class="card-meta">…</div>
20
- * <div class="card-action">…</div>
18
+ * <div class="icen-card-body">…</div>
19
+ * <div class="icen-card-foot">
20
+ * <div class="icen-card-meta">…</div>
21
+ * <div class="icen-card-action">…</div>
21
22
  * </div>
22
23
  * </div>
23
24
  *
24
25
  * 规格源自 opengal src/presentation/ui/data/card.tsx。
25
26
  */
26
27
 
27
- .card {
28
+ .icen-card {
28
29
  position: relative;
29
- background: var(--token-card);
30
- border: 1px solid var(--token-outline-soft);
31
- box-shadow: var(--token-shadow-inset);
32
- border-radius: var(--radius-lg);
30
+ background: var(--icen-token-card);
31
+ border: 1px solid var(--icen-token-outline-soft);
32
+ box-shadow: var(--icen-token-shadow-inset);
33
+ border-radius: var(--icen-radius-lg);
33
34
  overflow: hidden;
34
35
  }
35
36
 
36
37
  /* ── 变体 ── */
37
- .card--elevated {
38
- box-shadow: var(--token-shadow-card);
38
+ .icen-card--elevated {
39
+ box-shadow: var(--icen-token-shadow-card);
39
40
  border-color: transparent;
40
41
  }
41
- .card--outlined {
42
- border-color: var(--token-outline);
42
+ .icen-card--outlined {
43
+ border-color: var(--icen-token-outline);
43
44
  box-shadow: none;
44
45
  }
45
- .card--flat {
46
+ .icen-card--flat {
46
47
  box-shadow: none;
47
- background: var(--token-bg-soft);
48
+ background: var(--icen-token-bg-soft);
48
49
  }
49
- .card--glass {
50
- background: var(--token-surface-glass);
50
+ .icen-card--glass {
51
+ background: var(--icen-token-surface-glass);
51
52
  backdrop-filter: blur(12px);
52
53
  -webkit-backdrop-filter: blur(12px);
53
54
  box-shadow: none;
54
55
  }
55
56
 
56
57
  /* ── 修饰 ── */
57
- .card--interactive {
58
+ .icen-card--interactive {
58
59
  cursor: pointer;
59
60
  transition:
60
61
  border-color var(--icen-tx-slow),
61
62
  box-shadow var(--icen-tx-slow),
62
63
  transform var(--icen-tx-slow);
63
64
  }
64
- .card--interactive:hover {
65
- transform: translateY(-1px);
66
- border-color: color-mix(in srgb, var(--token-accent) 26%, var(--token-outline-soft));
67
- box-shadow: var(--token-shadow-card);
65
+ /* hover 抬升仅可悬停设备生效(触屏关闭,AGENTS 动效守卫);focus-within 全设备保留 */
66
+ @media (hover: hover) and (pointer: fine) {
67
+ .icen-card--interactive:hover {
68
+ transform: translateY(-1px);
69
+ border-color: color-mix(in srgb, var(--icen-token-accent) 26%, var(--icen-token-outline-soft));
70
+ box-shadow: var(--icen-token-shadow-card);
71
+ }
68
72
  }
69
- .card--interactive:focus-within {
70
- border-color: var(--token-accent);
73
+ .icen-card--interactive:focus-within {
74
+ border-color: var(--icen-token-accent);
71
75
  }
72
- .card.is-selected {
76
+ .icen-card--interactive:focus-within {
77
+ border-color: var(--icen-token-accent);
78
+ }
79
+ .icen-card.is-selected {
73
80
  box-shadow: var(--icen-ring);
74
81
  }
75
82
 
76
83
  /* ── 媒体封面 ── */
77
- .card-media {
84
+ .icen-card-media {
78
85
  position: relative;
79
86
  width: 100%;
80
87
  aspect-ratio: 16 / 9;
81
88
  overflow: hidden;
82
- background: var(--token-bg-soft);
89
+ background: var(--icen-token-bg-soft);
83
90
  }
84
91
  /* 封面比例变体 */
85
- .card-media--square { aspect-ratio: 1 / 1; }
86
- .card-media--tall { aspect-ratio: 3 / 4; }
87
- .card-media--wide { aspect-ratio: 21 / 9; }
88
- .card-media--auto { aspect-ratio: auto; }
89
- /* 封面 hover 放大(配合 .card--interactive) */
90
- .card--interactive:hover .card-media > img,
91
- .card--interactive:hover .card-media > video {
92
- transform: scale(1.04);
93
- }
94
- .card-media > img,
95
- .card-media > video {
96
- width: 100%;
92
+ .icen-card-media--square { aspect-ratio: 1 / 1; }
93
+ .icen-card-media--tall { aspect-ratio: 3 / 4; }
94
+ .icen-card-media--wide { aspect-ratio: 21 / 9; }
95
+ .icen-card-media--auto { aspect-ratio: auto; }
96
+ /* 封面 hover 放大(配合 .icen-card--interactive,仅可悬停设备) */
97
+ @media (hover: hover) and (pointer: fine) {
98
+ .icen-card--interactive:hover .icen-card-media > img,
99
+ .icen-card--interactive:hover .icen-card-media > video {
100
+ transform: scale(1.04);
101
+ }
102
+ }
103
+ .icen-card-media > img,
104
+ .icen-card-media > video {
105
+ inline-size: 100%;
97
106
  height: 100%;
98
107
  object-fit: cover;
99
- transition: transform var(--icen-tx-slow) var(--ease-out);
108
+ transition: transform var(--icen-tx-slow) var(--icen-ease-out);
100
109
  }
101
- .card-tag {
110
+ .icen-card-tag {
102
111
  position: absolute;
103
- top: var(--density-space-xs);
104
- left: var(--density-space-xs);
105
- padding: 2px var(--density-space-xs);
106
- font-size: var(--density-font-size-xs);
112
+ top: var(--icen-density-space-xs);
113
+ inset-inline-start: var(--icen-density-space-xs);
114
+ padding: 2px var(--icen-density-space-xs);
115
+ font-size: var(--icen-density-font-size-xs);
107
116
  font-weight: 600;
108
- color: var(--token-on-accent);
109
- background: color-mix(in srgb, var(--token-text) 70%, transparent);
110
- border-radius: var(--radius-xs);
117
+ color: var(--icen-token-on-accent);
118
+ background: color-mix(in srgb, var(--icen-token-text) 70%, transparent);
119
+ border-radius: var(--icen-radius-xs);
111
120
  backdrop-filter: blur(8px);
112
121
  -webkit-backdrop-filter: blur(8px);
113
122
  }
114
123
 
115
124
  /* ── 子结构 ── */
116
- .card-head {
125
+ .icen-card-head {
117
126
  display: flex;
118
127
  align-items: flex-start;
119
128
  justify-content: space-between;
120
- gap: var(--density-space-sm);
121
- padding: var(--density-space-md);
129
+ gap: var(--icen-density-space-sm);
130
+ padding: var(--icen-density-space-md);
122
131
  }
123
- .card-title {
124
- font-size: var(--density-font-size-lg);
132
+ .icen-card-title {
133
+ font-size: var(--icen-density-font-size-lg);
125
134
  font-weight: 600;
126
- color: var(--token-text);
135
+ color: var(--icen-token-text);
127
136
  line-height: 1.3;
128
137
  margin: 0;
129
- font-family: var(--font-heading);
138
+ font-family: var(--icen-font-heading);
130
139
  }
131
- .card-desc {
132
- font-size: var(--density-font-size-sm);
133
- color: var(--token-text-muted);
140
+ .icen-card-desc {
141
+ font-size: var(--icen-density-font-size-sm);
142
+ color: var(--icen-token-text-muted);
134
143
  margin: 2px 0 0;
135
144
  line-height: 1.4;
136
145
  }
137
- .card-body {
138
- padding: 0 var(--density-space-md) var(--density-space-md);
139
- font-size: var(--density-font-size-md);
140
- color: var(--token-text-muted);
146
+ .icen-card-body {
147
+ padding: 0 var(--icen-density-space-md) var(--icen-density-space-md);
148
+ font-size: var(--icen-density-font-size-md);
149
+ color: var(--icen-token-text-muted);
141
150
  line-height: 1.6;
142
151
  }
143
- .card-body > p:first-child { margin-top: 0; }
144
- .card-body > p:last-child { margin-bottom: 0; }
152
+ .icen-card-body > p:first-child { margin-top: 0; }
153
+ .icen-card-body > p:last-child { margin-bottom: 0; }
145
154
 
146
- .card-foot {
155
+ .icen-card-foot {
147
156
  display: flex;
148
157
  align-items: center;
149
- gap: var(--density-space-sm);
150
- padding: var(--density-space-sm) var(--density-space-md);
151
- border-top: 1px solid var(--token-outline-soft);
152
- background: color-mix(in srgb, var(--token-bg-soft) 50%, transparent);
158
+ gap: var(--icen-density-space-sm);
159
+ padding: var(--icen-density-space-sm) var(--icen-density-space-md);
160
+ border-top: 1px solid var(--icen-token-outline-soft);
161
+ background: color-mix(in srgb, var(--icen-token-bg-soft) 50%, transparent);
153
162
  }
154
- .card-meta {
163
+ .icen-card-meta {
155
164
  display: flex;
156
165
  align-items: center;
157
- gap: var(--density-space-xs);
158
- font-size: var(--density-font-size-xs);
159
- color: var(--token-text-faint);
166
+ gap: var(--icen-density-space-xs);
167
+ font-size: var(--icen-density-font-size-xs);
168
+ color: var(--icen-token-text-faint);
160
169
  }
161
- .card-action {
162
- margin-left: auto;
170
+ .icen-card-action {
171
+ margin-inline-start: auto;
163
172
  flex-shrink: 0;
164
173
  }
165
174
 
166
175
  @media (prefers-reduced-motion: reduce) {
167
- .card--interactive { transition: none; }
176
+ .icen-card--interactive { transition: none; }
168
177
  }
169
178
 
170
179
  /* ── 卡片网格(card-group):自适应多列 ── */
171
- .card-group {
180
+ .icen-card-group {
172
181
  display: grid;
173
- gap: var(--density-space-md);
182
+ gap: var(--icen-density-space-md);
174
183
  grid-template-columns: repeat(auto-fill, minmax(240px, 1fr));
175
184
  }
176
- .card-group--2 { grid-template-columns: repeat(2, 1fr); }
177
- .card-group--3 { grid-template-columns: repeat(3, 1fr); }
178
- .card-group--4 { grid-template-columns: repeat(4, 1fr); }
185
+ .icen-card-group--2 { grid-template-columns: repeat(2, 1fr); }
186
+ .icen-card-group--3 { grid-template-columns: repeat(3, 1fr); }
187
+ .icen-card-group--4 { grid-template-columns: repeat(4, 1fr); }
179
188
 
180
189
  /* ── 卡片列表(横向铺开,常用于搜索结果/消息流) ── */
181
- .card-list {
190
+ .icen-card-list {
182
191
  display: flex;
183
192
  flex-direction: column;
184
- gap: var(--density-space-sm);
193
+ gap: var(--icen-density-space-sm);
185
194
  }
186
- .card-list > .card {
195
+ .icen-card-list > .icen-card {
187
196
  display: flex;
188
197
  flex-direction: row;
189
198
  align-items: stretch;
190
199
  }
191
- .card-list > .card .card-media {
192
- width: 120px;
200
+ .icen-card-list > .icen-card .icen-card-media {
201
+ inline-size: 120px;
193
202
  flex-shrink: 0;
194
203
  aspect-ratio: auto;
195
204
  }
196
- .card-list > .card .card-head,
197
- .card-list > .card .card-body,
198
- .card-list > .card .card-foot {
205
+ .icen-card-list > .icen-card .icen-card-head,
206
+ .icen-card-list > .icen-card .icen-card-body,
207
+ .icen-card-list > .icen-card .icen-card-foot {
199
208
  flex: 1;
200
209
  }
201
210
 
202
211
  /* ── 卡片头副标题 ── */
203
- .card-subtitle {
204
- font-size: var(--density-font-size-xs);
205
- color: var(--token-text-faint);
212
+ .icen-card-subtitle {
213
+ font-size: var(--icen-density-font-size-xs);
214
+ color: var(--icen-token-text-faint);
206
215
  margin: 1px 0 0;
207
216
  line-height: 1.4;
208
217
  }
209
218
 
210
219
  /* ── 卡片状态色边 ── */
211
- .card--success { border-color: color-mix(in srgb, var(--token-success) 35%, transparent); }
212
- .card--warning { border-color: color-mix(in srgb, var(--token-warning) 35%, transparent); }
213
- .card--error { border-color: color-mix(in srgb, var(--token-error) 35%, transparent); }
220
+ .icen-card--success { border-color: color-mix(in srgb, var(--icen-token-success) 35%, transparent); }
221
+ .icen-card--warning { border-color: color-mix(in srgb, var(--icen-token-warning) 35%, transparent); }
222
+ .icen-card--error { border-color: color-mix(in srgb, var(--icen-token-error) 35%, transparent); }
214
223
 
215
- /* ── 卡片右上角徽标位 ── */
216
- .card-badge {
224
+ /* ── 卡片右上角徽标位(物理角契约:与 .icen-badge 角标一致,RTL 不镜像) ── */
225
+ .icen-card-badge {
217
226
  position: absolute;
218
- top: var(--density-space-sm);
219
- right: var(--density-space-sm);
227
+ top: var(--icen-density-space-sm);
228
+ right: var(--icen-density-space-sm); /* guard:allow-physical 徽标位钉在卡片物理右上角(同 .icen-badge 角标契约) */
220
229
  z-index: 1;
221
230
  }
231
+
232
+ }