@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.
- package/AGENTS.md +262 -0
- package/README.md +52 -13
- package/dist/base.css +33 -5
- package/dist/behaviors/accordion.d.mts +7 -0
- package/dist/behaviors/accordion.mjs +37 -11
- package/dist/behaviors/ai-chat.d.mts +59 -0
- package/dist/behaviors/ai-chat.mjs +580 -0
- package/dist/behaviors/ai-composer.d.mts +137 -0
- package/dist/behaviors/ai-composer.mjs +2114 -0
- package/dist/behaviors/ai-core.d.mts +156 -0
- package/dist/behaviors/ai-core.mjs +504 -0
- package/dist/behaviors/ai-diff.d.mts +53 -0
- package/dist/behaviors/ai-diff.mjs +413 -0
- package/dist/behaviors/ai-panel.d.mts +101 -0
- package/dist/behaviors/ai-panel.mjs +1087 -0
- package/dist/behaviors/ai-provider.d.mts +198 -0
- package/dist/behaviors/ai-provider.mjs +1061 -0
- package/dist/behaviors/ai-tool.d.mts +26 -0
- package/dist/behaviors/ai-tool.mjs +2173 -0
- package/dist/behaviors/ai-tools.d.mts +84 -0
- package/dist/behaviors/ai-tools.mjs +1762 -0
- package/dist/behaviors/back-top.d.mts +20 -0
- package/dist/behaviors/back-top.mjs +64 -32
- package/dist/behaviors/carousel.d.mts +7 -0
- package/dist/behaviors/carousel.mjs +72 -27
- package/dist/behaviors/charts.d.mts +296 -0
- package/dist/behaviors/charts.mjs +1364 -440
- package/dist/behaviors/command-palette.d.mts +42 -0
- package/dist/behaviors/command-palette.mjs +167 -27
- package/dist/behaviors/context-menu.d.mts +53 -0
- package/dist/behaviors/context-menu.mjs +127 -39
- package/dist/behaviors/controls.d.mts +59 -0
- package/dist/behaviors/controls.mjs +601 -0
- package/dist/behaviors/copy.d.mts +7 -0
- package/dist/behaviors/copy.mjs +41 -15
- package/dist/behaviors/datatable.d.mts +90 -0
- package/dist/behaviors/datatable.mjs +279 -53
- package/dist/behaviors/date-picker.d.mts +4 -0
- package/dist/behaviors/date-picker.mjs +276 -69
- package/dist/behaviors/dropdown.d.mts +8 -0
- package/dist/behaviors/dropdown.mjs +171 -28
- package/dist/behaviors/events.d.mts +330 -0
- package/dist/behaviors/events.mjs +208 -0
- package/dist/behaviors/input.d.mts +4 -0
- package/dist/behaviors/input.mjs +52 -32
- package/dist/behaviors/modal.d.mts +30 -0
- package/dist/behaviors/modal.mjs +87 -16
- package/dist/behaviors/nav.d.mts +7 -0
- package/dist/behaviors/nav.mjs +57 -15
- package/dist/behaviors/notification.d.mts +188 -0
- package/dist/behaviors/notification.mjs +274 -140
- package/dist/behaviors/popover.d.mts +82 -0
- package/dist/behaviors/popover.mjs +92 -5
- package/dist/behaviors/select.d.mts +6 -0
- package/dist/behaviors/select.mjs +287 -45
- package/dist/behaviors/sidebar.d.mts +7 -0
- package/dist/behaviors/sidebar.mjs +44 -13
- package/dist/behaviors/slider.d.mts +7 -0
- package/dist/behaviors/slider.mjs +55 -43
- package/dist/behaviors/split-pane.d.mts +8 -0
- package/dist/behaviors/split-pane.mjs +70 -29
- package/dist/behaviors/tabs.d.mts +9 -0
- package/dist/behaviors/tabs.mjs +102 -26
- package/dist/behaviors/tag-input.d.mts +7 -0
- package/dist/behaviors/tag-input.mjs +66 -17
- package/dist/behaviors/theme.d.mts +36 -0
- package/dist/behaviors/theme.mjs +51 -5
- package/dist/behaviors/toast.d.mts +48 -0
- package/dist/behaviors/toast.mjs +98 -25
- package/dist/behaviors/tree.d.mts +7 -0
- package/dist/behaviors/tree.mjs +39 -15
- package/dist/behaviors/upload.d.mts +4 -0
- package/dist/behaviors/upload.mjs +79 -44
- package/dist/cli.mjs +1 -1
- package/dist/components/ai-chat.css +1037 -0
- package/dist/components/ai-chat.mjs +3 -0
- package/dist/components/ai-composer.mjs +3 -0
- package/dist/components/ai-context.mjs +2 -0
- package/dist/components/ai-diff.css +311 -0
- package/dist/components/ai-diff.mjs +3 -0
- package/dist/components/ai-files.mjs +3 -0
- package/dist/components/ai-message.mjs +3 -0
- package/dist/components/ai-panel.css +682 -0
- package/dist/components/ai-reasoning.mjs +3 -0
- package/dist/components/ai-subagent.mjs +2 -0
- package/dist/components/ai-todo.mjs +2 -0
- package/dist/components/ai-tool-call.mjs +2 -0
- package/dist/components/ai-tool.css +532 -0
- package/dist/components/ai-usage.mjs +3 -0
- package/dist/components/badge.css +5 -9
- package/dist/components/breadcrumb.css +0 -36
- package/dist/components/btn.css +4 -7
- package/dist/components/card.css +3 -6
- package/dist/components/chart-bar.css +10 -0
- package/dist/components/chart-calendar.mjs +4 -0
- package/dist/components/chart-gauge.css +1 -1
- package/dist/components/chart-heatmap.css +40 -0
- package/dist/components/chart-pie.css +0 -6
- package/dist/components/chart-scatter.css +24 -0
- package/dist/components/chart-scatter.mjs +4 -0
- package/dist/components/charts.css +87 -2
- package/dist/components/charts.mjs +1 -0
- package/dist/components/command-palette.css +2 -2
- package/dist/components/content.css +11 -25
- package/dist/components/copy.css +8 -8
- package/dist/components/datatable.css +5 -9
- package/dist/components/date-picker.css +4 -8
- package/dist/components/empty.css +0 -4
- package/dist/components/feedback.css +10 -17
- package/dist/components/form.css +13 -14
- package/dist/components/input.css +2 -2
- package/dist/components/layout.css +36 -36
- package/dist/components/media.css +12 -8
- package/dist/components/menu.css +2 -2
- package/dist/components/modal.css +1 -1
- package/dist/components/nav.css +11 -6
- package/dist/components/notification.css +27 -28
- package/dist/components/pagination.css +4 -2
- package/dist/components/pagination.mjs +1 -0
- package/dist/components/panel.css +16 -16
- package/dist/components/pill.css +15 -15
- package/dist/components/rating.mjs +1 -0
- package/dist/components/segmented.css +14 -6
- package/dist/components/segmented.mjs +1 -0
- package/dist/components/select.css +79 -24
- package/dist/components/sidebar.css +1 -1
- package/dist/components/split-pane.css +0 -1
- package/dist/components/stat.css +14 -18
- package/dist/components/steps.css +15 -5
- package/dist/components/steps.mjs +1 -0
- package/dist/components/switch.css +11 -13
- package/dist/components/switch.mjs +1 -0
- package/dist/components/table.css +46 -47
- package/dist/components/table.mjs +1 -0
- package/dist/components/tabs.css +57 -45
- package/dist/components/tag-input.css +5 -10
- package/dist/components/toast.css +16 -13
- package/dist/components/tooltip.css +2 -2
- package/dist/components/upload.css +0 -15
- package/dist/index.d.mts +39 -0
- package/dist/index.mjs +11243 -3312
- package/dist/registry.json +147 -9
- package/dist/retro-effects.css +23 -32
- package/dist/tokens/colors.css +4 -1
- package/dist/tokens/retro-effects.css +23 -32
- package/dist/tokens/style-profiles.css +24 -2
- package/dist/tokens/typography.css +2 -0
- package/dist/tokens.css +30 -3
- package/dist/ui.css +3420 -645
- package/docs/spec/ai-native.md +662 -0
- package/package.json +15 -5
|
@@ -28,7 +28,15 @@
|
|
|
28
28
|
* …
|
|
29
29
|
* </div>
|
|
30
30
|
*
|
|
31
|
-
* segmented/
|
|
31
|
+
* segmented / stepper 由 behaviors/controls.ts 接线(initSegmented / initStepper,
|
|
32
|
+
* 派 icen:segmented-change / icen:stepper-change);otp 由 behaviors/input.ts 的
|
|
33
|
+
* initInput 接线;toggle-group 为纯 CSS 状态组件(.is-active,使用方自行驱动)。
|
|
34
|
+
*
|
|
35
|
+
* 增强段(正文"增强"段):
|
|
36
|
+
* 变体:segmented--block / segmented--ghost / toggle-group--block / toggle-group--ghost
|
|
37
|
+
* 槽位:stepper-unit(步进器单位后缀)/ otp-separator(OTP 分组分隔符)
|
|
38
|
+
* 状态类(消费方施加):.otp.is-complete(behavior 接线中)/ .otp.is-error /
|
|
39
|
+
* .segmented.is-error / .segmented.is-disabled / .toggle-group.is-error / .toggle-group.is-disabled
|
|
32
40
|
*/
|
|
33
41
|
|
|
34
42
|
/* ── 分段控件(排他单选) ── */
|
|
@@ -72,7 +80,7 @@
|
|
|
72
80
|
.segmented-item.is-active,
|
|
73
81
|
.segmented-item[aria-checked='true'] {
|
|
74
82
|
background: var(--token-accent);
|
|
75
|
-
color: var(--token-on-accent
|
|
83
|
+
color: var(--token-on-accent);
|
|
76
84
|
box-shadow: var(--token-shadow-elevated);
|
|
77
85
|
}
|
|
78
86
|
.segmented-item:disabled,
|
|
@@ -130,7 +138,7 @@
|
|
|
130
138
|
.toggle-item.is-active,
|
|
131
139
|
.toggle-item[aria-checked='true'] {
|
|
132
140
|
background: var(--token-accent);
|
|
133
|
-
color: var(--token-on-accent
|
|
141
|
+
color: var(--token-on-accent);
|
|
134
142
|
box-shadow: var(--token-shadow-card);
|
|
135
143
|
}
|
|
136
144
|
.toggle-item:disabled,
|
|
@@ -181,7 +189,7 @@
|
|
|
181
189
|
}
|
|
182
190
|
.stepper-btn:focus-visible {
|
|
183
191
|
outline: none;
|
|
184
|
-
box-shadow:
|
|
192
|
+
box-shadow: var(--icen-ring-inset);
|
|
185
193
|
}
|
|
186
194
|
.stepper-btn:disabled,
|
|
187
195
|
.stepper-btn[aria-disabled='true'] {
|
|
@@ -225,7 +233,7 @@
|
|
|
225
233
|
height: 48px;
|
|
226
234
|
padding: 0;
|
|
227
235
|
text-align: center;
|
|
228
|
-
font-size:
|
|
236
|
+
font-size: var(--density-font-size-xl);
|
|
229
237
|
font-weight: 600;
|
|
230
238
|
font-family: var(--font-mono);
|
|
231
239
|
color: var(--token-text);
|
|
@@ -254,7 +262,7 @@
|
|
|
254
262
|
cursor: not-allowed;
|
|
255
263
|
}
|
|
256
264
|
.otp--sm .otp-cell { width: 32px; height: 40px; font-size: var(--density-font-size-lg); }
|
|
257
|
-
.otp--lg .otp-cell { width: 48px; height: 56px; font-size:
|
|
265
|
+
.otp--lg .otp-cell { width: 48px; height: 56px; font-size: var(--density-font-size-2xl); }
|
|
258
266
|
|
|
259
267
|
@media (prefers-reduced-motion: reduce) {
|
|
260
268
|
.segmented-item, .toggle-item, .stepper-btn, .stepper, .otp-cell { transition: none; }
|
|
@@ -4,14 +4,24 @@
|
|
|
4
4
|
*
|
|
5
5
|
* 完整契约:
|
|
6
6
|
* <div class="select [data-disabled] [.is-open]" data-select
|
|
7
|
-
* [data-select-search] [data-select-multiple] [data-select-max="3"]
|
|
7
|
+
* [data-select-search] [data-select-multiple] [data-select-max="3"]
|
|
8
|
+
* [data-panel-width="220"] [data-panel-min="200"]
|
|
9
|
+
* [data-panel-max="360"] [data-panel-max-height="320"]>
|
|
10
|
+
* <!-- 选项 .select-option 内支持任意 HTML(色卡 / 图标 / 多行);
|
|
11
|
+
* 面板尺寸为全库统一 PanelSizing 契约(behaviors/popover.ts) -->
|
|
8
12
|
* <button class="select-trigger pressable focus-ring [--sm|--lg]" aria-haspopup="listbox"
|
|
9
13
|
* aria-expanded="false" [disabled]>
|
|
10
14
|
* <span class="select-leading">…</span> 可选前缀
|
|
11
|
-
* <span class="select-value is-empty">占位</span>
|
|
12
|
-
* <
|
|
15
|
+
* <span class="select-value is-empty">占位</span> 多选有选中时 behavior 隐藏它
|
|
16
|
+
* <span class="select-chips"> ← 多选选中态由 behavior 渲染(勿手写)
|
|
17
|
+
* <span class="select-chip">标签<span class="select-chip-x" role="button" tabindex="-1">×</span></span>
|
|
18
|
+
* <span class="select-chip select-chip--more">+2</span>
|
|
19
|
+
* </span>
|
|
13
20
|
* <svg class="select-chevron">…</svg>
|
|
14
21
|
* </button>
|
|
22
|
+
* <button class="select-clear" aria-label="清除全部" hidden>×</button> ← 多选可选:
|
|
23
|
+
* 与 trigger 同级(不能嵌套在 button 内),绝对定位叠进 trigger 右侧;
|
|
24
|
+
* behavior 在有选中时自动显示
|
|
15
25
|
* <div class="select-panel" hidden role="listbox">
|
|
16
26
|
* <div class="select-search"> ← data-select-search 时 behavior 自动注入
|
|
17
27
|
* <input class="select-search-input" placeholder="搜索…" />
|
|
@@ -26,7 +36,8 @@
|
|
|
26
36
|
* </div>
|
|
27
37
|
*
|
|
28
38
|
* behavior 维护:
|
|
29
|
-
* - .select.is-open ↔ aria-expanded;panel
|
|
39
|
+
* - .select.is-open ↔ aria-expanded;panel portal 到 body(inline left/top/width/max-height,
|
|
40
|
+
* 带 data-side="top|bottom";多选时带 data-select-multiple);ESC/外部点击关闭
|
|
30
41
|
* - 选项 .is-focused 跟随键盘箭头;Enter 选中 → 写回 .select-value / .is-selected
|
|
31
42
|
* - data-select-search:面板顶部自动插入搜索框,实时过滤(含 data-keywords),空分组自动隐藏
|
|
32
43
|
* - data-select-multiple:点击切选不关面板,trigger 显示计数,hidden input 同步逗号分隔值
|
|
@@ -35,7 +46,6 @@
|
|
|
35
46
|
.select {
|
|
36
47
|
position: relative;
|
|
37
48
|
width: 100%;
|
|
38
|
-
isolation: isolate; /* panel 不被后面兄弟节点的层叠遮挡 */
|
|
39
49
|
}
|
|
40
50
|
|
|
41
51
|
.select-trigger {
|
|
@@ -105,12 +115,11 @@
|
|
|
105
115
|
}
|
|
106
116
|
.select.is-open .select-chevron { transform: rotate(180deg); }
|
|
107
117
|
|
|
118
|
+
/* 面板由 behavior portal 到 body:left/top/width/max-height 由 JS 按 trigger rect inline 写入;
|
|
119
|
+
data-side="top|bottom" 标记翻侧方向;多选时 panel 带 data-select-multiple 属性。 */
|
|
108
120
|
.select-panel {
|
|
109
121
|
position: absolute;
|
|
110
|
-
|
|
111
|
-
left: 0;
|
|
112
|
-
min-width: 100%;
|
|
113
|
-
max-height: 240px;
|
|
122
|
+
z-index: var(--z-popover);
|
|
114
123
|
overflow-y: auto;
|
|
115
124
|
overscroll-behavior: contain;
|
|
116
125
|
padding: 4px;
|
|
@@ -118,17 +127,10 @@
|
|
|
118
127
|
border: 1px solid var(--token-outline);
|
|
119
128
|
border-radius: var(--radius-md);
|
|
120
129
|
box-shadow: var(--token-shadow-overlay);
|
|
121
|
-
z-index: var(--z-popover);
|
|
122
130
|
transform-origin: top center;
|
|
123
|
-
animation:
|
|
124
|
-
}
|
|
125
|
-
@keyframes select-panel-in {
|
|
126
|
-
from { opacity: 0; transform: scale(0.96) translateY(-4px); }
|
|
127
|
-
to { opacity: 1; transform: scale(1) translateY(0); }
|
|
128
|
-
}
|
|
129
|
-
@media (prefers-reduced-motion: reduce) {
|
|
130
|
-
.select-panel { animation: none; }
|
|
131
|
+
animation: icen-pop-in var(--icen-tx-fast);
|
|
131
132
|
}
|
|
133
|
+
.select-panel[data-side='top'] { transform-origin: bottom center; }
|
|
132
134
|
|
|
133
135
|
/* 选项 */
|
|
134
136
|
.select-option {
|
|
@@ -217,8 +219,13 @@
|
|
|
217
219
|
box-shadow: var(--icen-control-focus-shadow);
|
|
218
220
|
}
|
|
219
221
|
|
|
220
|
-
/* ──
|
|
222
|
+
/* ── 多选清除按钮(与 trigger 同级,绝对定位叠进 trigger 右侧、chevron 左侧) ── */
|
|
221
223
|
.select-clear {
|
|
224
|
+
position: absolute;
|
|
225
|
+
top: 50%;
|
|
226
|
+
right: calc(var(--density-space-sm) + 20px);
|
|
227
|
+
transform: translateY(-50%);
|
|
228
|
+
z-index: 1;
|
|
222
229
|
display: inline-flex;
|
|
223
230
|
align-items: center;
|
|
224
231
|
justify-content: center;
|
|
@@ -230,7 +237,7 @@
|
|
|
230
237
|
border-radius: var(--radius-xs);
|
|
231
238
|
background: transparent;
|
|
232
239
|
color: var(--token-text-faint);
|
|
233
|
-
font-size:
|
|
240
|
+
font-size: var(--density-font-size-lg);
|
|
234
241
|
line-height: 1;
|
|
235
242
|
cursor: pointer;
|
|
236
243
|
transition: color var(--icen-tx-fast), background-color var(--icen-tx-fast);
|
|
@@ -239,6 +246,53 @@
|
|
|
239
246
|
color: var(--token-text);
|
|
240
247
|
background: var(--token-fill-1);
|
|
241
248
|
}
|
|
249
|
+
/* 有清除钮时 trigger 右侧让位(clear 18px + chevron 14px + 间距) */
|
|
250
|
+
.select:has(.select-clear) .select-trigger { padding-right: 52px; }
|
|
251
|
+
|
|
252
|
+
/* ── 多选 chips(tag 式展示;× 仅 hover 对应 chip 时出现) ── */
|
|
253
|
+
.select-chips {
|
|
254
|
+
display: inline-flex;
|
|
255
|
+
flex-wrap: wrap;
|
|
256
|
+
align-items: center;
|
|
257
|
+
gap: 4px;
|
|
258
|
+
flex: 1;
|
|
259
|
+
min-width: 0;
|
|
260
|
+
}
|
|
261
|
+
.select-chip {
|
|
262
|
+
display: inline-flex;
|
|
263
|
+
align-items: center;
|
|
264
|
+
max-width: 100%;
|
|
265
|
+
font-size: var(--density-font-size-xs);
|
|
266
|
+
line-height: 1.6;
|
|
267
|
+
color: var(--token-text);
|
|
268
|
+
background: var(--token-fill-2);
|
|
269
|
+
border-radius: var(--radius-sm);
|
|
270
|
+
padding: 0 7px;
|
|
271
|
+
white-space: nowrap;
|
|
272
|
+
}
|
|
273
|
+
.select-chip-x {
|
|
274
|
+
display: inline-flex;
|
|
275
|
+
align-items: center;
|
|
276
|
+
justify-content: center;
|
|
277
|
+
width: 0;
|
|
278
|
+
opacity: 0;
|
|
279
|
+
overflow: hidden;
|
|
280
|
+
margin-left: 0;
|
|
281
|
+
color: var(--token-text-faint);
|
|
282
|
+
border-radius: var(--radius-full);
|
|
283
|
+
font-size: var(--density-font-size-md);
|
|
284
|
+
line-height: 1;
|
|
285
|
+
cursor: pointer;
|
|
286
|
+
transition:
|
|
287
|
+
width var(--icen-tx-fast),
|
|
288
|
+
opacity var(--icen-tx-fast),
|
|
289
|
+
margin-left var(--icen-tx-fast),
|
|
290
|
+
color var(--icen-tx-fast);
|
|
291
|
+
}
|
|
292
|
+
.select-chip:hover .select-chip-x,
|
|
293
|
+
.select-chip-x:focus-visible { width: 12px; opacity: 1; margin-left: 4px; }
|
|
294
|
+
.select-chip-x:hover { color: var(--token-error); }
|
|
295
|
+
.select-chip--more { color: var(--token-text-muted); background: var(--token-fill-1); }
|
|
242
296
|
|
|
243
297
|
/* ── 多选 trigger 高度自适应(chips 可能换行) ── */
|
|
244
298
|
.select[data-select-multiple] .select-trigger {
|
|
@@ -249,8 +303,8 @@
|
|
|
249
303
|
flex-wrap: wrap;
|
|
250
304
|
}
|
|
251
305
|
|
|
252
|
-
/* 多选项 checkbox
|
|
253
|
-
.select[data-select-multiple] .select-option::before {
|
|
306
|
+
/* 多选项 checkbox 指示器(选项左侧;panel portal 到 body,属性在 panel 上) */
|
|
307
|
+
.select-panel[data-select-multiple] .select-option::before {
|
|
254
308
|
content: '';
|
|
255
309
|
width: 14px;
|
|
256
310
|
height: 14px;
|
|
@@ -259,11 +313,11 @@
|
|
|
259
313
|
border-radius: var(--radius-xs);
|
|
260
314
|
transition: background-color var(--icen-tx-fast), border-color var(--icen-tx-fast);
|
|
261
315
|
}
|
|
262
|
-
.select[data-select-multiple] .select-option.is-selected::before {
|
|
316
|
+
.select-panel[data-select-multiple] .select-option.is-selected::before {
|
|
263
317
|
background: var(--token-accent);
|
|
264
318
|
border-color: var(--token-accent);
|
|
265
319
|
}
|
|
266
|
-
.select[data-select-multiple] .select-option.is-selected::after {
|
|
320
|
+
.select-panel[data-select-multiple] .select-option.is-selected::after {
|
|
267
321
|
content: '✓';
|
|
268
322
|
margin-left: auto;
|
|
269
323
|
}
|
|
@@ -271,5 +325,6 @@
|
|
|
271
325
|
@media (prefers-reduced-motion: reduce) {
|
|
272
326
|
.select-panel { animation: none; }
|
|
273
327
|
.select-search-input,
|
|
328
|
+
.select-chip-x,
|
|
274
329
|
.select-clear { transition: none; }
|
|
275
330
|
}
|
|
@@ -170,7 +170,7 @@
|
|
|
170
170
|
padding: 0 5px;
|
|
171
171
|
font-size: var(--density-font-size-xs);
|
|
172
172
|
font-weight: 600;
|
|
173
|
-
color: var(--token-on-accent
|
|
173
|
+
color: var(--token-on-accent);
|
|
174
174
|
background: var(--token-accent);
|
|
175
175
|
border-radius: var(--radius-full);
|
|
176
176
|
font-variant-numeric: tabular-nums;
|
package/dist/components/stat.css
CHANGED
|
@@ -6,10 +6,10 @@
|
|
|
6
6
|
* <div class="stat-card [.stat-card--interactive] [.stat-card--horizontal]">
|
|
7
7
|
* <div class="stat-head">
|
|
8
8
|
* <span class="stat-label">用户总数</span>
|
|
9
|
-
* <span class="stat-icon [.icon--
|
|
9
|
+
* <span class="stat-icon [.icon--success|.icon--warning|.icon--error|.icon--info]>…svg…</span>
|
|
10
10
|
* </div>
|
|
11
11
|
* <div class="stat-body">
|
|
12
|
-
* <div class="stat-num [
|
|
12
|
+
* <div class="stat-num [--accent|--warning|--error|--info]">0</div>
|
|
13
13
|
* <div class="stat-delta [.up|.down|.flat]"> ← 可选趋势
|
|
14
14
|
* <svg>…arrow…</svg> +12.4%
|
|
15
15
|
* <span class="stat-period">比上周</span>
|
|
@@ -85,10 +85,10 @@
|
|
|
85
85
|
background: var(--token-accent-subtle);
|
|
86
86
|
color: var(--token-accent);
|
|
87
87
|
}
|
|
88
|
-
.stat-icon.icon--
|
|
89
|
-
.stat-icon.icon--
|
|
90
|
-
.stat-icon.icon--
|
|
91
|
-
.stat-icon.icon--info
|
|
88
|
+
.stat-icon.icon--success { background: color-mix(in srgb, var(--token-success) 14%, transparent); color: var(--token-success); }
|
|
89
|
+
.stat-icon.icon--warning { background: color-mix(in srgb, var(--token-warning) 14%, transparent); color: var(--token-warning); }
|
|
90
|
+
.stat-icon.icon--error { background: color-mix(in srgb, var(--token-error) 14%, transparent); color: var(--token-error); }
|
|
91
|
+
.stat-icon.icon--info { background: color-mix(in srgb, var(--token-info) 14%, transparent); color: var(--token-info); }
|
|
92
92
|
.stat-icon svg { width: 14px; height: 14px; }
|
|
93
93
|
|
|
94
94
|
/* ── 内容体(数字 + 趋势) ── */
|
|
@@ -99,17 +99,17 @@
|
|
|
99
99
|
}
|
|
100
100
|
|
|
101
101
|
.stat-num {
|
|
102
|
-
font-size:
|
|
102
|
+
font-size: var(--density-font-size-2xl);
|
|
103
103
|
font-weight: 700;
|
|
104
104
|
line-height: 1.2;
|
|
105
105
|
font-variant-numeric: tabular-nums lining-nums;
|
|
106
106
|
color: var(--token-text);
|
|
107
107
|
word-break: break-all;
|
|
108
108
|
}
|
|
109
|
-
.stat-num
|
|
110
|
-
.stat-num
|
|
111
|
-
.stat-num
|
|
112
|
-
.stat-num
|
|
109
|
+
.stat-num--accent { color: var(--token-accent); }
|
|
110
|
+
.stat-num--warning { color: var(--token-warning); }
|
|
111
|
+
.stat-num--error { color: var(--token-error); }
|
|
112
|
+
.stat-num--info { color: var(--token-info); }
|
|
113
113
|
|
|
114
114
|
.stat-delta {
|
|
115
115
|
display: inline-flex;
|
|
@@ -134,7 +134,7 @@
|
|
|
134
134
|
gap: 2px;
|
|
135
135
|
}
|
|
136
136
|
.stat-card--sm .stat-num { font-size: var(--density-font-size-lg); }
|
|
137
|
-
.stat-card--sm .stat-label { font-size:
|
|
137
|
+
.stat-card--sm .stat-label { font-size: var(--density-font-size-2xs); }
|
|
138
138
|
|
|
139
139
|
/* ── 横向布局(dashboard 顶栏:标签左 + 数字右) ── */
|
|
140
140
|
.stat-card--horizontal {
|
|
@@ -215,20 +215,16 @@
|
|
|
215
215
|
margin: 0 1px;
|
|
216
216
|
}
|
|
217
217
|
|
|
218
|
-
/* ──
|
|
218
|
+
/* ── 加载态骨架(脉冲 keyframes 见 base.css 的 icen-skeleton-pulse) ── */
|
|
219
219
|
.stat-card.is-loading .stat-num,
|
|
220
220
|
.stat-card.is-loading .stat-delta {
|
|
221
221
|
color: transparent;
|
|
222
222
|
background: var(--token-fill-2);
|
|
223
223
|
border-radius: var(--radius-xs);
|
|
224
|
-
animation: stat-skeleton 1.5s ease-in-out infinite;
|
|
224
|
+
animation: icen-skeleton-pulse var(--stat-skeleton-duration, 1.5s) ease-in-out infinite;
|
|
225
225
|
}
|
|
226
226
|
.stat-card.is-loading .stat-num { height: 28px; }
|
|
227
227
|
.stat-card.is-loading .stat-delta { height: 14px; width: 60%; }
|
|
228
|
-
@keyframes stat-skeleton {
|
|
229
|
-
0%, 100% { opacity: 1; }
|
|
230
|
-
50% { opacity: 0.5; }
|
|
231
|
-
}
|
|
232
228
|
@media (prefers-reduced-motion: reduce) {
|
|
233
229
|
.stat-card.is-loading .stat-num,
|
|
234
230
|
.stat-card.is-loading .stat-delta { animation: none; }
|
|
@@ -2,7 +2,8 @@
|
|
|
2
2
|
* @icen.ai/ui — Component: steps(步骤条,横向默认 / .steps--vertical 垂直)
|
|
3
3
|
*
|
|
4
4
|
* 完整契约:
|
|
5
|
-
* <ol class="steps [steps--vertical] [steps--sm|steps--lg]
|
|
5
|
+
* <ol class="steps [steps--vertical] [steps--sm|steps--lg] [steps--dots|steps--progress|steps--connected]"
|
|
6
|
+
* aria-label="进度">
|
|
6
7
|
* <li class="step [step--finish|step--process|step--wait] [.step--error]">
|
|
7
8
|
* <span class="step-line"></span> ← 横向:右半段连线;末步自动隐藏
|
|
8
9
|
* <span class="step-dot">[✓ | ! | 数字]</span>
|
|
@@ -14,7 +15,11 @@
|
|
|
14
15
|
* </ol>
|
|
15
16
|
*
|
|
16
17
|
* 四态:finish / process / wait / error(错误用 error 色 dot + 描边)。
|
|
17
|
-
*
|
|
18
|
+
* 变体与增强(正文下半段):--dots 纯点紧凑 / --progress 步骤间填充进度线 / --connected 虚线连接;
|
|
19
|
+
* dot 内可放 svg.step-dot-icon;step-desc 旁可加 .step-extra 富化描述;
|
|
20
|
+
* 可点击步骤标 .step--clickable(与 controls.ts initSteps 的 JSDoc 同口径)。
|
|
21
|
+
* 点击 .step[role=button] 由 behaviors/controls.ts 的 initSteps() 接线(激活态位移 +
|
|
22
|
+
* icen:step-change);跳转业务仍由使用方监听事件实现。
|
|
18
23
|
*/
|
|
19
24
|
|
|
20
25
|
.steps {
|
|
@@ -61,7 +66,7 @@
|
|
|
61
66
|
}
|
|
62
67
|
.step--finish .step-dot {
|
|
63
68
|
background: var(--token-accent);
|
|
64
|
-
color: var(--token-on-accent
|
|
69
|
+
color: var(--token-on-accent);
|
|
65
70
|
}
|
|
66
71
|
.step--process .step-dot {
|
|
67
72
|
background: var(--token-accent-subtle);
|
|
@@ -141,7 +146,9 @@
|
|
|
141
146
|
padding: 0;
|
|
142
147
|
font-size: 0;
|
|
143
148
|
}
|
|
144
|
-
|
|
149
|
+
/* 线 top = dot 高度一半:默认 32→16 / sm 24→12 / lg 40→20 / dots 10→5;
|
|
150
|
+
本块位于尺寸变体之后,同等特异性下靠源顺序生效,dots 与 --sm/--lg 叠加时以 5px 为准 */
|
|
151
|
+
.steps--dots .step-line { top: 5px; }
|
|
145
152
|
.steps--dots .step-title,
|
|
146
153
|
.steps--dots .step-desc { display: none; }
|
|
147
154
|
.steps--dots .step { flex: none; }
|
|
@@ -152,7 +159,7 @@
|
|
|
152
159
|
width: 16px;
|
|
153
160
|
height: 16px;
|
|
154
161
|
}
|
|
155
|
-
.step--finish .step-dot-icon { color: var(--token-on-accent
|
|
162
|
+
.step--finish .step-dot-icon { color: var(--token-on-accent); }
|
|
156
163
|
.step--process .step-dot-icon { color: var(--token-accent); }
|
|
157
164
|
.step--wait .step-dot-icon { color: var(--token-text-faint); }
|
|
158
165
|
.step--error .step-dot-icon { color: var(--token-error); }
|
|
@@ -171,8 +178,11 @@
|
|
|
171
178
|
}
|
|
172
179
|
|
|
173
180
|
/* ── 进度条变体(步骤间的填充进度,非离散连线) ── */
|
|
181
|
+
/* 高度 1px→3px 时线只向下扩张 2px,整体上移 1px 使线心与 1px 基线居中一致;
|
|
182
|
+
用 translateY 而非改 top,可同时适配 --sm(12px)/--lg(20px) 的不同基线 */
|
|
174
183
|
.steps--progress .step-line {
|
|
175
184
|
height: 3px;
|
|
185
|
+
transform: translateY(-1px);
|
|
176
186
|
border-radius: var(--radius-full);
|
|
177
187
|
background: var(--token-fill-2);
|
|
178
188
|
overflow: hidden;
|
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
/*
|
|
2
2
|
* @icen.ai/ui — Component: switch / checkbox / radio(开关 / 勾选 / 单选行)
|
|
3
|
-
*
|
|
3
|
+
* 状态组件:状态全走 aria-checked / .is-selected;交互由 behaviors/controls.ts 的
|
|
4
|
+
* initSwitch() 接线(点击 / Space / Enter 翻转并派 icen:switch-change / icen:check-change),
|
|
5
|
+
* 不接线时亦可由使用方自行驱动状态。
|
|
4
6
|
*
|
|
5
7
|
* 完整契约:
|
|
6
8
|
* <button class="switch [--sm|--lg]" role="switch" aria-checked="true|false" [disabled]>
|
|
@@ -59,8 +61,8 @@
|
|
|
59
61
|
width: var(--switch-thumb);
|
|
60
62
|
height: var(--switch-thumb);
|
|
61
63
|
border-radius: var(--radius-full);
|
|
62
|
-
background: var(--token-on-accent
|
|
63
|
-
box-shadow: 0 1px 2px
|
|
64
|
+
background: var(--token-on-accent);
|
|
65
|
+
box-shadow: 0 1px 2px color-mix(in srgb, var(--token-text) 15%, transparent);
|
|
64
66
|
transition: transform var(--icen-tx-bounce);
|
|
65
67
|
}
|
|
66
68
|
.switch[aria-checked='true'] .switch-thumb {
|
|
@@ -71,10 +73,6 @@
|
|
|
71
73
|
.switch--sm { --switch-w: 36px; --switch-h: 20px; --switch-thumb: 16px; }
|
|
72
74
|
.switch--lg { --switch-w: 56px; --switch-h: 28px; --switch-thumb: 24px; }
|
|
73
75
|
|
|
74
|
-
@media (prefers-reduced-motion: reduce) {
|
|
75
|
-
.switch-thumb { transition: none; }
|
|
76
|
-
}
|
|
77
|
-
|
|
78
76
|
/* ── 勾选框(✓ 与半选横条均 ::before 自绘) ── */
|
|
79
77
|
.checkbox {
|
|
80
78
|
--checkbox-size: 16px;
|
|
@@ -104,7 +102,7 @@
|
|
|
104
102
|
.checkbox[aria-checked='mixed'] {
|
|
105
103
|
background: var(--token-accent);
|
|
106
104
|
border-color: var(--token-accent);
|
|
107
|
-
color: var(--token-on-accent
|
|
105
|
+
color: var(--token-on-accent);
|
|
108
106
|
}
|
|
109
107
|
.checkbox::before {
|
|
110
108
|
content: '';
|
|
@@ -224,7 +222,7 @@
|
|
|
224
222
|
display: flex;
|
|
225
223
|
align-items: center;
|
|
226
224
|
justify-content: center;
|
|
227
|
-
font-size:
|
|
225
|
+
font-size: var(--density-font-size-2xs);
|
|
228
226
|
font-weight: 700;
|
|
229
227
|
color: transparent;
|
|
230
228
|
}
|
|
@@ -234,9 +232,9 @@
|
|
|
234
232
|
left: 6px;
|
|
235
233
|
top: 50%;
|
|
236
234
|
transform: translateY(-50%);
|
|
237
|
-
font-size:
|
|
235
|
+
font-size: var(--density-font-size-2xs);
|
|
238
236
|
font-weight: 700;
|
|
239
|
-
color: var(--token-on-accent
|
|
237
|
+
color: var(--token-on-accent);
|
|
240
238
|
}
|
|
241
239
|
.switch--text[aria-checked='false']::before {
|
|
242
240
|
content: 'OFF';
|
|
@@ -244,7 +242,7 @@
|
|
|
244
242
|
right: 6px;
|
|
245
243
|
top: 50%;
|
|
246
244
|
transform: translateY(-50%);
|
|
247
|
-
font-size:
|
|
245
|
+
font-size: var(--density-font-size-2xs);
|
|
248
246
|
font-weight: 700;
|
|
249
247
|
color: var(--token-text-faint);
|
|
250
248
|
}
|
|
@@ -304,7 +302,7 @@
|
|
|
304
302
|
background-color var(--icen-tx-fast);
|
|
305
303
|
}
|
|
306
304
|
.radio-card:hover {
|
|
307
|
-
border-color: var(--
|
|
305
|
+
border-color: var(--icen-hover-border);
|
|
308
306
|
}
|
|
309
307
|
.radio-card-head {
|
|
310
308
|
display: flex;
|