@icen.ai/ui 0.2.1 → 0.4.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 (121) hide show
  1. package/README.md +29 -16
  2. package/dist/base.css +389 -48
  3. package/dist/behaviors/accordion.mjs +20 -0
  4. package/dist/behaviors/carousel.mjs +30 -1
  5. package/dist/behaviors/charts.mjs +356 -0
  6. package/dist/behaviors/copy.mjs +4 -3
  7. package/dist/behaviors/datatable.mjs +968 -0
  8. package/dist/behaviors/input.mjs +20 -1
  9. package/dist/behaviors/modal.mjs +14 -0
  10. package/dist/behaviors/nav.mjs +31 -4
  11. package/dist/behaviors/sidebar.mjs +12 -0
  12. package/dist/behaviors/slider.mjs +35 -3
  13. package/dist/behaviors/tabs.mjs +100 -9
  14. package/dist/behaviors/tag-input.mjs +11 -0
  15. package/dist/behaviors/theme.mjs +26 -0
  16. package/dist/behaviors/toast.mjs +83 -15
  17. package/dist/behaviors/tree.mjs +57 -1
  18. package/dist/behaviors/upload.mjs +2 -3
  19. package/dist/cli.mjs +74 -0
  20. package/dist/components/accordion.mjs +3 -0
  21. package/dist/components/alert.mjs +2 -0
  22. package/dist/components/avatar.mjs +2 -0
  23. package/dist/components/breadcrumb.css +91 -18
  24. package/dist/components/breadcrumb.mjs +2 -0
  25. package/dist/components/btn.css +174 -14
  26. package/dist/components/btn.mjs +2 -0
  27. package/dist/components/card.css +118 -18
  28. package/dist/components/card.mjs +2 -0
  29. package/dist/components/carousel.mjs +3 -0
  30. package/dist/components/chart-area.css +15 -0
  31. package/dist/components/chart-area.mjs +4 -0
  32. package/dist/components/chart-bar.css +79 -0
  33. package/dist/components/chart-bar.mjs +4 -0
  34. package/dist/components/chart-gauge.css +38 -0
  35. package/dist/components/chart-gauge.mjs +4 -0
  36. package/dist/components/chart-heatmap.css +52 -0
  37. package/dist/components/chart-heatmap.mjs +4 -0
  38. package/dist/components/chart-line.css +15 -0
  39. package/dist/components/chart-line.mjs +4 -0
  40. package/dist/components/chart-pie.css +26 -0
  41. package/dist/components/chart-pie.mjs +4 -0
  42. package/dist/components/chart-radar.css +19 -0
  43. package/dist/components/chart-radar.mjs +4 -0
  44. package/dist/components/chart-sparkline.css +14 -0
  45. package/dist/components/chart-sparkline.mjs +4 -0
  46. package/dist/components/chart-stack.css +30 -0
  47. package/dist/components/chart-stack.mjs +4 -0
  48. package/dist/components/charts.css +66 -74
  49. package/dist/components/charts.mjs +12 -0
  50. package/dist/components/content.css +256 -74
  51. package/dist/components/context-menu.mjs +3 -0
  52. package/dist/components/datatable.css +429 -0
  53. package/dist/components/datatable.mjs +4 -0
  54. package/dist/components/desc.mjs +2 -0
  55. package/dist/components/dropdown.mjs +3 -0
  56. package/dist/components/empty.css +50 -10
  57. package/dist/components/empty.mjs +2 -0
  58. package/dist/components/feedback.css +158 -47
  59. package/dist/components/form.css +139 -22
  60. package/dist/components/input.css +165 -45
  61. package/dist/components/input.mjs +3 -0
  62. package/dist/components/kbd.mjs +2 -0
  63. package/dist/components/layout.mjs +2 -0
  64. package/dist/components/list.mjs +2 -0
  65. package/dist/components/media-card.mjs +2 -0
  66. package/dist/components/media.css +187 -40
  67. package/dist/components/menu.css +159 -32
  68. package/dist/components/modal.css +140 -34
  69. package/dist/components/modal.mjs +3 -0
  70. package/dist/components/nav.css +134 -32
  71. package/dist/components/nav.mjs +3 -0
  72. package/dist/components/pagination.css +105 -19
  73. package/dist/components/pagination.mjs +2 -0
  74. package/dist/components/panel.css +61 -6
  75. package/dist/components/panel.mjs +2 -0
  76. package/dist/components/pill.css +74 -14
  77. package/dist/components/pill.mjs +2 -0
  78. package/dist/components/popover.css +109 -7
  79. package/dist/components/popover.mjs +3 -0
  80. package/dist/components/progress.mjs +2 -0
  81. package/dist/components/rating.mjs +2 -0
  82. package/dist/components/result.mjs +2 -0
  83. package/dist/components/segmented.css +199 -50
  84. package/dist/components/segmented.mjs +2 -0
  85. package/dist/components/select.css +140 -39
  86. package/dist/components/select.mjs +3 -0
  87. package/dist/components/sidebar.css +162 -34
  88. package/dist/components/sidebar.mjs +3 -0
  89. package/dist/components/skeleton.mjs +2 -0
  90. package/dist/components/slider.css +169 -31
  91. package/dist/components/slider.mjs +3 -0
  92. package/dist/components/spinner.mjs +2 -0
  93. package/dist/components/stat.css +103 -8
  94. package/dist/components/stat.mjs +2 -0
  95. package/dist/components/steps.css +105 -31
  96. package/dist/components/steps.mjs +2 -0
  97. package/dist/components/switch.css +171 -54
  98. package/dist/components/switch.mjs +2 -0
  99. package/dist/components/table.css +114 -12
  100. package/dist/components/table.mjs +2 -0
  101. package/dist/components/tabs.css +104 -17
  102. package/dist/components/tabs.mjs +3 -0
  103. package/dist/components/tag-input.css +119 -23
  104. package/dist/components/tag-input.mjs +3 -0
  105. package/dist/components/timeline.mjs +2 -0
  106. package/dist/components/toast.css +85 -12
  107. package/dist/components/toast.mjs +3 -0
  108. package/dist/components/tooltip.css +86 -26
  109. package/dist/components/tooltip.mjs +2 -0
  110. package/dist/components/tree.mjs +3 -0
  111. package/dist/components/upload.css +144 -17
  112. package/dist/components/upload.mjs +3 -0
  113. package/dist/index.mjs +811 -42
  114. package/dist/registry.json +310 -2
  115. package/dist/retro-effects.css +264 -0
  116. package/dist/tokens/colors.css +18 -90
  117. package/dist/tokens/retro-effects.css +264 -0
  118. package/dist/tokens/style-profiles.css +47 -47
  119. package/dist/tokens.css +65 -137
  120. package/dist/ui.css +5069 -1026
  121. package/package.json +9 -1
