@icen.ai/ui 0.5.0 → 0.8.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 (151) hide show
  1. package/AGENTS.md +262 -0
  2. package/README.md +52 -13
  3. package/dist/base.css +33 -5
  4. package/dist/behaviors/accordion.d.mts +7 -0
  5. package/dist/behaviors/accordion.mjs +37 -11
  6. package/dist/behaviors/ai-chat.d.mts +59 -0
  7. package/dist/behaviors/ai-chat.mjs +580 -0
  8. package/dist/behaviors/ai-composer.d.mts +137 -0
  9. package/dist/behaviors/ai-composer.mjs +2114 -0
  10. package/dist/behaviors/ai-core.d.mts +156 -0
  11. package/dist/behaviors/ai-core.mjs +504 -0
  12. package/dist/behaviors/ai-diff.d.mts +53 -0
  13. package/dist/behaviors/ai-diff.mjs +413 -0
  14. package/dist/behaviors/ai-panel.d.mts +101 -0
  15. package/dist/behaviors/ai-panel.mjs +1087 -0
  16. package/dist/behaviors/ai-provider.d.mts +198 -0
  17. package/dist/behaviors/ai-provider.mjs +1061 -0
  18. package/dist/behaviors/ai-tool.d.mts +26 -0
  19. package/dist/behaviors/ai-tool.mjs +2173 -0
  20. package/dist/behaviors/ai-tools.d.mts +84 -0
  21. package/dist/behaviors/ai-tools.mjs +1762 -0
  22. package/dist/behaviors/back-top.d.mts +20 -0
  23. package/dist/behaviors/back-top.mjs +64 -32
  24. package/dist/behaviors/carousel.d.mts +7 -0
  25. package/dist/behaviors/carousel.mjs +72 -27
  26. package/dist/behaviors/charts.d.mts +296 -0
  27. package/dist/behaviors/charts.mjs +1364 -440
  28. package/dist/behaviors/command-palette.d.mts +42 -0
  29. package/dist/behaviors/command-palette.mjs +167 -27
  30. package/dist/behaviors/context-menu.d.mts +53 -0
  31. package/dist/behaviors/context-menu.mjs +127 -39
  32. package/dist/behaviors/controls.d.mts +59 -0
  33. package/dist/behaviors/controls.mjs +601 -0
  34. package/dist/behaviors/copy.d.mts +7 -0
  35. package/dist/behaviors/copy.mjs +41 -15
  36. package/dist/behaviors/datatable.d.mts +90 -0
  37. package/dist/behaviors/datatable.mjs +279 -53
  38. package/dist/behaviors/date-picker.d.mts +4 -0
  39. package/dist/behaviors/date-picker.mjs +276 -69
  40. package/dist/behaviors/dropdown.d.mts +8 -0
  41. package/dist/behaviors/dropdown.mjs +171 -28
  42. package/dist/behaviors/events.d.mts +330 -0
  43. package/dist/behaviors/events.mjs +208 -0
  44. package/dist/behaviors/input.d.mts +4 -0
  45. package/dist/behaviors/input.mjs +52 -32
  46. package/dist/behaviors/modal.d.mts +30 -0
  47. package/dist/behaviors/modal.mjs +87 -16
  48. package/dist/behaviors/nav.d.mts +7 -0
  49. package/dist/behaviors/nav.mjs +57 -15
  50. package/dist/behaviors/notification.d.mts +188 -0
  51. package/dist/behaviors/notification.mjs +274 -140
  52. package/dist/behaviors/popover.d.mts +82 -0
  53. package/dist/behaviors/popover.mjs +92 -5
  54. package/dist/behaviors/select.d.mts +6 -0
  55. package/dist/behaviors/select.mjs +287 -45
  56. package/dist/behaviors/sidebar.d.mts +7 -0
  57. package/dist/behaviors/sidebar.mjs +44 -13
  58. package/dist/behaviors/slider.d.mts +7 -0
  59. package/dist/behaviors/slider.mjs +55 -43
  60. package/dist/behaviors/split-pane.d.mts +8 -0
  61. package/dist/behaviors/split-pane.mjs +70 -29
  62. package/dist/behaviors/tabs.d.mts +9 -0
  63. package/dist/behaviors/tabs.mjs +102 -26
  64. package/dist/behaviors/tag-input.d.mts +7 -0
  65. package/dist/behaviors/tag-input.mjs +66 -17
  66. package/dist/behaviors/theme.d.mts +36 -0
  67. package/dist/behaviors/theme.mjs +51 -5
  68. package/dist/behaviors/toast.d.mts +48 -0
  69. package/dist/behaviors/toast.mjs +98 -25
  70. package/dist/behaviors/tree.d.mts +7 -0
  71. package/dist/behaviors/tree.mjs +39 -15
  72. package/dist/behaviors/upload.d.mts +4 -0
  73. package/dist/behaviors/upload.mjs +79 -44
  74. package/dist/cli.mjs +1 -1
  75. package/dist/components/ai-chat.css +1037 -0
  76. package/dist/components/ai-chat.mjs +3 -0
  77. package/dist/components/ai-composer.mjs +3 -0
  78. package/dist/components/ai-context.mjs +2 -0
  79. package/dist/components/ai-diff.css +311 -0
  80. package/dist/components/ai-diff.mjs +3 -0
  81. package/dist/components/ai-files.mjs +3 -0
  82. package/dist/components/ai-message.mjs +3 -0
  83. package/dist/components/ai-panel.css +682 -0
  84. package/dist/components/ai-reasoning.mjs +3 -0
  85. package/dist/components/ai-subagent.mjs +2 -0
  86. package/dist/components/ai-todo.mjs +2 -0
  87. package/dist/components/ai-tool-call.mjs +2 -0
  88. package/dist/components/ai-tool.css +532 -0
  89. package/dist/components/ai-usage.mjs +3 -0
  90. package/dist/components/badge.css +5 -9
  91. package/dist/components/breadcrumb.css +0 -36
  92. package/dist/components/btn.css +4 -7
  93. package/dist/components/card.css +3 -6
  94. package/dist/components/chart-bar.css +10 -0
  95. package/dist/components/chart-calendar.mjs +4 -0
  96. package/dist/components/chart-gauge.css +1 -1
  97. package/dist/components/chart-heatmap.css +40 -0
  98. package/dist/components/chart-pie.css +0 -6
  99. package/dist/components/chart-scatter.css +24 -0
  100. package/dist/components/chart-scatter.mjs +4 -0
  101. package/dist/components/charts.css +87 -2
  102. package/dist/components/charts.mjs +1 -0
  103. package/dist/components/command-palette.css +2 -2
  104. package/dist/components/content.css +11 -25
  105. package/dist/components/copy.css +8 -8
  106. package/dist/components/datatable.css +5 -9
  107. package/dist/components/date-picker.css +4 -8
  108. package/dist/components/empty.css +0 -4
  109. package/dist/components/feedback.css +10 -17
  110. package/dist/components/form.css +13 -14
  111. package/dist/components/input.css +2 -2
  112. package/dist/components/layout.css +36 -36
  113. package/dist/components/media.css +12 -8
  114. package/dist/components/menu.css +2 -2
  115. package/dist/components/modal.css +1 -1
  116. package/dist/components/nav.css +11 -6
  117. package/dist/components/notification.css +27 -28
  118. package/dist/components/pagination.css +4 -2
  119. package/dist/components/pagination.mjs +1 -0
  120. package/dist/components/panel.css +16 -16
  121. package/dist/components/pill.css +15 -15
  122. package/dist/components/rating.mjs +1 -0
  123. package/dist/components/segmented.css +14 -6
  124. package/dist/components/segmented.mjs +1 -0
  125. package/dist/components/select.css +79 -24
  126. package/dist/components/sidebar.css +1 -1
  127. package/dist/components/split-pane.css +0 -1
  128. package/dist/components/stat.css +14 -18
  129. package/dist/components/steps.css +15 -5
  130. package/dist/components/steps.mjs +1 -0
  131. package/dist/components/switch.css +11 -13
  132. package/dist/components/switch.mjs +1 -0
  133. package/dist/components/table.css +46 -47
  134. package/dist/components/table.mjs +1 -0
  135. package/dist/components/tabs.css +57 -45
  136. package/dist/components/tag-input.css +5 -10
  137. package/dist/components/toast.css +16 -13
  138. package/dist/components/tooltip.css +2 -2
  139. package/dist/components/upload.css +0 -15
  140. package/dist/index.d.mts +39 -0
  141. package/dist/index.mjs +11243 -3312
  142. package/dist/registry.json +147 -9
  143. package/dist/retro-effects.css +23 -32
  144. package/dist/tokens/colors.css +4 -1
  145. package/dist/tokens/retro-effects.css +23 -32
  146. package/dist/tokens/style-profiles.css +24 -2
  147. package/dist/tokens/typography.css +2 -0
  148. package/dist/tokens.css +30 -3
  149. package/dist/ui.css +3420 -645
  150. package/docs/spec/ai-native.md +662 -0
  151. package/package.json +15 -5
