@icen.ai/ui 0.5.0 → 0.8.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 (138) hide show
  1. package/AGENTS.md +256 -0
  2. package/README.md +47 -13
  3. package/dist/base.css +31 -4
  4. package/dist/behaviors/accordion.d.mts +4 -0
  5. package/dist/behaviors/accordion.mjs +4 -3
  6. package/dist/behaviors/ai-chat.d.mts +57 -0
  7. package/dist/behaviors/ai-chat.mjs +557 -0
  8. package/dist/behaviors/ai-composer.d.mts +112 -0
  9. package/dist/behaviors/ai-composer.mjs +2032 -0
  10. package/dist/behaviors/ai-core.d.mts +151 -0
  11. package/dist/behaviors/ai-core.mjs +491 -0
  12. package/dist/behaviors/ai-diff.d.mts +53 -0
  13. package/dist/behaviors/ai-diff.mjs +282 -0
  14. package/dist/behaviors/ai-panel.d.mts +98 -0
  15. package/dist/behaviors/ai-panel.mjs +1012 -0
  16. package/dist/behaviors/ai-provider.d.mts +198 -0
  17. package/dist/behaviors/ai-provider.mjs +1055 -0
  18. package/dist/behaviors/ai-tool.d.mts +18 -0
  19. package/dist/behaviors/ai-tool.mjs +2125 -0
  20. package/dist/behaviors/ai-tools.d.mts +81 -0
  21. package/dist/behaviors/ai-tools.mjs +1658 -0
  22. package/dist/behaviors/back-top.d.mts +20 -0
  23. package/dist/behaviors/back-top.mjs +49 -32
  24. package/dist/behaviors/carousel.d.mts +4 -0
  25. package/dist/behaviors/carousel.mjs +34 -16
  26. package/dist/behaviors/charts.d.mts +250 -0
  27. package/dist/behaviors/charts.mjs +1301 -448
  28. package/dist/behaviors/command-palette.d.mts +8 -0
  29. package/dist/behaviors/command-palette.mjs +24 -12
  30. package/dist/behaviors/context-menu.d.mts +36 -0
  31. package/dist/behaviors/context-menu.mjs +6 -2
  32. package/dist/behaviors/copy.d.mts +4 -0
  33. package/dist/behaviors/copy.mjs +7 -6
  34. package/dist/behaviors/datatable.d.mts +78 -0
  35. package/dist/behaviors/datatable.mjs +54 -11
  36. package/dist/behaviors/date-picker.d.mts +4 -0
  37. package/dist/behaviors/date-picker.mjs +104 -36
  38. package/dist/behaviors/dropdown.d.mts +4 -0
  39. package/dist/behaviors/dropdown.mjs +7 -3
  40. package/dist/behaviors/input.d.mts +4 -0
  41. package/dist/behaviors/input.mjs +29 -22
  42. package/dist/behaviors/modal.d.mts +11 -0
  43. package/dist/behaviors/modal.mjs +11 -6
  44. package/dist/behaviors/nav.d.mts +7 -0
  45. package/dist/behaviors/nav.mjs +25 -9
  46. package/dist/behaviors/notification.d.mts +172 -0
  47. package/dist/behaviors/notification.mjs +243 -89
  48. package/dist/behaviors/popover.d.mts +46 -0
  49. package/dist/behaviors/popover.mjs +2 -1
  50. package/dist/behaviors/select.d.mts +4 -0
  51. package/dist/behaviors/select.mjs +131 -26
  52. package/dist/behaviors/sidebar.d.mts +4 -0
  53. package/dist/behaviors/sidebar.mjs +4 -3
  54. package/dist/behaviors/slider.d.mts +4 -0
  55. package/dist/behaviors/slider.mjs +4 -3
  56. package/dist/behaviors/split-pane.d.mts +4 -0
  57. package/dist/behaviors/split-pane.mjs +13 -13
  58. package/dist/behaviors/tabs.d.mts +8 -0
  59. package/dist/behaviors/tabs.mjs +44 -19
  60. package/dist/behaviors/tag-input.d.mts +4 -0
  61. package/dist/behaviors/tag-input.mjs +12 -3
  62. package/dist/behaviors/theme.d.mts +25 -0
  63. package/dist/behaviors/theme.mjs +3 -1
  64. package/dist/behaviors/toast.d.mts +26 -0
  65. package/dist/behaviors/toast.mjs +24 -18
  66. package/dist/behaviors/tree.d.mts +4 -0
  67. package/dist/behaviors/tree.mjs +4 -3
  68. package/dist/behaviors/upload.d.mts +4 -0
  69. package/dist/behaviors/upload.mjs +63 -26
  70. package/dist/components/ai-chat.css +1037 -0
  71. package/dist/components/ai-chat.mjs +3 -0
  72. package/dist/components/ai-composer.mjs +3 -0
  73. package/dist/components/ai-context.mjs +2 -0
  74. package/dist/components/ai-diff.css +311 -0
  75. package/dist/components/ai-diff.mjs +3 -0
  76. package/dist/components/ai-files.mjs +3 -0
  77. package/dist/components/ai-message.mjs +3 -0
  78. package/dist/components/ai-panel.css +682 -0
  79. package/dist/components/ai-reasoning.mjs +3 -0
  80. package/dist/components/ai-subagent.mjs +2 -0
  81. package/dist/components/ai-todo.mjs +2 -0
  82. package/dist/components/ai-tool-call.mjs +2 -0
  83. package/dist/components/ai-tool.css +532 -0
  84. package/dist/components/ai-usage.mjs +3 -0
  85. package/dist/components/badge.css +4 -8
  86. package/dist/components/breadcrumb.css +1 -5
  87. package/dist/components/btn.css +4 -7
  88. package/dist/components/card.css +3 -6
  89. package/dist/components/chart-bar.css +10 -0
  90. package/dist/components/chart-calendar.mjs +5 -0
  91. package/dist/components/chart-gauge.css +1 -1
  92. package/dist/components/chart-heatmap.css +40 -0
  93. package/dist/components/chart-scatter.css +24 -0
  94. package/dist/components/chart-scatter.mjs +4 -0
  95. package/dist/components/charts.css +86 -1
  96. package/dist/components/charts.mjs +1 -0
  97. package/dist/components/command-palette.css +2 -2
  98. package/dist/components/content.css +8 -9
  99. package/dist/components/copy.css +8 -8
  100. package/dist/components/datatable.css +4 -8
  101. package/dist/components/date-picker.css +3 -7
  102. package/dist/components/empty.css +0 -4
  103. package/dist/components/feedback.css +10 -17
  104. package/dist/components/form.css +13 -14
  105. package/dist/components/input.css +2 -2
  106. package/dist/components/layout.css +36 -36
  107. package/dist/components/media.css +12 -8
  108. package/dist/components/menu.css +2 -2
  109. package/dist/components/modal.css +1 -1
  110. package/dist/components/nav.css +11 -6
  111. package/dist/components/notification.css +28 -28
  112. package/dist/components/pagination.css +1 -1
  113. package/dist/components/panel.css +16 -16
  114. package/dist/components/pill.css +15 -15
  115. package/dist/components/segmented.css +5 -5
  116. package/dist/components/segmented.mjs +1 -0
  117. package/dist/components/select.css +12 -20
  118. package/dist/components/sidebar.css +1 -1
  119. package/dist/components/split-pane.css +0 -1
  120. package/dist/components/stat.css +14 -18
  121. package/dist/components/steps.css +2 -2
  122. package/dist/components/switch.css +8 -12
  123. package/dist/components/table.css +46 -47
  124. package/dist/components/tabs.css +35 -46
  125. package/dist/components/tag-input.css +4 -4
  126. package/dist/components/toast.css +16 -13
  127. package/dist/components/tooltip.css +2 -2
  128. package/dist/index.d.mts +37 -0
  129. package/dist/index.mjs +7890 -1199
  130. package/dist/registry.json +113 -4
  131. package/dist/retro-effects.css +21 -17
  132. package/dist/tokens/colors.css +4 -1
  133. package/dist/tokens/retro-effects.css +21 -17
  134. package/dist/tokens/style-profiles.css +21 -0
  135. package/dist/tokens.css +25 -1
  136. package/dist/ui.css +3168 -433
  137. package/docs/spec/ai-native.md +659 -0
  138. package/package.json +15 -5