@@ -1,5 +1,6 @@
1
1
  /*
2
2
  * @icen.ai/ui — Component: content(内容展示族)
3
+ *
3
4
  * 包含:kbd(按键)/ code-inline(行内代码)/ list(分隔列表)/ accordion(手风琴,behaviors/accordion 配套)/
4
5
  * timeline(时间线)/ desc(描述列表)/ tree(树形,behaviors/tree 配套)
5
6
  * 规格源自 opengal src/presentation/ui/data/exhibit.tsx 与 data/display.tsx。
@@ -7,131 +8,231 @@
7
8
 
8
9
  /* ══════════════ kbd · 按键 ══════════════ */
9
10
  .kbd {
10
- display: inline-flex; align-items: center; justify-content: center;
11
+ display: inline-flex;
12
+ align-items: center;
13
+ justify-content: center;
11
14
  vertical-align: middle;
12
- font-family: var(--font-mono); font-weight: 500;
15
+ font-family: var(--font-mono);
16
+ font-weight: 500;
13
17
  border-radius: var(--radius-xs);
14
18
  border: 1px solid var(--token-outline);
15
19
  background: var(--token-control);
16
20
  color: var(--token-text-muted);
17
21
  box-shadow: var(--token-shadow-inset);
18
- height: 20px; min-width: 20px;
19
- padding: 0 6px;
20
- font-size: 11px;
22
+ height: 20px;
23
+ min-width: 20px;
24
+ padding: 0 var(--density-space-xs);
25
+ font-size: var(--density-font-size-xs);
26
+ }
27
+ .kbd--sm {
28
+ height: 16px;
29
+ min-width: 16px;
30
+ padding: 0 4px;
31
+ font-size: 10px;
21
32
  }