@@ -1,23 +1,23 @@
1
1
  /*
2
2
  * @icen.ai/ui — Component: layout(布局原语,全部是工具类,无 JS)
3
3
  * stack / divider / surface / text / grid / center / container / aspect / visually-hidden
4
- * 全部消费 --token-*;档位类名与 opengal primitives/layout(-containers) 一一对应。
4
+ * 全部消费 --token-* 与 --density-*;档位类名与 opengal primitives/layout(-containers) 一一对应。
5
5
  */
6
6
 
7
- /* ── Stack:flex 堆叠(默认列向,gap 8px) ── */
8
- .stack { display: flex; flex-direction: column; gap: 8px; }
7
+ /* ── Stack:flex 堆叠(默认列向,gap = density-space-sm) ── */
8
+ .stack { display: flex; flex-direction: column; gap: var(--density-space-sm); }
9
9
  .stack--row { flex-direction: row; }
10
10
  .stack--inline { display: inline-flex; }
11
11
  .stack--wrap { flex-wrap: wrap; }
12
12
  .stack--gap-0 { gap: 0; }
13
- .stack--gap-1 { gap: 4px; }
14
- .stack--gap-2 { gap: 8px; }
15
- .stack--gap-3 { gap: 12px; }
16
- .stack--gap-4 { gap: 16px; }
17
- .stack--gap-6 { gap: 24px; }
18
- .stack--gap-8 { gap: 32px; }
19
- .stack--gap-12 { gap: 48px; }
20
- .stack--gap-16 { gap: 64px; }
13
+ .stack--gap-1 { gap: var(--density-space-xs); }
14
+ .stack--gap-2 { gap: var(--density-space-sm); }
15
+ .stack--gap-3 { gap: var(--density-space-md); }
16
+ .stack--gap-4 { gap: var(--density-space-lg); }
17
+ .stack--gap-6 { gap: var(--density-space-xl); }
18
+ .stack--gap-8 { gap: var(--density-space-2xl); }
19
+ .stack--gap-12 { gap: var(--density-space-3xl); }
20
+ .stack--gap-16 { gap: var(--density-space-4xl); }
21
21
  .stack--items-start { align-items: flex-start; }