@@ -72,7 +72,7 @@
72
72
  .segmented-item.is-active,
73
73
  .segmented-item[aria-checked='true'] {
74
74
  background: var(--token-accent);
75
- color: var(--token-on-accent, #fff);
75
+ color: var(--token-on-accent);
76
76
  box-shadow: var(--token-shadow-elevated);
77
77
  }
78
78
  .segmented-item:disabled,
@@ -130,7 +130,7 @@
130
130
  .toggle-item.is-active,
131
131
  .toggle-item[aria-checked='true'] {
132
132
  background: var(--token-accent);
133
- color: var(--token-on-accent, #fff);
133
+ color: var(--token-on-accent);
134
134
  box-shadow: var(--token-shadow-card);
135
135
  }
136
136
  .toggle-item:disabled,
@@ -181,7 +181,7 @@
181
181
  }
182
182
  .stepper-btn:focus-visible {
183
183
  outline: none;
184
- box-shadow: inset 0 0 0 2px color-mix(in srgb, var(--token-accent) 50%, transparent);
184
+ box-shadow: var(--icen-ring-inset);
185
185
  }
186
186
  .stepper-btn:disabled,
187
187
  .stepper-btn[aria-disabled='true'] {
@@ -225,7 +225,7 @@
225
225
  height: 48px;
226
226
  padding: 0;
227
227
  text-align: center;
228
- font-size: 18px;
228
+ font-size: var(--density-font-size-xl);
229
229
  font-weight: 600;
230
230
  font-family: var(--font-mono);
231
231
  color: var(--token-text);
@@ -254,7 +254,7 @@
254
254
  cursor: not-allowed;
255
255
  }
256
256
  .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: 22px; }