22
- .kbd--sm { height: 16px; min-width: 16px; padding: 0 4px; font-size: 10px; }
33
+ .kbd-group {
34
+ display: inline-flex;
35
+ align-items: center;
36
+ gap: 2px;
37
+ font-family: var(--font-mono);
38
+ font-size: var(--density-font-size-xs);
39
+ color: var(--token-text-muted);
40
+ }
41
+ .kbd-group .kbd { font-size: inherit; }
23
42
 
24
43
  /* ══════════════ code-inline · 行内代码 ══════════════ */
25
44
  .code-inline {
26
- padding: 2px 6px;
45
+ padding: 2px var(--density-space-xs);
27
46
  border-radius: var(--radius-xs);
28
47
  background: var(--token-control);
29
48
  border: 1px solid var(--token-outline-soft);
30
- font-size: 12px;
49
+ font-size: 0.9em;
31
50
  font-family: var(--font-mono);
32
51
  color: var(--token-accent);
52
+ word-break: break-word;
33
53
  }
34
54
 
35
- /* ══════════════ list · 分隔列表 ══════════════ */
36
- .list { list-style: none; margin: 0; padding: 0; }
55
+ /* ══════════════ list · 分隔列表 ══════════════
56
+ * DOM:<ul class="list [list--hover|list--compact]"><li class="list-item">…</li></ul>
57
+ * list--hover:每项 hover 浮起(默认有 hover);
58
+ * list--compact:缩小 padding。
59
+ */
60
+ .list {
61
+ list-style: none;
62
+ margin: 0;
63
+ padding: 0;
64
+ }
37
65
  .list-item {
38
- padding: 8px;
39
- border-radius: var(--radius-md);
40
- transition: background-color var(--duration-normal) var(--ease-out);
66
+ padding: var(--density-space-sm);
67
+ border-radius: var(--radius-sm);
68
+ transition: background-color var(--icen-tx-fast);
41
69
  }
42
70
  .list-item:hover { background: var(--token-control-hover); }
43
71
  .list .list-item + .list-item { border-top: 1px solid var(--token-outline-soft); }
72
+ .list--compact .list-item { padding: var(--density-space-xs) var(--density-space-sm); }
44
73
 
45
74
  /* ══════════════ accordion · 手风琴(behaviors/accordion 配套) ══════════════
46
- * DOM 契约:
75
+ * DOM:
47
76
  * <div class="accordion" data-single?>
48
- * <div class="accordion-item">
49
- * <button class="accordion-trigger">标题 <svg class="accordion-chevron"/></button>
77
+ * <div class="accordion-item [.is-open] [.is-disabled]">
78
+ * <button class="accordion-trigger" aria-expanded="true">标题 <svg class="accordion-chevron"/></button>
50
79
  * <div class="accordion-panel"><div class="accordion-panel-inner">内容</div></div>
51
80
  * </div>
52
81
  * </div>
53
82
  * 展开 = item 挂 .is-open;panel 用 grid-template-rows 0fr→1fr 做过渡。
83
+ * data-single:展开一项自动收起其余(behavior 实现)。
54
84
  */
55
- .accordion-item { border-bottom: 1px solid var(--token-outline-soft); }
85
+ .accordion-item {
86
+ border-bottom: 1px solid var(--token-outline-soft);
87
+ }
56
88
  .accordion-item:last-child { border-bottom: 0; }