22
22
  .stack--items-center { align-items: center; }
23
23
  .stack--items-end { align-items: flex-end; }
@@ -34,13 +34,13 @@
34
34
  .divider { background: var(--token-outline-soft); height: 1px; width: 100%; }
35
35
  .divider--vertical { width: 1px; height: 100%; align-self: stretch; }
36
36
 
37
- /* ── Surface:卡片容器(默认 inset 阴影 + 16px padding) ── */
37
+ /* ── Surface:卡片容器(默认 inset 阴影 + density-space-lg padding) ── */
38
38
  .surface {
39
39
  border-radius: var(--radius-lg);
40
40
  background: var(--token-card);
41
41
  border: 1px solid var(--token-outline-soft);
42
42
  box-shadow: var(--token-shadow-inset);
43
- padding: 16px;
43
+ padding: var(--density-space-lg);
44
44
  }
45
45
  .surface--elevated { box-shadow: var(--token-shadow-card); }
46
46
  .surface--overlay {
@@ -49,18 +49,18 @@
49
49
  box-shadow: var(--token-shadow-overlay);
50
50
  }
51
51
  .surface--p-none { padding: 0; }
52
- .surface--p-sm { padding: 12px; }
53
- .surface--p-md { padding: 16px; }
54
- .surface--p-lg { padding: 20px; }
52
+ .surface--p-sm { padding: var(--density-space-md); }
53
+ .surface--p-md { padding: var(--density-space-lg); }
54
+ .surface--p-lg { padding: calc(var(--density-space-lg) + var(--density-space-xs)); }
55
55
 
56
56
  /* ── Text:字号 / 语义色 / 截断 ── */
57
- .text--xs { font-size: 11px; }
58
- .text--sm { font-size: 12px; }
59
- .text--base { font-size: 13px; }
60
- .text--md { font-size: 14px; }
61
- .text--lg { font-size: 15px; }
62
- .text--xl { font-size: 18px; }
63
- .text--2xl { font-size: 22px; }
57
+ .text--xs { font-size: var(--density-font-size-xs); }
58
+ .text--sm { font-size: var(--density-font-size-sm); }
59
+ .text--base { font-size: var(--density-font-size-md); }
60
+ .text--md { font-size: var(--density-font-size-lg); }
61
+ .text--lg { font-size: var(--density-font-size-lg); }
62
+ .text--xl { font-size: var(--density-font-size-xl); }
63
+ .text--2xl { font-size: var(--density-font-size-2xl); }
64
64
  .text--muted { color: var(--token-text-muted); }
65
65
  .text--faint { color: var(--token-text-faint); }
66
66
  .text--accent { color: var(--token-accent); }
@@ -69,8 +69,8 @@
69
69
  .text--error { color: var(--token-error); }
70
70
  .text--truncate { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
71
71
 
72
- /* ── Grid:栅格(默认 gap 12px) ── */
73
- .grid { display: grid; gap: 12px; }
72
+ /* ── Grid:栅格(默认 gap = density-space-md) ── */
73
+ .grid { display: grid; gap: var(--density-space-md); }
74
74
  .grid--cols-1 { grid-template-columns: repeat(1, minmax(0, 1fr)); }
75
75
  .grid--cols-2 { grid-template-columns: repeat(2, minmax(0, 1fr)); }
76
76
  .grid--cols-3 { grid-template-columns: repeat(3, minmax(0, 1fr)); }
@@ -78,28 +78,28 @@
78
78
  .grid--cols-6 { grid-template-columns: repeat(6, minmax(0, 1fr)); }
79
79
  .grid--cols-12 { grid-template-columns: repeat(12, minmax(0, 1fr)); }
80
80
  .grid--gap-0 { gap: 0; }
81
- .grid--gap-4 { gap: 4px; }
82
- .grid--gap-8 { gap: 8px; }
83
- .grid--gap-12 { gap: 12px; }
84
- .grid--gap-16 { gap: 16px; }
85
- .grid--gap-24 { gap: 24px; }
81
+ .grid--gap-4 { gap: var(--density-space-xs); }
82
+ .grid--gap-8 { gap: var(--density-space-sm); }
83
+ .grid--gap-12 { gap: var(--density-space-md); }
84
+ .grid--gap-16 { gap: var(--density-space-lg); }
85
+ .grid--gap-24 { gap: var(--density-space-xl); }
86
86
 
87
87
  /* ── Center:flex 居中盒 ── */
88
88
  .center { display: flex; align-items: center; justify-content: center; }
89
89
 
90
90
  /* ── Container:限宽容器(默认 960px) ── */
91
- .container { width: 100%; margin-inline: auto; padding-inline: 16px; max-width: 960px; }
91
+ .container { width: 100%; margin-inline: auto; padding-inline: var(--density-space-lg); max-width: 960px; }
92
92
  .container--sm { max-width: 480px; }
93
93
  .container--md { max-width: 720px; }
94
94
  .container--lg { max-width: 960px; }
95
95
  .container--xl { max-width: 1200px; }
96
96
  .container--full { max-width: none; }
97
97
 
98
- /* ── Aspect:固定比例盒(padding-bottom hack,内容 absolute inset:0) ── */
99
- .aspect { position: relative; width: 100%; overflow: hidden; padding-bottom: 56.25%; }
100
- .aspect--square { padding-bottom: 100%; }
101
- .aspect--4-3 { padding-bottom: 75%; }
102
- .aspect--2-3 { padding-bottom: 150%; }
98
+ /* ── Aspect:固定比例盒(aspect-ratio,内容 absolute inset:0 铺满) ── */
99
+ .aspect { position: relative; width: 100%; overflow: hidden; aspect-ratio: 16 / 9; }
100
+ .aspect--square { aspect-ratio: 1 / 1; }
101
+ .aspect--4-3 { aspect-ratio: 4 / 3; }
102
+ .aspect--2-3 { aspect-ratio: 2 / 3; }
103
103
  .aspect > * { position: absolute; inset: 0; }
104
104
 
105
105
  /* ── VisuallyHidden:屏幕阅读器专用文本(sr-only 等价) ── */
@@ -4,6 +4,10 @@
4
4
  * 包含:avatar(头像)/ media-card(封面卡,滑出 overlay)/ rating(星级评分)/ carousel(轮播,与 behaviors/carousel 配套)
5
5
  * 规格源自 opengal data/display.tsx 的 Avatar、data/cartridge-card.tsx 的 hover overlay、
6
6
  * data/exhibit.tsx 的 Carousel 与 Rating。
7
+ *
8
+ * 例外声明(deliberate exception):carousel-thumbs 隐藏滚动条是有意设计
9
+ * (缩略图条视觉纯净,滚动仍可用)。违反「组件不写滚动条样式」纪律仅此处,
10
+ * 先例参照 scroll-area.css 的尺寸变体。
7
11
  */
8
12
 
9
13
  /* ══════════════ avatar · 头像 ══════════════ */
@@ -23,8 +27,8 @@
23
27
  flex-shrink: 0;
24
28
  user-select: none;
25
29
  }