257
+ .otp--lg .otp-cell { width: 48px; height: 56px; font-size: var(--density-font-size-2xl); }
258
258
 
259
259
  @media (prefers-reduced-motion: reduce) {
260
260
  .segmented-item, .toggle-item, .stepper-btn, .stepper, .otp-cell { transition: none; }
@@ -1,2 +1,3 @@
1
1
  // @icen.ai/ui — kit: segmented(CSS + behavior 一行入口;构建产物,勿手改)
2
2
  import './segmented.css';
3
+ export { initInput } from '../behaviors/input.mjs';
@@ -26,7 +26,8 @@
26
26
  * </div>
27
27
  *
28
28
  * behavior 维护:
29
- * - .select.is-open ↔ aria-expanded;panel [hidden] 切换;ESC/外部点击关闭
29
+ * - .select.is-open ↔ aria-expanded;panel portal 到 body(inline left/top/width/max-height,
30
+ * 带 data-side="top|bottom";多选时带 data-select-multiple);ESC/外部点击关闭
30
31
  * - 选项 .is-focused 跟随键盘箭头;Enter 选中 → 写回 .select-value / .is-selected
31
32
  * - data-select-search:面板顶部自动插入搜索框,实时过滤(含 data-keywords),空分组自动隐藏
32
33
  * - data-select-multiple:点击切选不关面板,trigger 显示计数,hidden input 同步逗号分隔值
@@ -35,7 +36,6 @@
35
36
  .select {
36
37
  position: relative;
37
38
  width: 100%;
38
- isolation: isolate; /* panel 不被后面兄弟节点的层叠遮挡 */
39
39
  }
40
40
 
41
41
  .select-trigger {
@@ -105,12 +105,11 @@
105
105
  }
106
106
  .select.is-open .select-chevron { transform: rotate(180deg); }
107
107
 
108
+ /* 面板由 behavior portal 到 body:left/top/width/max-height 由 JS 按 trigger rect inline 写入;
109
+ data-side="top|bottom" 标记翻侧方向;多选时 panel 带 data-select-multiple 属性。 */
108
110
  .select-panel {
109
111
  position: absolute;
110
- top: calc(100% + 4px);
111
- left: 0;
112
- min-width: 100%;
113
- max-height: 240px;
112
+ z-index: var(--z-popover);
114
113
  overflow-y: auto;
115
114
  overscroll-behavior: contain;
116
115
  padding: 4px;
@@ -118,17 +117,10 @@
118
117
  border: 1px solid var(--token-outline);
119
118
  border-radius: var(--radius-md);
120
119
  box-shadow: var(--token-shadow-overlay);
121
- z-index: var(--z-popover);
122
120
  transform-origin: top center;
123
- animation: select-panel-in var(--icen-tx-fast);
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; }
121
+ animation: icen-pop-in var(--icen-tx-fast);
131
122
  }