57
89
  .accordion-trigger {
58
90
  width: 100%;
59
- display: flex; align-items: center; justify-content: space-between; gap: 8px;
60
- padding: 12px 8px;
61
- font-size: 14px; font-weight: 500;
62
- color: var(--token-text); text-align: left;
63
- background: none; border: 0; cursor: pointer;
64
- border-radius: var(--radius-md);
65
- transition: background-color var(--duration-normal) var(--ease-out);
91
+ display: flex;
92
+ align-items: center;
93
+ justify-content: space-between;
94
+ gap: var(--density-space-sm);
95
+ padding: var(--density-space-sm);
96
+ font-size: var(--density-font-size-md);
97
+ font-weight: 500;
98
+ color: var(--token-text);
99
+ text-align: left;
100
+ background: none;
101
+ border: 0;
102
+ cursor: pointer;
103
+ border-radius: var(--radius-sm);
104
+ transition: background-color var(--icen-tx-fast);
105
+ }
106
+ .accordion-trigger:hover {
107
+ background: var(--token-control-hover);
108
+ }
109
+ .accordion-trigger:focus-visible {
110
+ outline: none;
111
+ box-shadow: var(--icen-ring);
112
+ }
113
+ .accordion-item.is-disabled .accordion-trigger,
114
+ .accordion-item[aria-disabled='true'] .accordion-trigger {
115
+ opacity: var(--icen-disabled-opacity);
116
+ cursor: not-allowed;
117
+ pointer-events: none;
66
118
  }
67
- .accordion-trigger:hover { background: var(--token-control-hover); }
68
119
  .accordion-chevron {
69
- width: 14px; height: 14px; flex-shrink: 0;
120
+ width: 14px;
121
+ height: 14px;
122
+ flex-shrink: 0;
70
123
  color: var(--token-text-faint);
71
- transition: transform var(--duration-normal) var(--ease-out);
124
+ transition: transform var(--icen-tx-normal);
125
+ }
126
+ .accordion-item.is-open .accordion-chevron {
127
+ transform: rotate(180deg);
72
128
  }
73
- .accordion-item.is-open .accordion-chevron { transform: rotate(180deg); }
74
129
  .accordion-panel {
75
130
  display: grid;
76
131
  grid-template-rows: 0fr;
77
- transition: grid-template-rows var(--duration-normal) var(--ease-out);
132
+ transition: grid-template-rows var(--icen-tx-normal);
78
133
  }
79
134
  .accordion-item.is-open .accordion-panel { grid-template-rows: 1fr; }
80
135
  .accordion-panel-inner {
81
136
  overflow: hidden;
82
- padding: 0 8px 12px;
83
- font-size: 13px;
137
+ min-height: 0;
138
+ padding: 0 var(--density-space-sm) var(--density-space-sm);
139
+ font-size: var(--density-font-size-sm);
84
140
  color: var(--token-text-muted);
85
141
  line-height: 1.6;
86
142
  }
87
143
 
144
+ /* 卡片式手风琴:整组包在带边框的卡片里 */
145
+ .accordion--cards {
146
+ border: 1px solid var(--token-outline-soft);
147
+ border-radius: var(--radius-md);
148
+ overflow: hidden;
149
+ }
150
+ .accordion--cards .accordion-item {
151
+ border-bottom: 0;
152
+ }
153
+ .accordion--cards .accordion-item + .accordion-item {
154
+ border-top: 1px solid var(--token-outline-soft);
155
+ }
156
+
88
157
  /* ══════════════ timeline · 时间线 ══════════════
89
- * DOM 契约:.timeline-item > .timeline-dot + .timeline-body
90
- * 连接线 = item 的 ::after(相对 item 绝对定位,从 dot 下方贯穿到下一项),末项不画。
158
+ * DOM:.timeline-item > .timeline-dot + .timeline-body
159
+ * 连接线 = item::after(相对 item 绝对定位,从 dot 下方贯穿到下一项),末项不画。
91
160
  */