26
- .avatar--xs { width: 20px; height: 20px; font-size: 9px; }
27
- .avatar--sm { width: 28px; height: 28px; font-size: 10px; }
30
+ .avatar--xs { width: 20px; height: 20px; font-size: var(--density-font-size-2xs); }
31
+ .avatar--sm { width: 28px; height: 28px; font-size: var(--density-font-size-2xs); }
28
32
  .avatar--lg { width: 48px; height: 48px; font-size: var(--density-font-size-md); }
29
33
  .avatar--xl { width: 80px; height: 80px; font-size: var(--density-font-size-lg); }
30
34
  .avatar img {
@@ -68,7 +72,7 @@
68
72
  /* 渐变底头像 */
69
73
  .avatar--gradient {
70
74
  background: linear-gradient(135deg, var(--token-accent), var(--token-accent-deep, var(--token-accent)));
71
- color: var(--token-on-accent, #fff);
75
+ color: var(--token-on-accent);
72
76
  }
73
77
 
74
78
  /* 方形头像 */
@@ -86,7 +90,7 @@
86
90
  justify-content: center;
87
91
  width: 28px;
88
92
  height: 28px;
89
- font-size: 10px;
93
+ font-size: var(--density-font-size-2xs);
90
94
  font-weight: 600;
91
95
  color: var(--token-text-muted);
92
96
  background: var(--token-fill-2);
@@ -108,7 +112,7 @@
108
112
  .media-card:hover {
109
113
  transform: translateY(-6px);
110
114
  box-shadow:
111
- 0 8px 32px color-mix(in srgb, var(--token-text) 18%, transparent),
115
+ var(--token-shadow-overlay),
112
116
  0 0 20px var(--token-accent-glow);
113
117
  }
114
118
  .media-card-cover {
@@ -136,7 +140,7 @@
136
140
  }
137
141
  .media-card:hover .media-card-overlay {
138
142
  transform: translateY(0);
139
- transition-delay: 80ms;
143
+ transition-delay: var(--media-overlay-delay, 80ms);
140
144
  }
141
145
  .media-card-overlay-title {
142
146
  font-size: var(--density-font-size-md);
@@ -341,7 +345,7 @@
341
345
  outline: none;
342
346
  box-shadow: var(--icen-ring);
343
347
  }
344
- .carousel-dot.active,
348
+ .carousel-dot.is-active,
345
349
  .carousel-dot[aria-current='true'] {
346
350
  width: 20px;
347
351
  background: var(--token-accent);
@@ -357,7 +361,7 @@
357
361
  transition: width var(--icen-tx-slow);
358
362
  }
359
363
 
360
- /* 缩略图导航条 */
364
+ /* 缩略图导航条(deliberate exception:隐藏滚动条是设计意图,见文件头注释) */
361
365
  .carousel-thumbs {
362
366
  display: flex;
363
367
  gap: var(--density-space-xs);
@@ -41,7 +41,7 @@
41
41
  border: 1px solid var(--token-outline);
42
42
  box-shadow: var(--token-shadow-overlay);
43
43
  border-radius: var(--radius-lg);
44
- animation: icen-menu-in var(--icen-tx-fast);
44
+ animation: icen-menu-in var(--menu-in-duration, var(--icen-tx-fast));
45
45
  }
46
46
  .menu[data-side='top'] { animation-name: icen-menu-in-top; }
47
47
  .menu[data-side='left'] { animation-name: icen-menu-in-left; }
@@ -52,7 +52,7 @@
52
52
  min-width: 218px;
53
53
  max-width: 286px;
54
54
  z-index: var(--z-tooltip); /* 上下文菜单高于普通 popover,与 tooltip 平齐 */
55
- animation-duration: 100ms;
55
+ --menu-in-duration: 100ms;
56
56
  }
57
57
 
58
58
  /* ── 分组标签 / 头(context-menu 的 header 项) ── */
@@ -102,7 +102,7 @@
102
102
  border: 0;
103
103
  cursor: pointer;
104
104
  color: var(--token-text-faint);
105
- font-size: 16px;
105
+ font-size: var(--density-font-size-lg);
106
106
  line-height: 1;
107
107
  border-radius: var(--radius-sm);
108
108
  transition:
@@ -25,7 +25,12 @@
25
25
  backdrop-filter: blur(12px) saturate(1.1);
26
26
  -webkit-backdrop-filter: blur(12px) saturate(1.1);
27
27
  border-bottom: 1px solid var(--token-outline-soft);
28
- transition: all var(--icen-tx-slow);
28
+ transition:
29
+ background-color var(--icen-tx-slow),
30
+ border-color var(--icen-tx-slow),
31
+ box-shadow var(--icen-tx-slow),
32
+ transform var(--icen-tx-slow),
33
+ backdrop-filter var(--icen-tx-slow);
29
34
  }