123
+ .select-panel[data-side='top'] { transform-origin: bottom center; }
132
124
 
133
125
  /* 选项 */
134
126
  .select-option {
@@ -230,7 +222,7 @@
230
222
  border-radius: var(--radius-xs);
231
223
  background: transparent;
232
224
  color: var(--token-text-faint);
233
- font-size: 15px;
225
+ font-size: var(--density-font-size-lg);
234
226
  line-height: 1;
235
227
  cursor: pointer;
236
228
  transition: color var(--icen-tx-fast), background-color var(--icen-tx-fast);
@@ -249,8 +241,8 @@
249
241
  flex-wrap: wrap;
250
242
  }
251
243
 
252
- /* 多选项 checkbox 指示器(选项左侧) */
253
- .select[data-select-multiple] .select-option::before {
244
+ /* 多选项 checkbox 指示器(选项左侧;panel portal 到 body,属性在 panel 上) */
245
+ .select-panel[data-select-multiple] .select-option::before {
254
246
  content: '';
255
247
  width: 14px;
256
248
  height: 14px;
@@ -259,11 +251,11 @@
259
251
  border-radius: var(--radius-xs);
260
252
  transition: background-color var(--icen-tx-fast), border-color var(--icen-tx-fast);
261
253
  }
262
- .select[data-select-multiple] .select-option.is-selected::before {
254
+ .select-panel[data-select-multiple] .select-option.is-selected::before {
263
255
  background: var(--token-accent);
264
256
  border-color: var(--token-accent);
265
257
  }
266
- .select[data-select-multiple] .select-option.is-selected::after {
258
+ .select-panel[data-select-multiple] .select-option.is-selected::after {
267
259
  content: '✓';
268
260
  margin-left: auto;
269
261
  }
@@ -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, #fff);
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;
@@ -82,7 +82,6 @@
82
82
  }
83
83
  .split-pane--vertical .split-pane-first {
84
84
  flex: 0 0 var(--split, 50%);
85
- flex-basis: var(--split, 50%);
86
85
  min-height: 0;
87
86
  }
88
87
  .split-pane--vertical .split-pane-second {
@@ -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--ok|.icon--warn|.icon--bad|.icon--info]>…svg…</span>
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 [.accent|.warn|.bad|.info]">0</div>
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--ok { background: color-mix(in srgb, var(--token-success) 14%, transparent); color: var(--token-success); }
89
- .stat-icon.icon--warn { background: color-mix(in srgb, var(--token-warning) 14%, transparent); color: var(--token-warning); }
90
- .stat-icon.icon--bad { 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); }
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: 24px;
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.accent { color: var(--token-accent); }
110
- .stat-num.warn { color: var(--token-warning); }
111
- .stat-num.bad { color: var(--token-error); }
112
- .stat-num.info { color: var(--token-info); }
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: 10px; }
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; }
@@ -61,7 +61,7 @@
61
61
  }