92
- .timeline { display: flex; flex-direction: column; }
161
+ .timeline {
162
+ display: flex;
163
+ flex-direction: column;
164
+ }
93
165
  .timeline-item {
94
166
  position: relative;
95
- display: flex; gap: 12px;
96
- padding-bottom: 24px;
167
+ display: flex;
168
+ gap: var(--density-space-sm);
169
+ padding-bottom: var(--density-space-lg);
97
170
  }
98
171
  .timeline-item:last-child { padding-bottom: 0; }
99
172
  .timeline-item:not(:last-child)::after {
100
173
  content: '';
101
174
  position: absolute;
102
- left: 13.5px; /* 28px dot 的水平中心 */
103
- top: 32px; /* 28px dot + 4px 间距 */
175
+ left: 13.5px; /* 28px dot 的水平中心 */
176
+ top: 32px;
104
177
  bottom: 0;
105
178
  width: 1px;
106
179
  background: var(--token-outline-soft);
107
180
  }
108
181
  .timeline-dot {
109
- width: 28px; height: 28px; flex-shrink: 0;
182
+ width: 28px;
183
+ height: 28px;
184
+ flex-shrink: 0;
110
185
  border-radius: var(--radius-full);
111
- display: flex; align-items: center; justify-content: center;
186
+ display: flex;
187
+ align-items: center;
188
+ justify-content: center;
112
189
  background: var(--token-control);
113
190
  border: 1px solid var(--token-outline-soft);
114
191
  color: var(--token-text-muted);
115
192
  z-index: 1;
116
193
  }
117
194
  .timeline-dot svg { width: 13px; height: 13px; }