30
35
  .nav:has(.nav-bottom) {
31
36
  height: auto;
@@ -82,6 +87,7 @@
82
87
  .nav-bottom { width: 100%; padding-top: var(--density-space-xs); }
83
88
 
84
89
  .nav-btn {
90
+ position: relative;
85
91
  display: inline-flex;
86
92
  align-items: center;
87
93
  gap: var(--density-space-xs);
@@ -113,7 +119,7 @@
113
119
  .nav-btn.is-active,
114
120
  .nav-btn[aria-current='page'] {
115
121
  background: var(--token-accent);
116
- color: var(--token-on-accent, #fff);
122
+ color: var(--token-on-accent);
117
123
  font-weight: 500;
118
124
  box-shadow: var(--token-shadow-elevated);
119
125
  }
@@ -183,7 +189,7 @@
183
189
  .nav-search-kbd {
184
190
  margin-left: auto;
185
191
  padding: 1px 5px;
186
- font-size: 10px;
192
+ font-size: var(--density-font-size-2xs);
187
193
  font-family: var(--font-mono);
188
194
  color: var(--token-text-faint);
189
195
  background: var(--token-fill-2);
@@ -203,14 +209,13 @@
203
209
  border-radius: var(--radius-full);
204
210
  pointer-events: none;
205
211
  }
206
- .nav-btn { position: relative; }
207
212
  .nav-btn-badge--count {
208
213
  min-width: 16px;
209
214
  height: 16px;
210
215
  padding: 0 4px;
211
- font-size: 9px;
216
+ font-size: var(--density-font-size-2xs);
212
217
  font-weight: 700;
213
- color: var(--token-on-accent, #fff);
218
+ color: var(--token-on-accent);
214
219
  display: inline-flex;
215
220
  align-items: center;
216
221
  justify-content: center;
@@ -9,7 +9,7 @@
9
9
  *
10
10
  * 完整契约(由 behavior 渲染):
11
11
  * <div class="notification-container" role="region" aria-label="通知" data-position="top-right">
12
- * <div class="notification [notif--success|warning|error|info]
12
+ * <div class="notification [notification--success|warning|error]
13
13
  * [.is-priority] [.is-unread] [.is-progress] [.is-clickable] [.is-paused]
14
14
  * [.has-avatar]" role="alert|button">
15
15
  * <span class="notification-icon">…svg 或 img.notification-avatar…</span>
@@ -78,19 +78,19 @@
78
78
  overflow: hidden; /* 倒计时进度条贴底 */
79
79
  animation: icen-notif-in var(--icen-tx-normal);
80
80
  }
81
- .notification.notif--success { border-left-color: var(--token-success); }
82
- .notification.notif--warning { border-left-color: var(--token-warning); }
83
- .notification.notif--error { border-left-color: var(--token-error); }
84
- .notification.notif--info { border-left-color: var(--token-info); }
81
+ .notification.notification--success { border-left-color: var(--token-success); }
82
+ .notification.notification--warning { border-left-color: var(--token-warning); }
83
+ .notification.notification--error { border-left-color: var(--token-error); }
84
+ /* info 为基类默认配色(基类左侧边即 --token-info),无修饰类 */
85
85
 
86
86
  /* ── 优先级:高优先级强调(左侧加粗 + 更强阴影)── */
87
87
  .notification.is-priority {
88
88
  border-left-width: 4px;
89
89
  box-shadow: var(--token-shadow-overlay), 0 0 0 1px color-mix(in srgb, var(--token-accent) 24%, transparent);
90
90
  }
91
- .notification.is-priority.notif--success { box-shadow: var(--token-shadow-overlay), 0 0 0 1px color-mix(in srgb, var(--token-success) 28%, transparent); }
92
- .notification.is-priority.notif--warning { box-shadow: var(--token-shadow-overlay), 0 0 0 1px color-mix(in srgb, var(--token-warning) 28%, transparent); }
93
- .notification.is-priority.notif--error { box-shadow: var(--token-shadow-overlay), 0 0 0 1px color-mix(in srgb, var(--token-error) 28%, transparent); }
91
+ .notification.is-priority.notification--success { box-shadow: var(--token-shadow-overlay), 0 0 0 1px color-mix(in srgb, var(--token-success) 28%, transparent); }
92
+ .notification.is-priority.notification--warning { box-shadow: var(--token-shadow-overlay), 0 0 0 1px color-mix(in srgb, var(--token-warning) 28%, transparent); }
93
+ .notification.is-priority.notification--error { box-shadow: var(--token-shadow-overlay), 0 0 0 1px color-mix(in srgb, var(--token-error) 28%, transparent); }
94
94
 
95
95
  /* ── 未读:标题左侧 4px 强调点 + 加粗 ── */
96
96
  .notification.is-unread .notification-title::before {
@@ -105,9 +105,9 @@
105
105
  background: var(--token-accent);
106
106
  flex-shrink: 0;
107
107
  }
108
- .notification.is-unread.notif--success .notification-title::before { background: var(--token-success); }
109
- .notification.is-unread.notif--warning .notification-title::before { background: var(--token-warning); }
110
- .notification.is-unread.notif--error .notification-title::before { background: var(--token-error); }
108
+ .notification.is-unread.notification--success .notification-title::before { background: var(--token-success); }
109
+ .notification.is-unread.notification--warning .notification-title::before { background: var(--token-warning); }
110
+ .notification.is-unread.notification--error .notification-title::before { background: var(--token-error); }
111
111
 
112
112
  /* ── 可点击:整条 hover 抬升 ── */
113
113
  .notification.is-clickable {
@@ -135,10 +135,9 @@
135
135
  color: var(--token-text-faint);
136
136
  }
137
137
  .notification-icon svg { width: 16px; height: 16px; }
138
- .notif--success .notification-icon { color: var(--token-success); }
139
- .notif--warning .notification-icon { color: var(--token-warning); }
140
- .notif--error .notification-icon { color: var(--token-error); }
141
- .notif--info .notification-icon { color: var(--token-info); }
138
+ .notification--success .notification-icon { color: var(--token-success); }
139
+ .notification--warning .notification-icon { color: var(--token-warning); }
140
+ .notification--error .notification-icon { color: var(--token-error); }
142
141
 
143
142
  /* 头像(圆形图) */
144
143
  .notification-avatar {
@@ -155,7 +154,7 @@
155
154
  }
156
155
 
157
156
  /* 进度通知的图标默认走品牌色 */
158
- .notification.is-progress:not(.notif--success):not(.notif--warning):not(.notif--error) .notification-icon {
157
+ .notification.is-progress:not(.notification--success):not(.notification--warning):not(.notification--error) .notification-icon {
159
158
  color: var(--token-accent);
160
159
  }
161
160
 
@@ -221,23 +220,23 @@
221
220
  /* primary:实底 accent */
222
221
  .notification-action--primary {
223
222
  background: var(--token-accent);
224
- color: var(--token-on-accent, #fff);
223
+ color: var(--token-on-accent);
225
224
  border-color: var(--token-accent);
226
225
  }
227
226
  .notification-action--primary:hover {
228
227
  background: var(--token-accent-deep, var(--token-accent));
229
- color: var(--token-on-accent, #fff);
228
+ color: var(--token-on-accent);
230
229
  border-color: var(--token-accent-deep, var(--token-accent));
231
230
  }
232
231
  /* danger:实底 error */
233
232
  .notification-action--danger {
234
233
  background: var(--token-error);
235
- color: var(--token-on-accent, #fff);
234
+ color: var(--token-on-accent);
236
235
  border-color: var(--token-error);
237
236
  }
238
237
  .notification-action--danger:hover {
239
238
  filter: brightness(0.92);
240
- color: var(--token-on-accent, #fff);
239
+ color: var(--token-on-accent);
241
240
  border-color: var(--token-error);
242
241
  }
243
242
 
@@ -282,9 +281,9 @@
282
281
  border-radius: var(--radius-full);
283
282
  transition: width var(--icen-tx-normal) var(--ease-out);
284
283
  }
285
- .notification.notif--success .notification-progress-bar { background: var(--token-success); }
286
- .notification.notif--warning .notification-progress-bar { background: var(--token-warning); }
287
- .notification.notif--error .notification-progress-bar { background: var(--token-error); }
284
+ .notification.notification--success .notification-progress-bar { background: var(--token-success); }
285
+ .notification.notification--warning .notification-progress-bar { background: var(--token-warning); }
286
+ .notification.notification--error .notification-progress-bar { background: var(--token-error); }
288
287
  .notification-progress-label {
289
288
  flex: 0 0 auto;
290
289
  font-size: var(--density-font-size-xs);
@@ -340,9 +339,9 @@
340
339
  animation-fill-mode: forwards;
341
340
  animation-play-state: running;
342
341
  }
343
- .notification.notif--success .notification-countdown-fill { background: var(--token-success); opacity: 0.6; }
344
- .notification.notif--warning .notification-countdown-fill { background: var(--token-warning); opacity: 0.6; }
345
- .notification.notif--error .notification-countdown-fill { background: var(--token-error); opacity: 0.6; }
342
+ .notification.notification--success .notification-countdown-fill { background: var(--token-success); opacity: 0.6; }
343
+ .notification.notification--warning .notification-countdown-fill { background: var(--token-warning); opacity: 0.6; }
344
+ .notification.notification--error .notification-countdown-fill { background: var(--token-error); opacity: 0.6; }
346
345
  .notification.is-paused .notification-countdown-fill {
347
346
  animation-play-state: paused;
348
347
  }
@@ -357,7 +356,7 @@
357
356
  }
358
357
 
359
358
  /* ── 退场动画 ── */
360
- .notification.leaving {
359
+ .notification.is-leaving {
361
360
  opacity: 0;
362
361
  transform: translateX(20px);
363
362
  transition:
@@ -381,7 +380,7 @@
381
380
 
382
381
  @media (prefers-reduced-motion: reduce) {
383
382
  .notification { animation: none; }
384
- .notification.leaving { transform: none; }
383
+ .notification.is-leaving { transform: none; }
385
384
  .notification-countdown-fill { animation: none; transform-origin: left; }
386
385
  .notification-progress-bar { transition: none; }
387
386
  }
@@ -10,7 +10,9 @@
10
10
  * <button class="page-btn motion" aria-label="下一页">›</button>
11
11
  * </nav>
12
12
  *
13
- * 翻页逻辑由消费方实现,这里只提供静态样式契约。
13
+ * 点击接线由 behaviors/controls.ts 的 initPagination() 提供(.page-btn 激活位移 +
14
+ * icen:page-change,上下页按钮按 aria-label / data-dir 推断方向);总页数与省略号
15
+ * 折叠策略由消费方维护,这里只提供样式契约。
14
16
  */
15
17
 
16
18
  .pagination {
@@ -48,7 +50,7 @@
48
50
  .page-btn.is-active,
49
51
  .page-btn[aria-current='page'] {
50
52
  background: var(--token-accent);
51
- color: var(--token-on-accent, #fff);
53
+ color: var(--token-on-accent);
52
54
  font-weight: 500;
53
55
  box-shadow: var(--token-shadow-elevated);
54
56
  }
@@ -1,2 +1,3 @@
1
1
  // @icen.ai/ui — kit: pagination(CSS + behavior 一行入口;构建产物,勿手改)
2
2
  import './pagination.css';
3
+ export { initPagination } from '../behaviors/controls.mjs';
@@ -2,8 +2,8 @@
2
2
  * @icen.ai/ui — Component: panel(白卡片容器 + 标题栏 + 可选 footer)
3
3
  *
4
4
  * 完整契约:
5
- * <div class="panel-block [panel-block--flush] [panel-block--accent]
6
- * [panel-block--collapsible] [.is-collapsed]">
5
+ * <div class="panel [panel--flush] [panel--accent]
6
+ * [panel--collapsible] [.is-collapsed]">
7
7
  * <div class="panel-title">
8
8
  * <div class="panel-title-text">
9
9
  * <span>标题</span>
@@ -24,10 +24,10 @@
24
24
  * --collapsible:标题栏出现展开/折叠钮(behavior 可选,也可靠纯 CSS details/summary)。
25
25
  * --accent:强调色标题边。
26
26
  * .panel-subtitle:标题下方的副标题/描述文字。
27
- * .panel-block.is-collapsed:折叠态——隐藏 body + foot。
27
+ * .panel.is-collapsed:折叠态——隐藏 body + foot。
28
28
  */
29
29
 
30
- .panel-block {
30
+ .panel {
31
31
  background: var(--token-surface);
32
32
  border: 1px solid var(--token-line-soft);
33
33
  border-radius: var(--radius-lg);
@@ -63,7 +63,7 @@
63
63
  white-space: nowrap;
64
64
  }
65
65
  .panel-subtitle {
66
- font-size: 11px;
66
+ font-size: var(--density-font-size-xs);
67
67
  font-weight: 400;
68
68
  letter-spacing: 0;
69
69
  text-transform: none;
@@ -107,19 +107,19 @@
107
107
  height: 14px;
108
108
  transition: transform var(--icen-tx-fast);
109
109
  }
110
- .panel-block.is-collapsed .panel-toggle-icon {
110
+ .panel.is-collapsed .panel-toggle-icon {
111
111
  transform: rotate(-90deg);
112
112
  }
113
113
 
114
114
  /* ── 折叠态:隐藏 body + foot,去掉标题栏底边 ── */
115
- .panel-block.is-collapsed .panel-body,
116
- .panel-block.is-collapsed .panel-foot {
115
+ .panel.is-collapsed .panel-body,
116
+ .panel.is-collapsed .panel-foot {
117
117
  display: none;
118
118
  }
119
- .panel-block.is-collapsed .panel-title {
119
+ .panel.is-collapsed .panel-title {
120
120
  border-bottom-color: transparent;
121
121
  }
122
- .panel-block--collapsible .panel-body {
122
+ .panel--collapsible .panel-body {
123
123
  animation: panel-expand var(--icen-tx-normal) var(--ease-out);
124
124
  }
125
125
  @keyframes panel-expand {
@@ -133,7 +133,7 @@
133
133
  font-size: var(--density-font-size-md);
134
134
  line-height: 1.6;
135
135
  }
136
- .panel-block--flush .panel-body { padding: 0; }
136
+ .panel--flush .panel-body { padding: 0; }
137
137
 
138
138
  .panel-foot {
139
139
  display: flex;
@@ -146,24 +146,24 @@
146
146
  }
147
147
 
148
148
  /* ── 强调变体 ── */
149
- .panel-block--accent { border-color: color-mix(in srgb, var(--token-accent) 30%, transparent); }
150
- .panel-block--accent .panel-title {
149
+ .panel--accent { border-color: color-mix(in srgb, var(--token-accent) 30%, transparent); }
150
+ .panel--accent .panel-title {
151
151
  color: var(--token-accent);
152
152
  background: var(--token-accent-subtle);
153
153
  }
154
154
 
155
155
  /* ── 平面变体(无阴影,嵌套时用) ── */
156
- .panel-block--flat {
156
+ .panel--flat {
157
157
  box-shadow: none;
158
158
  background: var(--token-bg-soft);
159
159
  }
160
160
 
161
161
  /* ── 可折叠模式:标题栏可点(纯 CSS 方案用 details/summary) ── */
162
- .panel-block--collapsible .panel-title {
162
+ .panel--collapsible .panel-title {
163
163
  cursor: pointer;
164
164
  }
165
165
 
166
166
  @media (prefers-reduced-motion: reduce) {
167
167
  .panel-toggle-icon { transition: none; }
168
- .panel-block--collapsible .panel-body { animation: none; }
168
+ .panel--collapsible .panel-body { animation: none; }
169
169
  }
@@ -2,7 +2,7 @@
2
2
  * @icen.ai/ui — Component: pill(状态徽章 / tag)
3
3
  *
4
4
  * 完整契约:
5
- * <span class="pill [ok|warn|bad|accent|info] [.pill--dot|pill--outline|pill--sm]">文本</span>
5
+ * <span class="pill [pill--success|pill--warning|pill--error|pill--info|pill--accent] [.pill--dot|pill--outline|pill--sm]">文本</span>
6
6
  *
7
7
  * 语义色纪律:仅绿/黄/红/信息 + 品牌 accent。
8
8
  * --dot:左侧加状态色圆点;--outline:透明底、纯描边;--sm:紧凑尺寸。
@@ -24,27 +24,27 @@
24
24
  vertical-align: middle;
25
25
  }
26
26
 
27
- .pill.ok {
27
+ .pill--success {
28
28
  color: var(--token-success);
29
29
  border-color: color-mix(in srgb, var(--token-success) 35%, transparent);
30
30
  background: color-mix(in srgb, var(--token-success) 9%, transparent);
31
31
  }
32
- .pill.warn {
32
+ .pill--warning {
33
33
  color: var(--token-warning);
34
34
  border-color: color-mix(in srgb, var(--token-warning) 35%, transparent);
35
35
  background: color-mix(in srgb, var(--token-warning) 9%, transparent);
36
36
  }
37
- .pill.bad {
37
+ .pill--error {
38
38
  color: var(--token-error);
39
39
  border-color: color-mix(in srgb, var(--token-error) 35%, transparent);
40
40
  background: color-mix(in srgb, var(--token-error) 9%, transparent);
41
41
  }
42
- .pill.accent {
42
+ .pill--accent {
43
43
  color: var(--token-accent-deep, var(--token-accent));
44
44
  border-color: color-mix(in srgb, var(--token-accent) 40%, transparent);
45
45
  background: color-mix(in srgb, var(--token-accent) 9%, transparent);
46
46
  }
47
- .pill.info {
47
+ .pill--info {
48
48
  color: var(--token-info);
49
49
  border-color: color-mix(in srgb, var(--token-info) 35%, transparent);
50
50
  background: color-mix(in srgb, var(--token-info) 9%, transparent);
@@ -69,7 +69,7 @@
69
69
  /* 尺寸变体 */
70
70
  .pill--sm {
71
71
  padding: 1px var(--density-space-xs);
72
- font-size: 10px;
72
+ font-size: var(--density-font-size-2xs);
73
73
  }
74
74
  .pill--lg {
75
75
  padding: 4px calc(var(--density-space-sm) + 2px);
@@ -79,13 +79,13 @@
79
79
  /* 实色变体:accent 实底(用于 count、活跃状态等强调场景) */
80
80
  .pill--solid {
81
81
  background: var(--token-accent);
82
- color: var(--token-on-accent, #fff);
82
+ color: var(--token-on-accent);
83
83
  border-color: var(--token-accent);
84
84
  }
85
- .pill--solid.ok { background: var(--token-success); border-color: var(--token-success); color: var(--token-on-accent, #fff); }
86
- .pill--solid.warn { background: var(--token-warning); border-color: var(--token-warning); color: var(--token-on-accent, #fff); }
87
- .pill--solid.bad { background: var(--token-error); border-color: var(--token-error); color: var(--token-on-accent, #fff); }
88
- .pill--solid.info { background: var(--token-info); border-color: var(--token-info); color: var(--token-on-accent, #fff); }
85
+ .pill--solid.pill--success { background: var(--token-success); border-color: var(--token-success); }
86
+ .pill--solid.pill--warning { background: var(--token-warning); border-color: var(--token-warning); }
87
+ .pill--solid.pill--error { background: var(--token-error); border-color: var(--token-error); }
88
+ .pill--solid.pill--info { background: var(--token-info); border-color: var(--token-info); }
89
89
 
90
90
  /* ── 增强 ── */
91
91
 
@@ -126,7 +126,7 @@
126
126
  border-radius: var(--radius-full);
127
127
  background: currentColor;
128
128
  margin-right: 2px;
129
- animation: pill-pulse 1.5s ease-in-out infinite;
129
+ animation: pill-pulse var(--pill-pulse-duration, 1.5s) ease-in-out infinite;
130
130
  }
131
131
  @keyframes pill-pulse {
132
132
  0%, 100% { opacity: 1; transform: scale(1); }
@@ -139,7 +139,7 @@
139
139
  height: 18px;
140
140
  padding: 0 5px;
141
141
  justify-content: center;
142
- font-size: 10px;
142
+ font-size: var(--density-font-size-2xs);
143
143
  font-weight: 700;
144
144
  font-variant-numeric: tabular-nums;
145
145
  line-height: 1;
@@ -148,7 +148,7 @@
148
148
  /* 渐变变体 */
149
149
  .pill--gradient {
150
150
  background: linear-gradient(135deg, var(--token-accent), var(--token-accent-deep, var(--token-accent)));
151
- color: var(--token-on-accent, #fff);
151
+ color: var(--token-on-accent);
152
152
  border-color: transparent;
153
153
  }
154
154
 
@@ -1,2 +1,3 @@
1
1
  // @icen.ai/ui — kit: rating(CSS + behavior 一行入口;构建产物,勿手改)
2
2
  import './media.css';
3
+ export { initRating } from '../behaviors/controls.mjs';