62
62
  .step--finish .step-dot {
63
63
  background: var(--token-accent);
64
- color: var(--token-on-accent, #fff);
64
+ color: var(--token-on-accent);
65
65
  }
66
66
  .step--process .step-dot {
67
67
  background: var(--token-accent-subtle);
@@ -152,7 +152,7 @@
152
152
  width: 16px;
153
153
  height: 16px;
154
154
  }
155
- .step--finish .step-dot-icon { color: var(--token-on-accent, #fff); }
155
+ .step--finish .step-dot-icon { color: var(--token-on-accent); }
156
156
  .step--process .step-dot-icon { color: var(--token-accent); }
157
157
  .step--wait .step-dot-icon { color: var(--token-text-faint); }
158
158
  .step--error .step-dot-icon { color: var(--token-error); }
@@ -59,8 +59,8 @@
59
59
  width: var(--switch-thumb);
60
60
  height: var(--switch-thumb);
61
61
  border-radius: var(--radius-full);
62
- background: var(--token-on-accent, #fff);
63
- box-shadow: 0 1px 2px rgba(0, 0, 0, 0.15);
62
+ background: var(--token-on-accent);
63
+ box-shadow: 0 1px 2px color-mix(in srgb, var(--token-text) 15%, transparent);
64
64
  transition: transform var(--icen-tx-bounce);
65
65
  }
66
66
  .switch[aria-checked='true'] .switch-thumb {
@@ -71,10 +71,6 @@
71
71
  .switch--sm { --switch-w: 36px; --switch-h: 20px; --switch-thumb: 16px; }
72
72
  .switch--lg { --switch-w: 56px; --switch-h: 28px; --switch-thumb: 24px; }
73
73
 
74
- @media (prefers-reduced-motion: reduce) {
75
- .switch-thumb { transition: none; }
76
- }
77
-
78
74
  /* ── 勾选框(✓ 与半选横条均 ::before 自绘) ── */
79
75
  .checkbox {
80
76
  --checkbox-size: 16px;
@@ -104,7 +100,7 @@
104
100
  .checkbox[aria-checked='mixed'] {
105
101
  background: var(--token-accent);
106
102
  border-color: var(--token-accent);
107
- color: var(--token-on-accent, #fff);
103
+ color: var(--token-on-accent);
108
104
  }
109
105
  .checkbox::before {
110
106
  content: '';
@@ -224,7 +220,7 @@
224
220
  display: flex;
225
221
  align-items: center;
226
222
  justify-content: center;
227
- font-size: 9px;
223
+ font-size: var(--density-font-size-2xs);
228
224
  font-weight: 700;
229
225
  color: transparent;
230
226
  }
@@ -234,9 +230,9 @@
234
230
  left: 6px;
235
231
  top: 50%;
236
232
  transform: translateY(-50%);
237
- font-size: 9px;
233
+ font-size: var(--density-font-size-2xs);
238
234
  font-weight: 700;
239
- color: var(--token-on-accent, #fff);
235
+ color: var(--token-on-accent);
240
236
  }
241
237
  .switch--text[aria-checked='false']::before {
242
238
  content: 'OFF';
@@ -244,7 +240,7 @@
244
240
  right: 6px;
245
241
  top: 50%;
246
242
  transform: translateY(-50%);
247
- font-size: 9px;
243
+ font-size: var(--density-font-size-2xs);
248
244
  font-weight: 700;
249
245
  color: var(--token-text-faint);
250
246
  }
@@ -304,7 +300,7 @@
304
300
  background-color var(--icen-tx-fast);
305
301
  }
306
302
  .radio-card:hover {
307
- border-color: var(--token-hover-border, color-mix(in srgb, var(--token-accent) 30%, transparent));
303
+ border-color: var(--icen-hover-border);
308
304
  }
309
305
  .radio-card-head {
310
306
  display: flex;
@@ -3,7 +3,7 @@
3
3
  *
4
4
  * 完整契约:
5
5
  * <div class="table-wrap [table-wrap--bordered]">
6
- * <table class="admin-table [--zebra|--compact|--dense] [--sticky-col]">
6
+ * <table class="table [--zebra|--compact|--dense] [--sticky-col]">
7
7
  * <caption class="table-caption">标题说明</caption> ← 可选
8
8
  * <thead>
9
9
  * <tr><th [colspan=rowspan] [data-sort]>列名</th>…</tr>
@@ -23,9 +23,9 @@
23
23
  * </div>
24
24
  *
25
25
  * .table-wrap:窄屏横向滚动(滚动条样式见 base.css);--bordered 加外边框。
26
- * .admin-table--zebra:斑马纹(奇数行底色)。
27
- * .admin-table--compact:紧凑(cell padding 缩小);--dense:极紧凑(行高更紧)。
28
- * .admin-table--sticky-col:首列水平粘滞(配合 td/th .col-fixed,长表横向滚动时保持可见)。
26
+ * .table--zebra:斑马纹(奇数行底色)。
27
+ * .table--compact:紧凑(cell padding 缩小);--dense:极紧凑(行高更紧)。
28
+ * .table--sticky-col:首列水平粘滞(配合 td/th .col-fixed,长表横向滚动时保持可见)。
29
29
  * .row-expand[hidden]:配合 .row-link.is-expanded 控制展开行显隐。
30
30
  */
31
31
 
@@ -38,18 +38,18 @@
38
38
  border: 1px solid var(--token-line-soft);
39
39
  }
40
40
 
41
- .admin-table {
41
+ .table {
42
42
  width: 100%;
43
43
  border-collapse: collapse;
44
44
  font-size: var(--density-font-size-md);
45
45
  font-variant-numeric: tabular-nums;
46
46
  }
47
- .admin-table th,
48
- .admin-table td {
47
+ .table th,
48
+ .table td {
49
49
  padding: var(--density-space-sm) calc(var(--density-space-md) + 2px);
50
50
  text-align: left;
51
51
  }
52
- .admin-table th {
52
+ .table th {
53
53
  font-weight: 600;
54
54
  font-size: var(--density-font-size-xs);
55
55
  letter-spacing: 0.05em;
@@ -60,27 +60,27 @@
60
60
  background: var(--token-bg-soft);
61
61
  position: sticky;
62
62
  top: 0;
63
- z-index: 1;
63
+ z-index: var(--z-raised);
64
64
  }
65
- .admin-table td {
65
+ .table td {
66
66
  border-bottom: 1px solid var(--token-line-soft);
67
67
  vertical-align: middle;
68
68
  color: var(--token-text);
69
69
  }
70
- .admin-table tbody tr:last-child td { border-bottom: 0; }
71
- .admin-table tbody tr {
70
+ .table tbody tr:last-child td { border-bottom: 0; }
71
+ .table tbody tr {
72
72
  transition: background-color var(--icen-tx-fast);
73
73
  }
74
- .admin-table tbody tr:hover {
74
+ .table tbody tr:hover {
75
75
  background: var(--token-surface-strong);
76
76
  }
77
- .admin-table tbody tr.row-link {
77
+ .table tbody tr.row-link {
78
78
  cursor: pointer;
79
79
  }
80
- .admin-table tbody tr.is-selected {
80
+ .table tbody tr.is-selected {
81
81
  background: var(--token-accent-subtle);
82
82
  }
83
- .admin-table tfoot td {
83
+ .table tfoot td {
84
84
  border-top: 1px solid var(--token-line);
85
85
  border-bottom: 0;
86
86
  font-weight: 500;
@@ -88,51 +88,50 @@
88
88
  }
89
89
 
90
90
  /* 紧凑变体 */
91
- .admin-table--compact th,
92
- .admin-table--compact td {
91
+ .table--compact th,
92
+ .table--compact td {
93
93
  padding: var(--density-space-xs) var(--density-space-sm);
94
94
  }
95
- .admin-table--dense th,
96
- .admin-table--dense td {
95
+ .table--dense th,
96
+ .table--dense td {
97
97
  padding: 4px var(--density-space-xs);
98
98
  font-size: var(--density-font-size-sm);
99
99
  }
100
100
 
101
101
  /* 右对齐数字列 */
102
- .admin-table td.num {
102
+ .table td.num {
103
103
  text-align: right;
104
104
  font-variant-numeric: tabular-nums lining-nums;
105
105
  }
106
106
 
107
- /* 操作列 */
108
- .admin-table .ops {
107
+ /* 操作列(.btn-sm 必伴 .btn,无需单独列) */
108
+ .table .ops {
109
109
  white-space: nowrap;
110
110
  text-align: right;
111
111
  }
112
- .admin-table .ops .btn,
113
- .admin-table .ops .btn-sm {
112
+ .table .ops .btn {
114
113
  margin-left: var(--density-space-xs);
115
114
  }
116
115
 
117
116
  /* 可排序表头(使用方 data-sort 指示) */
118
- .admin-table th[data-sort] {
117
+ .table th[data-sort] {
119
118
  cursor: pointer;
120
119
  user-select: none;
121
120
  }
122
- .admin-table th[data-sort]::after {
121
+ .table th[data-sort]::after {
123
122
  content: '↕';
124
123
  margin-left: var(--density-space-xs);
125
124
  color: var(--token-text-faint);
126
125
  opacity: 0.6;
127
126
  }
128
- .admin-table th[data-sort='asc']::after { content: '↑'; opacity: 1; color: var(--token-accent); }
129
- .admin-table th[data-sort='desc']::after { content: '↓'; opacity: 1; color: var(--token-accent); }
127
+ .table th[data-sort='asc']::after { content: '↑'; opacity: 1; color: var(--token-accent); }
128
+ .table th[data-sort='desc']::after { content: '↓'; opacity: 1; color: var(--token-accent); }
130
129
 
131
130
  /* ── 斑马纹 ── */
132
- .admin-table--zebra tbody tr:nth-child(odd) {
131
+ .table--zebra tbody tr:nth-child(odd) {
133
132
  background: color-mix(in srgb, var(--token-bg-soft) 50%, transparent);
134
133
  }
135
- .admin-table--zebra tbody tr:hover {
134
+ .table--zebra tbody tr:hover {
136
135
  background: var(--token-surface-strong);
137
136
  }
138
137
 
@@ -147,30 +146,30 @@
147
146
  }
148
147
 
149
148
  /* ── 首列粘滞(长表横向滚动时保持可见) ── */
150
- .admin-table--sticky-col th:first-child,
151
- .admin-table--sticky-col .col-fixed {
149
+ .table--sticky-col th:first-child,
150
+ .table--sticky-col .col-fixed {
152
151
  position: sticky;
153
152
  left: 0;
154
- z-index: 2;
153
+ z-index: calc(var(--z-raised) + 1);
155
154
  background: var(--token-bg-soft);
156
- box-shadow: 2px 0 4px color-mix(in srgb, var(--token-shadow-card-base, rgba(0,0,0,0.06)) 40%, transparent);
155
+ box-shadow: 2px 0 4px color-mix(in srgb, var(--token-text) 5%, transparent);
157
156
  }
158
- .admin-table--sticky-col tbody td.col-fixed {
157
+ .table--sticky-col tbody td.col-fixed {
159
158
  background: var(--token-surface);
160
159
  }
161
- .admin-table--sticky-col tbody tr:hover td.col-fixed {
160
+ .table--sticky-col tbody tr:hover td.col-fixed {
162
161
  background: var(--token-surface-strong);
163
162
  }
164
163
 
165
164
  /* ── 展开行 ── */
166
- .admin-table .row-expand > td {
165
+ .table .row-expand > td {
167
166
  padding: 0 var(--density-space-md);
168
167
  background: var(--token-bg-soft);
169
168
  border-bottom: 1px solid var(--token-line-soft);
170
169
  font-size: var(--density-font-size-sm);
171
170
  color: var(--token-text-muted);
172
171
  }
173
- .admin-table .row-expand[hidden] { display: none; }
172
+ .table .row-expand[hidden] { display: none; }
174
173
  /* 展开行的内容容器(使用方可加 padding/动画) */
175
174
  .row-expand-content {
176
175
  padding: var(--density-space-sm) 0;
@@ -182,22 +181,22 @@
182
181
  }
183
182
 
184
183
  /* ── 列宽工具类 ── */
185
- .admin-table .col-narrow { width: 80px; }
186
- .admin-table .col-wide { width: 240px; }
187
- .admin-table .col-action { width: 1%; white-space: nowrap; }
184
+ .table .col-narrow { width: 80px; }
185
+ .table .col-wide { width: 240px; }
186
+ .table .col-action { width: 1%; white-space: nowrap; }
188
187
 
189
188
  /* ── 行状态色 ── */
190
- .admin-table tbody tr.row-success { background: color-mix(in srgb, var(--token-success) 6%, transparent); }
191
- .admin-table tbody tr.row-warning { background: color-mix(in srgb, var(--token-warning) 6%, transparent); }
192
- .admin-table tbody tr.row-error { background: color-mix(in srgb, var(--token-error) 6%, transparent); }
189
+ .table tbody tr.row-success { background: color-mix(in srgb, var(--token-success) 6%, transparent); }
190
+ .table tbody tr.row-warning { background: color-mix(in srgb, var(--token-warning) 6%, transparent); }
191
+ .table tbody tr.row-error { background: color-mix(in srgb, var(--token-error) 6%, transparent); }
193
192
 
194
193
  /* ── 粘滞表头阴影提示 ── */
195
- .admin-table thead th {
194
+ .table thead th {
196
195
  box-shadow: 0 1px 0 var(--token-line);
197
196
  }
198
197
 
199
198
  /* ── 表头分组(rowspan/colspan 样式) ── */
200
- .admin-table th[rowspan] { vertical-align: bottom; }
199
+ .table th[rowspan] { vertical-align: bottom; }
201
200
 
202
201
  @media (prefers-reduced-motion: reduce) {
203
202
  .row-expand-content { animation: none; }