118
- .timeline-dot--accent { background: var(--token-accent); color: var(--token-on-accent); border-color: transparent; }
119
- .timeline-dot--success { background: var(--token-success); color: var(--token-on-accent); border-color: transparent; }
120
- .timeline-dot--warning { background: var(--token-warning); color: var(--token-on-accent); border-color: transparent; }
121
- .timeline-dot--error { background: var(--token-error); color: var(--token-on-accent); border-color: transparent; }
122
- .timeline-dot--info { background: var(--token-info); color: var(--token-on-accent); border-color: transparent; }
195
+ .timeline-dot--accent { background: var(--token-accent); color: var(--token-on-accent, #fff); border-color: transparent; }
196
+ .timeline-dot--success { background: var(--token-success); color: var(--token-on-accent, #fff); border-color: transparent; }
197
+ .timeline-dot--warning { background: var(--token-warning); color: var(--token-on-accent, #fff); border-color: transparent; }
198
+ .timeline-dot--error { background: var(--token-error); color: var(--token-on-accent, #fff); border-color: transparent; }
199
+ .timeline-dot--info { background: var(--token-info); color: var(--token-on-accent, #fff); border-color: transparent; }
200
+
123
201
  .timeline-body { flex: 1; min-width: 0; }
124
- .timeline-head { display: flex; align-items: center; gap: 8px; }
125
- .timeline-title { font-size: 13px; font-weight: 500; color: var(--token-text); }
126
- .timeline-time { font-size: 11px; color: var(--token-text-faint); margin-left: auto; font-variant-numeric: tabular-nums; }
127
- .timeline-desc { font-size: 12px; color: var(--token-text-muted); margin: 4px 0 0; }
202
+ .timeline-head {
203
+ display: flex;
204
+ align-items: center;
205
+ gap: var(--density-space-sm);
206
+ }
207
+ .timeline-title {
208
+ font-size: var(--density-font-size-md);
209
+ font-weight: 500;
210
+ color: var(--token-text);
211
+ }
212
+ .timeline-time {
213
+ font-size: var(--density-font-size-xs);
214
+ color: var(--token-text-faint);
215
+ margin-left: auto;
216
+ font-variant-numeric: tabular-nums;
217
+ }
218
+ .timeline-desc {
219
+ font-size: var(--density-font-size-sm);
220
+ color: var(--token-text-muted);
221
+ margin: 4px 0 0;
222
+ line-height: 1.5;
223
+ }
128
224
 
129
225
  /* ══════════════ desc · 描述列表 ══════════════
130
226
  * 列数由容器 style="--desc-cols:N" 指定,默认 2;item 可用 style="--desc-span:N" 跨列。
131
227
  * --bordered 变体:gap:1px 露出容器底色形成格线。
132
228
  */
133
- .desc { display: flex; flex-direction: column; gap: 8px; }
134
- .desc-title { font-size: 13px; font-weight: 500; color: var(--token-text); margin: 0; }
229
+ .desc { display: flex; flex-direction: column; gap: var(--density-space-sm); }
230
+ .desc-title {
231
+ font-size: var(--density-font-size-md);
232
+ font-weight: 500;
233
+ color: var(--token-text);
234
+ margin: 0;
235
+ }
135
236
  .desc-grid {
136
237
  display: grid;
137
238
  grid-template-columns: repeat(var(--desc-cols, 2), minmax(0, 1fr));
@@ -141,55 +242,136 @@
141
242
  .desc--bordered .desc-grid {
142
243
  background: var(--token-outline-soft);
143
244
  border: 1px solid var(--token-outline-soft);
144
- border-radius: var(--radius-lg);
245
+ border-radius: var(--radius-md);
145
246
  overflow: hidden;
146
247
  }
147
248
  .desc-item { grid-column: span var(--desc-span, 1); }
148
- .desc--bordered .desc-item { background: var(--token-card); padding: 8px 12px; }
149
- .desc:not(.desc--bordered) .desc-item { display: flex; flex-direction: column; gap: 2px; }
150
- .desc-item dt { font-size: 11px; color: var(--token-text-faint); }
151
- .desc-item dd { font-size: 13px; color: var(--token-text); margin: 0; }
249
+ .desc--bordered .desc-item {
250
+ background: var(--token-card);
251
+ padding: var(--density-space-sm) var(--density-space-md);
252
+ }
253
+ .desc:not(.desc--bordered) .desc-item {
254
+ display: flex;
255
+ flex-direction: column;
256
+ gap: 2px;
257
+ }
258
+ .desc-item dt {
259
+ font-size: var(--density-font-size-xs);
260
+ color: var(--token-text-faint);
261
+ }
262
+ .desc-item dd {
263
+ font-size: var(--density-font-size-md);
264
+ color: var(--token-text);
265
+ margin: 0;
266
+ line-height: 1.5;
267
+ }
268
+
269
+ @media (max-width: 640px) {
270
+ .desc-grid { grid-template-columns: 1fr !important; }
271
+ }
152
272
 
153
273
  /* ══════════════ tree · 树形(behaviors/tree 配套) ══════════════
154
- * DOM 契约:
274
+ * DOM:
155
275
  * <ul class="tree"><li>
156
- * <div class="tree-node" style="--depth:0">
157
- * <button class="tree-toggle"><svg/></button> <!-- 叶子用空 span.tree-toggle 占 18px -->
276
+ * <div class="tree-node [.is-selected] [.is-disabled]" style="--depth:0">
277
+ * <button class="tree-toggle [.is-collapsed]"><svg/></button>
158
278
  * <span class="tree-label">节点</span>
159
279
  * </div>
160
- * <ul>…子节点…</ul> <!-- 可选;behavior 切换 hidden -->
280
+ * <ul>…子节点…</ul>
161
281
  * </li></ul>
162
282
  * 折叠 = toggle 挂 .is-collapsed(chevron 转 -90°)+ 子 ul hidden;选中 = node 挂 .is-selected。
163
283
  */
164
- .tree, .tree ul { list-style: none; margin: 0; padding: 0; }
284
+ .tree, .tree ul {
285
+ list-style: none;
286
+ margin: 0;
287
+ padding: 0;
288
+ }
165
289
  .tree { user-select: none; }
166
290
  .tree-node {
167
- display: flex; align-items: center; gap: 6px;
168
- padding: 6px 8px 6px calc(4px + var(--depth, 0) * 14px);
169
- border-radius: var(--radius-md);
170
- font-size: 13px;
291
+ display: flex;
292
+ align-items: center;
293
+ gap: var(--density-space-xs);
294
+ padding: var(--density-space-xs) var(--density-space-sm) var(--density-space-xs) calc(4px + var(--depth, 0) * 14px);
295
+ border-radius: var(--radius-sm);
296
+ font-size: var(--density-font-size-md);
171
297
  color: var(--token-text);
172
298
  cursor: pointer;
173
- transition: background-color var(--duration-normal) var(--ease-out);
299
+ transition: background-color var(--icen-tx-fast);
174
300
  }
175
301
  .tree-node:hover { background: var(--token-control-hover); }
176
- .tree-node.is-selected {
302
+ .tree-node:focus-visible,
303
+ .tree-node:focus-within {
304
+ outline: none;
305
+ box-shadow: var(--icen-ring);
306
+ }
307
+ .tree-node.is-selected,
308
+ .tree-node[aria-selected='true'] {
177
309
  background: var(--token-accent-subtle);
178
310
  color: var(--token-accent);
179
311
  font-weight: 500;
180
312
  }
181
- .tree-node.is-disabled { opacity: 0.4; pointer-events: none; }
313
+ .tree-node.is-disabled,
314
+ .tree-node[aria-disabled='true'] {
315
+ opacity: var(--icen-disabled-opacity);
316
+ pointer-events: none;
317
+ }
182
318
  .tree-toggle {
183
- width: 18px; height: 18px; flex-shrink: 0;
184
- display: inline-flex; align-items: center; justify-content: center;
185
- padding: 0; border: 0; background: none;
319
+ width: 18px;
320
+ height: 18px;
321
+ flex-shrink: 0;
322
+ display: inline-flex;
323
+ align-items: center;
324
+ justify-content: center;
325
+ padding: 0;
326
+ border: 0;
327
+ background: none;
186
328
  color: var(--token-text-muted);
187
329
  cursor: pointer;
188
330
  }
189
331
  .tree-toggle:hover { color: var(--token-text); }
332
+ .tree-toggle:focus-visible {
333
+ outline: none;
334
+ border-radius: var(--radius-xs);
335
+ box-shadow: var(--icen-ring);
336
+ }
190
337
  .tree-toggle svg {
191
- width: 13px; height: 13px;
192
- transition: transform var(--duration-normal) var(--ease-out);
338
+ width: 13px;
339
+ height: 13px;
340
+ transition: transform var(--icen-tx-fast);
193
341
  }
194
342
  .tree-toggle.is-collapsed svg { transform: rotate(-90deg); }
195
- .tree-label { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
343
+ .tree-toggle[aria-hidden='true'] { visibility: hidden; pointer-events: none; }
344
+ .tree-label {
345
+ flex: 1;
346
+ min-width: 0;
347
+ overflow: hidden;
348
+ text-overflow: ellipsis;
349
+ white-space: nowrap;
350
+ }
351
+ .tree-icon {
352
+ flex-shrink: 0;
353
+ width: 14px;
354
+ height: 14px;
355
+ color: var(--token-text-muted);
356
+ }
357
+ .tree-node.is-selected .tree-icon { color: var(--token-accent); }
358
+ .tree-badge {
359
+ display: inline-flex;
360
+ align-items: center;
361
+ justify-content: center;
362
+ min-width: 16px;
363
+ height: 16px;
364
+ padding: 0 4px;
365
+ font-size: 10px;
366
+ font-weight: 600;
367
+ color: var(--token-on-accent, #fff);
368
+ background: var(--token-accent);
369
+ border-radius: var(--radius-full);
370
+ flex-shrink: 0;
371
+ }
372
+
373
+ @media (prefers-reduced-motion: reduce) {
374
+ .accordion-panel, .accordion-chevron, .tree-toggle svg, .list-item, .tree-node {
375
+ transition: none;
376
+ }
377
+ }
@@ -0,0 +1,3 @@
1
+ // @icen.ai/ui — kit: context-menu(CSS + behavior 一行入口;构建产物,勿手改)
2
+ import './menu.css';
3
+ export * from '../behaviors/context-menu.mjs';