@xihan-ui/styles 2.0.0 → 3.0.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 (156) hide show
  1. package/CHANGELOG.md +1328 -0
  2. package/README.md +6 -1
  3. package/component-tokens.d.ts +505 -111
  4. package/components.tokens.json +34750 -26291
  5. package/css/accordion.css +39 -13
  6. package/css/alert.css +61 -3
  7. package/css/anchor.css +49 -11
  8. package/css/approval.css +124 -84
  9. package/css/avatar-group.css +1 -1
  10. package/css/avatar.css +13 -5
  11. package/css/back-top.css +63 -44
  12. package/css/badge.css +63 -13
  13. package/css/bar-code.css +1 -1
  14. package/css/breadcrumb.css +63 -4
  15. package/css/button-group.css +5 -5
  16. package/css/button.css +69 -21
  17. package/css/calendar-picker.css +27 -8
  18. package/css/calendar-range-picker.css +48 -11
  19. package/css/card.css +116 -2
  20. package/css/carousel.css +153 -48
  21. package/css/cartesian-chart.css +830 -0
  22. package/css/cascader.css +184 -70
  23. package/css/checkbox-group.css +69 -99
  24. package/css/checkbox.css +21 -54
  25. package/css/citation.css +470 -0
  26. package/css/clipboard.css +23 -66
  27. package/css/code-view.css +103 -8
  28. package/css/collapsible.css +37 -11
  29. package/css/color-field.css +18 -0
  30. package/css/color-picker.css +57 -62
  31. package/css/color-slider.css +26 -19
  32. package/css/color-swatch-picker.css +8 -6
  33. package/css/combobox.css +82 -37
  34. package/css/command.css +48 -48
  35. package/css/context-menu.css +43 -28
  36. package/css/date-field.css +23 -0
  37. package/css/date-picker.css +57 -24
  38. package/css/date-range-picker.css +301 -14
  39. package/css/description.css +17 -1
  40. package/css/descriptions.css +43 -1
  41. package/css/dialog.css +99 -43
  42. package/css/diff-view.css +101 -16
  43. package/css/download-trigger.css +46 -80
  44. package/css/drawer.css +168 -133
  45. package/css/editable.css +19 -0
  46. package/css/empty-state.css +8 -7
  47. package/css/field-array.css +36 -0
  48. package/css/field.css +17 -19
  49. package/css/fieldset.css +1 -1
  50. package/css/file-upload.css +126 -136
  51. package/css/flex.css +324 -8
  52. package/css/float-button.css +168 -41
  53. package/css/floating-panel.css +59 -27
  54. package/css/form.css +26 -20
  55. package/css/funnel-chart.css +106 -0
  56. package/css/graph-chart.css +205 -0
  57. package/css/grid-list.css +235 -0
  58. package/css/grid.css +252 -1
  59. package/css/heatmap.css +119 -36
  60. package/css/hierarchy-chart.css +298 -0
  61. package/css/hover-card.css +33 -18
  62. package/css/icon.css +100 -0
  63. package/css/image-cropper.css +34 -8
  64. package/css/image-viewer.css +169 -26
  65. package/css/image.css +23 -4
  66. package/css/infinite-scroll.css +2 -2
  67. package/css/input-group.css +13 -15
  68. package/css/json-viewer.css +55 -7
  69. package/css/kbd.css +1 -1
  70. package/css/layout.css +71 -21
  71. package/css/liquid.css +106 -0
  72. package/css/list.css +2 -2
  73. package/css/listbox.css +72 -23
  74. package/css/loading-bar.css +27 -13
  75. package/css/log.css +131 -35
  76. package/css/markdown-stream.css +1 -1
  77. package/css/marquee.css +163 -7
  78. package/css/matrix-code.css +1 -1
  79. package/css/mention.css +35 -21
  80. package/css/menu.css +40 -28
  81. package/css/menubar.css +42 -28
  82. package/css/message-feed.css +174 -53
  83. package/css/navigation-menu.css +177 -18
  84. package/css/notification.css +431 -110
  85. package/css/number-field.css +22 -0
  86. package/css/page-header.css +4 -2
  87. package/css/pagination.css +129 -29
  88. package/css/password-input.css +40 -8
  89. package/css/pie-chart.css +247 -0
  90. package/css/popconfirm.css +50 -58
  91. package/css/popover.css +55 -21
  92. package/css/progress.css +308 -10
  93. package/css/prompt-input.css +37 -1
  94. package/css/question-flow.css +104 -64
  95. package/css/radar-chart.css +233 -0
  96. package/css/radio-group.css +372 -14
  97. package/css/rating.css +25 -27
  98. package/css/reasoning.css +62 -55
  99. package/css/reset.css +1 -1
  100. package/css/resizable.css +6 -1
  101. package/css/sankey-chart.css +174 -0
  102. package/css/scroll-area.css +32 -0
  103. package/css/scrollbar.css +1 -1
  104. package/css/select.css +76 -59
  105. package/css/side-nav.css +177 -30
  106. package/css/signature-pad.css +23 -8
  107. package/css/skeleton.css +13 -14
  108. package/css/slider.css +39 -17
  109. package/css/sortable.css +38 -8
  110. package/css/sparkline.css +164 -0
  111. package/css/spinner.css +50 -22
  112. package/css/splitter.css +8 -2
  113. package/css/statistic.css +10 -0
  114. package/css/steps.css +257 -38
  115. package/css/switch.css +30 -55
  116. package/css/table.css +168 -128
  117. package/css/tabs.css +243 -31
  118. package/css/tag-group.css +65 -37
  119. package/css/tag.css +55 -14
  120. package/css/tags-input.css +40 -3
  121. package/css/text-field.css +19 -0
  122. package/css/time-field.css +20 -1
  123. package/css/time-picker.css +44 -17
  124. package/css/time-range-picker.css +45 -18
  125. package/css/timeline.css +1 -1
  126. package/css/toggle-group.css +8 -8
  127. package/css/toggle.css +6 -5
  128. package/css/tool-call.css +64 -56
  129. package/css/toolbar.css +105 -7
  130. package/css/tooltip.css +18 -7
  131. package/css/tour.css +49 -21
  132. package/css/transfer.css +104 -81
  133. package/css/tree-select.css +235 -58
  134. package/css/tree.css +240 -147
  135. package/css/truncate.css +55 -12
  136. package/css/typography.css +93 -0
  137. package/css/virtualizer.css +57 -1
  138. package/css/watermark.css +23 -0
  139. package/family/action-control.css +14 -5
  140. package/family/chart.css +480 -0
  141. package/family/check-mark.css +94 -0
  142. package/family/choice-card.css +97 -0
  143. package/family/collection-item.css +70 -27
  144. package/family/field-chrome.css +1 -12
  145. package/family/loading-ring.css +95 -0
  146. package/family/material.css +72 -0
  147. package/family/menu-choice.css +56 -0
  148. package/family/motion.css +208 -11
  149. package/family/tag-list.css +59 -0
  150. package/index.css +23363 -14091
  151. package/index.unlayered.css +23198 -13922
  152. package/package.json +20 -8
  153. package/css/gradient-text.css +0 -91
  154. package/css/icon-wrapper.css +0 -81
  155. package/css/segmented.css +0 -280
  156. package/css/toast.css +0 -499
package/css/listbox.css CHANGED
@@ -7,6 +7,8 @@
7
7
 
8
8
  @import '../family/action-control.css';
9
9
  @import '../family/collection-item.css';
10
+ @import '../family/loading-ring.css';
11
+ @import '../family/motion.css';
10
12
 
11
13
  @layer xihan.components {
12
14
  /* 皮肤在场的标记:开发模式下按 scope 探一次,取不到就说明这份皮肤没被引入。 */
@@ -16,10 +18,10 @@
16
18
 
17
19
  [data-scope='listbox'][data-part='root'] {
18
20
  /* 条目外的字形(空态 / 在途占位里作者塞的图标)按档取尺,缺省 md;条目内的字形由家族随
19
- data-xh-collection-size 下发(§6.5)。列表框自绘的状态字形(前导对号所在的标记盒与盒里的勾)不读这支:
21
+ data-xh-collection-size 下发。列表框自绘的状态字形(行尾对号所在的标记盒与盒里的勾)不读这支:
20
22
  它们是指示符,走 --xh-control-indicator-* 一族——标记盒在自己身上把 --xh-icon-size 改接到盒的尺 */
21
23
  --xh-icon-size: var(--xh-listbox-icon-size, var(--xh-glyph-size-md));
22
- /* 定高小列表的自绘条挂在根上(§6.6):根是条子的定位盒,轨道底色关掉才不会在列表右缘糊出一条灰带 */
24
+ /* 定高小列表的自绘条挂在根上:根是条子的定位盒,轨道底色关掉才不会在列表右缘糊出一条灰带 */
23
25
  --xh-scrollbar-track-bg: transparent;
24
26
 
25
27
  /* 尺寸档只换这四个私有槽,条目、分组标题与空态占位都从 root 继承它们,
@@ -117,7 +119,7 @@
117
119
  /* 手写结构按真正的条目判断,空白文本与分组标题都不算候选。
118
120
  只排除 content 内部的 hidden 祖先;外层浮层退场时不改变本列表的几何。
119
121
  禁用条目仍是有效内容,不参与此处排除。 */
120
- [data-scope='listbox'][data-part='content']:not(:has(
122
+ [data-scope='listbox'][data-part='content']:not([data-xh-virtualized]):not(:has(
121
123
  [data-scope='listbox'][data-part='item']:not([hidden]):not([data-scope='listbox'][data-part='content'] [hidden] *)
122
124
  )),
123
125
  [data-scope='listbox'][data-part='group']:not(:has(
@@ -164,11 +166,18 @@
164
166
  display: block;
165
167
  padding-block: var(--xh-listbox-group-label-py, var(--xh-space-1));
166
168
  padding-inline: var(--xh-listbox-group-label-px, var(--xh-_listbox-item-px));
167
- color: var(--xh-listbox-group-label-fg, var(--xh-fg-subtle));
169
+ color: var(--xh-listbox-group-label-fg, var(--xh-fg-muted));
168
170
  font-size: var(--xh-listbox-group-label-font-size, var(--xh-text-caption-size));
169
171
  font-weight: var(--xh-listbox-group-label-font-weight, var(--xh-font-weight-medium));
170
172
  line-height: var(--xh-leading-none);
171
173
  user-select: none;
174
+ transition: opacity var(--xh-motion-duration-micro) var(--xh-motion-ease-enter);
175
+ }
176
+
177
+ /* 刷新:已有选项时后台在取,保留上一帧,条目与分组标题按 micro 淡下,数据到了再淡回;在途占位此时让位。
178
+ 淡的是内容不是面:content 自己是描边面,整块淡下去边也跟着淡 */
179
+ [data-scope='listbox'][data-part='content'][aria-busy='true'] [data-scope='listbox']:is([data-part='item'], [data-part='group-label']) {
180
+ opacity: var(--xh-state-disabled-opacity);
172
181
  }
173
182
 
174
183
  [data-scope='listbox'][data-part='group-label'][hidden] {
@@ -185,7 +194,7 @@
185
194
  display: block;
186
195
  padding-block: var(--xh-listbox-empty-py, var(--xh-space-3));
187
196
  padding-inline: var(--xh-listbox-empty-px, var(--xh-_listbox-item-px));
188
- color: var(--xh-listbox-empty-fg, var(--xh-fg-subtle));
197
+ color: var(--xh-listbox-empty-fg, var(--xh-fg-muted));
189
198
  font-size: var(--xh-listbox-empty-font-size, var(--xh-_listbox-font-size));
190
199
  line-height: var(--xh-leading-none);
191
200
  text-align: center;
@@ -202,10 +211,13 @@
202
211
 
203
212
  /* 在途占位:与空态占位同一个位置、同一副观感,两者不同屏 */
204
213
  [data-scope='listbox'][data-part='loading'] {
205
- display: block;
214
+ display: flex;
215
+ align-items: center;
216
+ justify-content: center;
217
+ gap: var(--xh-_listbox-gap);
206
218
  padding-block: var(--xh-listbox-loading-py, var(--xh-space-3));
207
219
  padding-inline: var(--xh-listbox-loading-px, var(--xh-_listbox-item-px));
208
- color: var(--xh-listbox-loading-fg, var(--xh-fg-subtle));
220
+ color: var(--xh-listbox-loading-fg, var(--xh-fg-muted));
209
221
  font-size: var(--xh-listbox-loading-font-size, var(--xh-_listbox-font-size));
210
222
  line-height: var(--xh-leading-none);
211
223
  text-align: center;
@@ -215,8 +227,17 @@
215
227
  display: none;
216
228
  }
217
229
 
230
+ /* 首次加载:文案前一枚加载环,由加载环配方画(连接层投影 data-xh-loading-ring 与 data-loading),
231
+ 直径取所在尺寸档的图标档 */
232
+ [data-scope='listbox'][data-part='loading']::before {
233
+ content: '';
234
+ flex: none;
235
+ inline-size: var(--xh-icon-size, var(--xh-glyph-size-md));
236
+ block-size: var(--xh-icon-size, var(--xh-glyph-size-md));
237
+ }
238
+
218
239
  /* 取下一页的按钮:铺满一行摆在列表尾——铺满一行的独立动作条目,接 Action Control 的 row 档、
219
- ghost 形态(§9.2):宽度由容器给、高度随内容、按下只换面不缩放;盒几何、悬停 / 按下 / 禁用面、
240
+ ghost 形态:宽度由容器给、高度随内容、按下只换面不缩放;盒几何、悬停 / 按下 / 禁用面、
220
241
  焦点环与粗指针热区全由家族给,白底承载 hover 100 → pressed 200。
221
242
  这里只把使用者槽映射到桥接槽并把文案居中:它是一行里唯一的东西,靠起始缘会像一条没对齐的条目 */
222
243
  [data-scope='listbox'][data-part='load-more-trigger'] {
@@ -232,7 +253,7 @@
232
253
 
233
254
  justify-content: center;
234
255
  text-align: center;
235
- /* row 档允许换行、高度随内容,折行的文案走正文行高(§6.4) */
256
+ /* row 档允许换行、高度随内容,折行的文案走正文行高 */
236
257
  line-height: var(--xh-leading-normal);
237
258
  }
238
259
 
@@ -240,27 +261,27 @@
240
261
  display: none;
241
262
  }
242
263
 
243
- /* 条目走 Collection Item 的 page 语境(页内持久集合,§7.3):网格、尺寸档、悬停 / 高亮 / 按下面
244
- (白底承载 hover 100 → pressed 200)与选中面(品牌淡底 + 淡底前景 + 前导对号,selected+hover 20% /
245
- +pressed 28%)都由家族按 aria-selected / aria-disabled 给出;禁用面(字色降级、not-allowed、不换面)
246
- 也归家族。这里只把公开槽映射到桥接槽,不复制任何状态选择器。
247
- page 集合坐在 surface 白底上,前景走 fg-default 而不是浮层的 frosted 前景 */
264
+ /* 条目走 Collection Item 的 overlay 语境,与树选择同一种选中读法:网格、尺寸档、悬停 / 高亮 / 按下面
265
+ (白底承载 hover 100 → pressed 200)由家族给,选中不换面、不换字色,只在行尾亮对号,
266
+ 选中叠悬停 / 按下沿用同一条阶梯;禁用面(字色降级、not-allowed、不换面)也归家族。
267
+ 这里只把公开槽映射到桥接槽,不复制任何状态选择器。
268
+ 列表框坐在 surface 白底上,前景走 fg-default 而不是浮层的 frosted 前景 */
248
269
  [data-scope='listbox'][data-part='item'] {
249
270
  --xh-collection-block-padding: var(--xh-listbox-item-py, var(--xh-_listbox-item-py));
250
271
  --xh-collection-inline-padding: var(--xh-listbox-item-px, var(--xh-_listbox-item-px));
251
272
  --xh-collection-gap: var(--xh-listbox-item-gap, var(--xh-_listbox-gap));
252
273
  --xh-collection-font-size: var(--xh-listbox-item-font-size, var(--xh-_listbox-font-size));
253
- --xh-collection-radius: var(--xh-listbox-item-radius, var(--xh-shape-control));
274
+ --xh-collection-radius: var(--xh-listbox-item-radius, var(--xh-shape-inset));
254
275
  /* 作者的图标尺槽经桥接槽下发到条目,家族缺省按 data-xh-collection-size 取档 */
255
276
  --xh-collection-glyph-size: var(--xh-listbox-icon-size, var(--xh-_collection-glyph-size));
256
277
  --xh-collection-fg-rest: var(--xh-listbox-item-fg, var(--xh-fg-default));
257
278
  --xh-collection-fg-hover: var(--xh-listbox-item-fg, var(--xh-fg-default));
258
279
  --xh-collection-fg-keyboard-highlight: var(--xh-listbox-item-fg, var(--xh-fg-default));
259
280
  --xh-collection-fg-pressed: var(--xh-listbox-item-fg, var(--xh-fg-default));
260
- --xh-collection-fg-selected: var(--xh-listbox-item-fg-selected, var(--xh-fg-on-brand-subtle));
261
- --xh-collection-fg-selected-hover: var(--xh-listbox-item-fg-selected, var(--xh-fg-on-brand-subtle));
262
- --xh-collection-fg-selected-highlight: var(--xh-listbox-item-fg-selected, var(--xh-fg-on-brand-subtle));
263
- --xh-collection-fg-selected-pressed: var(--xh-listbox-item-fg-selected, var(--xh-fg-on-brand-subtle));
281
+ --xh-collection-fg-selected: var(--xh-listbox-item-fg-selected, var(--xh-listbox-item-fg, var(--xh-fg-default)));
282
+ --xh-collection-fg-selected-hover: var(--xh-listbox-item-fg-selected, var(--xh-listbox-item-fg, var(--xh-fg-default)));
283
+ --xh-collection-fg-selected-highlight: var(--xh-listbox-item-fg-selected, var(--xh-listbox-item-fg, var(--xh-fg-default)));
284
+ --xh-collection-fg-selected-pressed: var(--xh-listbox-item-fg-selected, var(--xh-listbox-item-fg, var(--xh-fg-default)));
264
285
  --xh-collection-font-weight-selected: var(--xh-listbox-item-font-weight-selected, var(--xh-font-weight-regular));
265
286
  --xh-collection-font-weight-selected-hover: var(--xh-listbox-item-font-weight-selected, var(--xh-font-weight-regular));
266
287
  --xh-collection-font-weight-selected-highlight: var(--xh-listbox-item-font-weight-selected, var(--xh-font-weight-regular));
@@ -268,7 +289,9 @@
268
289
  --xh-collection-bg-hover: var(--xh-listbox-item-bg-hover, var(--xh-bg-subtle));
269
290
  --xh-collection-bg-keyboard-highlight: var(--xh-listbox-item-bg-hover, var(--xh-bg-subtle));
270
291
  --xh-collection-bg-pressed: var(--xh-listbox-item-bg-pressed, var(--xh-bg-subtle-hover));
271
- --xh-collection-bg-selected: var(--xh-listbox-item-bg-selected, var(--xh-bg-brand-subtle));
292
+ --xh-collection-bg-selected-hover: var(--xh-listbox-item-bg-hover, var(--xh-bg-subtle));
293
+ --xh-collection-bg-selected-highlight: var(--xh-listbox-item-bg-hover, var(--xh-bg-subtle));
294
+ --xh-collection-bg-selected-pressed: var(--xh-listbox-item-bg-pressed, var(--xh-bg-subtle-hover));
272
295
  /* data-highlighted 跟的是连接层记的焦点条目(指针点选也会落焦):只换面,焦点环在 :focus-visible 下再接回 */
273
296
  --xh-collection-outline-keyboard-highlight: transparent;
274
297
  --xh-collection-outline-selected-highlight: transparent;
@@ -307,10 +330,10 @@
307
330
  text-overflow: ellipsis;
308
331
  }
309
332
 
310
- /* 勾选标记落在家族网格的 indicator 列(page 语境下前置为前导对号);显隐与颜色由家族按选中态给,
333
+ /* 勾选标记落在家族网格行尾的 indicator 列(page 与 overlay 同位);显隐与颜色由家族按选中态给,
311
334
  未选中时占位不塌,切换选中不引起行宽抖动。
312
- 盒与盒里的勾是指示符(§6.5):盒按指示符档取尺,并在自己身上把 --xh-icon-size 改接到盒的尺,皮肤画的
313
- 兜底勾与作者塞进盒里的 XhIcon 读同一把尺、与盒同边长(前导对号不是勾选格,不取 × 0.75,与 Menu 族同口径);
335
+ 盒与盒里的勾是指示符:盒按指示符档取尺,并在自己身上把 --xh-icon-size 改接到盒的尺,皮肤画的
336
+ 兜底勾与作者塞进盒里的 XhIcon 读同一把尺、与盒同边长(对号不是勾选格,不取 × 0.75,与 Menu 族同口径);
314
337
  不读家族按档下发到行的 --xh-icon-size——那支只管作者放进条目里的图标,按图标档取的 20px 比 16 / 14 的指示符档大一圈 */
315
338
  [data-scope='listbox'][data-part='item-indicator'] {
316
339
  --xh-icon-size: var(--xh-listbox-item-indicator-size, var(--xh-control-indicator-size));
@@ -338,4 +361,30 @@
338
361
  -webkit-mask: var(--xh-glyph-mark-check) center / contain no-repeat;
339
362
  mask: var(--xh-glyph-mark-check) center / contain no-repeat;
340
363
  }
364
+
365
+ @media print {
366
+ /* 打印默认丢底色,而对号是遮罩出来的一块底色:行本就不换面,丢了它选中在纸上就没了踪影 */
367
+ [data-scope='listbox'][data-part='item-indicator'] {
368
+ print-color-adjust: exact;
369
+ }
370
+ }
371
+
372
+ @media (forced-colors: active) {
373
+ /* 兜底字形是 mask 挖出来的一块底色,这一档里底色被系统换成 Canvas,字形跟着消失。
374
+ 字形退出强制换色、直接写系统色(不能取 currentColor:退出强制换色的伪元素读到的是被系统换掉之前的作者色):
375
+ 条目面上取 CanvasText;按下与没被高亮时的悬停,家族把条目涂成 Highlight,字形换 HighlightText;
376
+ 禁用取 GrayText */
377
+ [data-scope='listbox'][data-part='item-indicator']:empty::before {
378
+ forced-color-adjust: none;
379
+ background-color: CanvasText;
380
+ }
381
+
382
+ [data-scope='listbox'][data-part='item']:not([aria-disabled='true'], [data-disabled], [aria-busy='true'], [data-error]):is(:active, [data-pressed], :hover:not(:focus-visible, [data-highlighted])) [data-scope='listbox'][data-part='item-indicator']:empty::before {
383
+ background-color: HighlightText;
384
+ }
385
+
386
+ [data-scope='listbox'][data-part='item']:is([aria-disabled='true'], [data-disabled]) [data-scope='listbox'][data-part='item-indicator']:empty::before {
387
+ background-color: GrayText;
388
+ }
389
+ }
341
390
  }
@@ -40,11 +40,12 @@
40
40
  display: none;
41
41
  }
42
42
 
43
- /* 冲到 100 之后进入淡出:机器会在淡出窗口走完之前一直停在 finishing,这段过渡才有时间跑完。
44
- 窗口(machine 的 LOADING_BAR_FADE_DURATION,200ms)比过渡本身(motion-duration-exit,120ms)
45
- 宽出一截是有意的余量;两者不是同一个数,改窗口时只要保证它仍不短于过渡 */
43
+ /* 走满之后才淡出:complete 期间根节点保持不透明,进度段冲到头的平移播完,机器才进 finishing。
44
+ 满格先停一拍(延迟一个 micro)再淡:用户要看清「走完了」,一到头就开始淡读起来像中途断掉。
45
+ 机器等的是浏览器实际起播的这段过渡(含延迟),不按毫秒猜 */
46
46
  [data-scope='loading-bar'][data-part='root'][data-state='finishing'] {
47
47
  opacity: 0;
48
+ transition-delay: var(--xh-motion-duration-micro);
48
49
  }
49
50
 
50
51
  /* 背景槽。默认透明:顶部加载条通常直接压在页面顶边上,一条贯穿整屏的浅色底
@@ -57,17 +58,24 @@
57
58
  }
58
59
 
59
60
  /*
60
- * 进度段。宽度那条轴(inline-size)由连接层写进内联样式,这里绝不重复写。
61
- * 背景色不走内联:要别的颜色改 --xh-loading-bar-range 这个槽,或者换语气。
61
+ * 进度段。铺满轨道,按连接层交出的比例往行首平移、由轨道裁掉:推进只走合成,
62
+ * 不重排也不重绘;末端的亮边跟着它一起走。背景色不走内联:要别的颜色改 --xh-loading-bar-range 这个槽,或者换语气。
62
63
  *
63
64
  * 语气取装饰档 --xh-_tone-soft:那一档压在画布上够 3:1,细带才看得出来。
64
65
  * 槽位由 root 上的 data-tone 声明,继承下来。
65
66
  * 没写 data-tone 时该槽没被声明,退回原来的品牌色。
66
67
  */
67
68
  [data-scope='loading-bar'][data-part='range'] {
69
+ inline-size: 100%;
68
70
  block-size: 100%;
69
71
  background: var(--xh-loading-bar-range, var(--xh-_tone-soft, var(--xh-bg-brand)));
70
- transition: inline-size var(--xh-loading-bar-speed, var(--xh-motion-duration-enter)) var(--xh-motion-ease-continuous);
72
+ translate: calc((var(--xh-_loading-bar-value, 0) - 1) * 100%) 0;
73
+ transition: translate var(--xh-loading-bar-speed, var(--xh-motion-duration-move)) var(--xh-motion-ease-continuous);
74
+ }
75
+
76
+ /* translate 只认物理方向:RTL 下行首在右边,平移方向翻转 */
77
+ [data-scope='loading-bar'][data-part='range']:dir(rtl) {
78
+ translate: calc((1 - var(--xh-_loading-bar-value, 0)) * 100%) 0;
71
79
  }
72
80
 
73
81
  /* 渲染了亮边才把进度段变成定位面:亮边贴在它的末端 */
@@ -94,7 +102,7 @@
94
102
  );
95
103
  }
96
104
 
97
- /* 条子还没起步时亮边一起收着:0% 宽的进度段末端不该先亮出一道边 */
105
+ /* 条子还没起步时亮边一起收着:进度为 0 的末端不该先亮出一道边 */
98
106
  [data-scope='loading-bar'][data-part='peg'][data-state='idle'] {
99
107
  opacity: 0;
100
108
  }
@@ -103,19 +111,25 @@
103
111
  display: none;
104
112
  }
105
113
 
106
- /* 减少动效:宽度与淡出都立刻到位。进度本身照常推进,只是不再有过渡的过程——
107
- 一条按 200ms 一拍持续变宽的带子正是最容易引发不适的那种动效。
114
+ /* 减少动效:作者写进两个时长槽的值不作数,退回令牌——进度段的平移随几何时长立刻到位,
115
+ 收尾的淡出保留减弱档的那一小段。一条按 200ms 一拍持续推进的带子正是最容易引发不适的那种动效。
108
116
  两条规则是同一件事的两个触发条件:系统偏好与作者打的 data-motion */
109
117
  @media (prefers-reduced-motion: reduce) {
110
- [data-scope='loading-bar'][data-part='root'],
118
+ [data-scope='loading-bar'][data-part='root'] {
119
+ transition-duration: var(--xh-motion-duration-exit);
120
+ }
121
+
111
122
  [data-scope='loading-bar'][data-part='range'] {
112
- transition: none;
123
+ transition-duration: var(--xh-motion-duration-move);
113
124
  }
114
125
  }
115
126
 
116
- :where([data-motion='reduce']) [data-scope='loading-bar'][data-part='root'],
127
+ :where([data-motion='reduce']) [data-scope='loading-bar'][data-part='root'] {
128
+ transition-duration: var(--xh-motion-duration-exit);
129
+ }
130
+
117
131
  :where([data-motion='reduce']) [data-scope='loading-bar'][data-part='range'] {
118
- transition: none;
132
+ transition-duration: var(--xh-motion-duration-move);
119
133
  }
120
134
 
121
135
  @media print {
package/css/log.css CHANGED
@@ -5,25 +5,11 @@
5
5
 
6
6
  /* 定义 log 样式。 */
7
7
 
8
+ /* 共享关键帧由 family/motion.css 提供,本皮肤 @import 它,单独引入仍成立。 */
9
+ @import '../family/motion.css';
8
10
  /* 独立皮肤同时传递引入回底钮的动作控件配方;full bundle 递归去重。 */
9
11
  @import '../family/action-control.css';
10
-
11
- @layer xihan.motion {
12
- /* 关键帧写在本文件里:动画名的查找只认「文档里有没有这个名字」,
13
- 引用别处文件里的名字时那份文件不一定在场,动画会静默地整个不跑。
14
- 幅度与缩放走令牌,减弱动效时由令牌层归零 */
15
- @keyframes xh-log-button-in {
16
- from {
17
- opacity: 0;
18
- scale: var(--xh-motion-scale-enter);
19
- }
20
-
21
- to {
22
- opacity: 1;
23
- scale: 1;
24
- }
25
- }
26
- }
12
+ @import '../family/material.css';
27
13
 
28
14
  @layer xihan.components {
29
15
  /* 皮肤在场的标记:开发模式下按 scope 探一次,取不到就说明这份皮肤没被引入。 */
@@ -34,7 +20,7 @@
34
20
  /* 行高是本组件的定尺基准:视口按行数定高、每行排版,都从这一个槽位来。
35
21
  它的兜底值须与连接层内联高度里用的那份逐字一致,否则 rows 算出来的高度对不上行。 */
36
22
  [data-scope='log'][data-part='root'] {
37
- --xh-_log-line-h: var(--xh-log-line-height, 1.25rem);
23
+ --xh-_log-line-h: var(--xh-log-line-height, var(--xh-text-code-leading));
38
24
 
39
25
  /* 尺寸缺省档:不写 data-size 时的取值。三档只改这两个私有槽,
40
26
  公开槽留在读处当首选,作者在祖先上设的覆盖才赢得过档位声明。
@@ -42,7 +28,7 @@
42
28
  --xh-_log-font-size: var(--xh-text-secondary-size);
43
29
  --xh-_log-content-px: var(--xh-space-3);
44
30
 
45
- /* 一张静态内容面:--xh-border-default 描边 + surface 底 + 无影(§5.3 描边与淡底互斥),
31
+ /* 一张静态内容面:--xh-border-default 描边 + surface 底 + 无影(描边与淡底互斥),
46
32
  与 code-view / diff-view / json-viewer 同走 solid */
47
33
  position: relative;
48
34
  display: flex;
@@ -79,6 +65,26 @@
79
65
  scrollbar-gutter: stable;
80
66
  }
81
67
 
68
+ /* 接了虚拟滚动:视口只定高、不滚动,里面那层 Virtualizer 视口铺满它、由它滚;
69
+ 行放在 Virtualizer 的条目里没有 content 包裹层,等宽排版落在视口上由行继承 */
70
+ [data-scope='log'][data-part='viewport'][data-virtualized] {
71
+ display: grid;
72
+ grid-template-rows: minmax(0, 1fr);
73
+ overflow: hidden;
74
+ /* 不滚动的视口不留滚动条空道:空道由里面那层 Virtualizer 视口自己管 */
75
+ scrollbar-gutter: auto;
76
+ font-family: var(--xh-log-font, var(--xh-font-family-mono));
77
+ font-size: var(--xh-log-font-size, var(--xh-_log-font-size));
78
+ }
79
+
80
+ [data-scope='log'][data-part='viewport'][hidden] {
81
+ display: none;
82
+ }
83
+
84
+ [data-scope='log'][data-part='viewport'][data-virtualized] [data-scope='log'][data-part='line'] {
85
+ padding-inline: var(--xh-log-line-px, var(--xh-log-content-px, var(--xh-_log-content-px)));
86
+ }
87
+
82
88
  /* 取行期间指针给出忙的反馈 */
83
89
  [data-scope='log'][data-part='root'][data-loading] [data-scope='log'][data-part='viewport'] {
84
90
  cursor: progress;
@@ -121,31 +127,96 @@
121
127
  color: var(--xh-log-level-error-fg, var(--xh-fg-danger));
122
128
  }
123
129
 
130
+ /* ANSI 着色:八种颜色映射到语义令牌(红、绿、黄、蓝落在语气前景,品红、青借代码着色的关键字与字符串色,
131
+ 黑与白落在正文与次要前景),高亮色(90–97)与基础色同一档,只由 data-bright 记下。
132
+ 颜色盖过行的级别色;粗体、斜体、下划线与暗淡各自一个开关 */
133
+ [data-scope='log'][data-part='segment'][data-fg='black'] {
134
+ color: var(--xh-log-ansi-black, var(--xh-fg-default));
135
+ }
136
+
137
+ [data-scope='log'][data-part='segment'][data-fg='red'] {
138
+ color: var(--xh-log-ansi-red, var(--xh-fg-danger));
139
+ }
140
+
141
+ [data-scope='log'][data-part='segment'][data-fg='green'] {
142
+ color: var(--xh-log-ansi-green, var(--xh-fg-success));
143
+ }
144
+
145
+ [data-scope='log'][data-part='segment'][data-fg='yellow'] {
146
+ color: var(--xh-log-ansi-yellow, var(--xh-fg-warning));
147
+ }
148
+
149
+ [data-scope='log'][data-part='segment'][data-fg='blue'] {
150
+ color: var(--xh-log-ansi-blue, var(--xh-fg-info));
151
+ }
152
+
153
+ [data-scope='log'][data-part='segment'][data-fg='magenta'] {
154
+ color: var(--xh-log-ansi-magenta, var(--xh-syntax-keyword));
155
+ }
156
+
157
+ [data-scope='log'][data-part='segment'][data-fg='cyan'] {
158
+ color: var(--xh-log-ansi-cyan, var(--xh-syntax-string));
159
+ }
160
+
161
+ [data-scope='log'][data-part='segment'][data-fg='white'] {
162
+ color: var(--xh-log-ansi-white, var(--xh-fg-muted));
163
+ }
164
+
165
+ [data-scope='log'][data-part='segment'][data-bold] {
166
+ font-weight: var(--xh-log-ansi-bold-weight, var(--xh-font-weight-semibold));
167
+ }
168
+
169
+ /* 暗淡只在没指定颜色时换成次要前景:指定了颜色的那一段保留自己的颜色 */
170
+ [data-scope='log'][data-part='segment'][data-dim]:not([data-fg]) {
171
+ color: var(--xh-log-ansi-dim-fg, var(--xh-fg-subtle));
172
+ }
173
+
174
+ [data-scope='log'][data-part='segment'][data-italic] {
175
+ font-style: italic;
176
+ }
177
+
178
+ [data-scope='log'][data-part='segment'][data-underline] {
179
+ text-decoration: underline;
180
+ }
181
+
124
182
  /* 回到底部:浮在视口右下角,收起时不卸载只隐藏。盒型、悬停 / 按下面与缩放由 Action Control 的
125
183
  floating 档给(circle 正方盒、ghost 形态:白底承载 hover 100 → pressed 200);材质随角落浮钮族走
126
- frosted 四件套(底 + 边 + 影 + 磨砂,§8),这里只把使用者槽映射到桥接槽:
184
+ frosted 四件套(底 + 边 + 影 + 磨砂),这里只把使用者槽映射到桥接槽:
127
185
  字形按 xs 档取 --xh-_action-profile-glyph-size(16px),与 back-top 同一把尺 */
128
186
  [data-scope='log'][data-part='scroll-to-end-trigger'] {
129
- --xh-_log-scroll-to-end-trigger-shadow: var(--xh-log-scroll-to-end-trigger-shadow, var(--xh-material-frosted-shadow));
187
+ /* 面走材质家族配方(family/material.css):frosted 档的底、交互阶梯、描边、投影、1px 顶光与背景滤镜,
188
+ liquid 档由配方换成液态面;这里把使用者槽接到 Action Control 的桥接槽 */
189
+ --xh-action-bg-rest: var(--xh-log-scroll-to-end-trigger-bg, var(--xh-_material-bg));
190
+ --xh-action-bg-hover: var(--xh-log-scroll-to-end-trigger-bg-hover, var(--xh-_material-bg-hover));
191
+ --xh-action-bg-pressed: var(--xh-_material-bg-pressed);
192
+ --xh-action-bg-focus-visible: var(--xh-log-scroll-to-end-trigger-bg, var(--xh-_material-bg-focus));
193
+ --xh-action-bg-disabled: var(--xh-log-scroll-to-end-trigger-bg, var(--xh-_material-bg));
194
+ --xh-action-fg-rest: var(--xh-log-scroll-to-end-trigger-fg, var(--xh-_material-fg));
195
+ --xh-action-fg-hover: var(--xh-log-scroll-to-end-trigger-fg, var(--xh-_material-fg));
196
+ --xh-action-fg-pressed: var(--xh-log-scroll-to-end-trigger-fg, var(--xh-_material-fg));
197
+ --xh-action-fg-focus-visible: var(--xh-log-scroll-to-end-trigger-fg, var(--xh-_material-fg));
198
+ --xh-action-border-rest: var(--xh-log-scroll-to-end-trigger-border, var(--xh-_material-border));
199
+ --xh-action-border-hover: var(--xh-log-scroll-to-end-trigger-border, var(--xh-_material-border));
200
+ --xh-action-border-pressed: var(--xh-log-scroll-to-end-trigger-border, var(--xh-_material-border));
201
+ --xh-action-border-focus-visible: var(--xh-log-scroll-to-end-trigger-border, var(--xh-_material-border));
202
+ --xh-action-border-disabled: var(--xh-log-scroll-to-end-trigger-border, var(--xh-_material-border));
203
+ --xh-action-shadow-rest: var(--xh-log-scroll-to-end-trigger-shadow, var(--xh-_material-shadow));
204
+ --xh-action-shadow-hover: var(--xh-log-scroll-to-end-trigger-shadow, var(--xh-_material-shadow));
205
+ --xh-action-shadow-pressed: var(--xh-log-scroll-to-end-trigger-shadow, var(--xh-_material-shadow));
206
+ --xh-action-shadow-focus-visible: var(--xh-log-scroll-to-end-trigger-shadow, var(--xh-_material-shadow));
207
+ --xh-action-shadow-disabled: var(--xh-log-scroll-to-end-trigger-shadow, var(--xh-_material-shadow));
208
+ --xh-action-highlight-rest: var(--xh-_material-highlight);
209
+ --xh-action-highlight-hover: var(--xh-_material-highlight);
210
+ --xh-action-highlight-pressed: var(--xh-_material-highlight);
211
+ --xh-action-highlight-focus-visible: var(--xh-_material-highlight);
212
+ --xh-action-highlight-disabled: var(--xh-_material-highlight);
130
213
  --xh-action-visual-size: var(--xh-log-scroll-to-end-trigger-size, var(--xh-_action-profile-visual-size));
131
214
  --xh-action-radius: var(--xh-log-scroll-to-end-trigger-radius, var(--xh-shape-circle));
132
- --xh-action-bg-rest: var(--xh-log-scroll-to-end-trigger-bg, var(--xh-material-frosted-bg));
133
- --xh-action-bg-hover: var(--xh-log-scroll-to-end-trigger-bg-hover, var(--xh-_action-variant-bg-hover));
134
- --xh-action-border-rest: var(--xh-log-scroll-to-end-trigger-border, var(--xh-material-frosted-border));
135
- --xh-action-border-hover: var(--xh-log-scroll-to-end-trigger-border, var(--xh-material-frosted-border));
136
- --xh-action-border-pressed: var(--xh-log-scroll-to-end-trigger-border, var(--xh-material-frosted-border));
137
- --xh-action-border-focus-visible: var(--xh-log-scroll-to-end-trigger-border, var(--xh-material-frosted-border));
138
- --xh-action-shadow-rest: var(--xh-_log-scroll-to-end-trigger-shadow);
139
- --xh-action-shadow-hover: var(--xh-_log-scroll-to-end-trigger-shadow);
140
- --xh-action-shadow-pressed: var(--xh-_log-scroll-to-end-trigger-shadow);
141
- --xh-action-fg-rest: var(--xh-log-scroll-to-end-trigger-fg, var(--xh-material-frosted-fg));
142
215
  --xh-icon-size: var(--xh-log-icon-size, var(--xh-_action-profile-glyph-size));
143
216
 
144
217
  position: absolute;
145
218
  inset-block-end: var(--xh-log-scroll-to-end-trigger-inset, var(--xh-space-3));
146
219
  inset-inline-end: var(--xh-log-scroll-to-end-trigger-inset, var(--xh-space-3));
147
- -webkit-backdrop-filter: var(--xh-material-frosted-backdrop);
148
- backdrop-filter: var(--xh-material-frosted-backdrop);
149
220
  }
150
221
 
151
222
  /* 连接层收起按钮时写 hidden 属性,上面的 display 会盖掉 UA 规则,这里补回 */
@@ -153,9 +224,15 @@
153
224
  display: none;
154
225
  }
155
226
 
156
- /* 收起不卸载,冒出来时靠这条进场动画;不写 display,可见性归上面那条 [hidden] 管 */
227
+ /* 收起不卸载:离底时冒出来播进场,回底时先播完退场、连接层才写 hidden 藏起。
228
+ 不写 display,可见性归上面那条 [hidden] 管;退场途中不再接指针 */
157
229
  [data-scope='log'][data-part='scroll-to-end-trigger'][data-state='visible'] {
158
- animation: xh-log-button-in var(--xh-motion-duration-enter) var(--xh-motion-ease-enter-strong);
230
+ animation: xh-pop-in var(--xh-motion-duration-enter) var(--xh-motion-ease-enter-strong);
231
+ }
232
+
233
+ [data-scope='log'][data-part='scroll-to-end-trigger'][data-state='hidden']:not([hidden]) {
234
+ pointer-events: none;
235
+ animation: xh-pop-out var(--xh-motion-duration-exit) var(--xh-motion-ease-exit) forwards;
159
236
  }
160
237
 
161
238
  /* 没写内容就由皮肤画一枚向下的字形;作者往按钮里塞了自己的图形,这条规则即不命中。
@@ -207,4 +284,23 @@
207
284
  display: none;
208
285
  }
209
286
  }
287
+
288
+ @media (forced-colors: active) {
289
+ /* 兜底字形是 mask 挖出来的一块底色,这一档里底色被系统换成 Canvas,字形跟着消失。
290
+ 字形退出强制换色、直接写系统色(不能取 currentColor:退出强制换色的伪元素读到的是被系统换掉之前的作者色):
291
+ 按钮面上取 ButtonText,悬停与按下时家族把按钮涂成 Highlight、字形换 HighlightText;
292
+ 禁用取 GrayText */
293
+ [data-scope='log'][data-part='scroll-to-end-trigger']:empty::before {
294
+ forced-color-adjust: none;
295
+ background-color: ButtonText;
296
+ }
297
+
298
+ [data-scope='log'][data-part='scroll-to-end-trigger']:not([data-disabled]):not([data-loading]):is(:hover, :active, [data-pressed]):empty::before {
299
+ background-color: HighlightText;
300
+ }
301
+
302
+ [data-scope='log'][data-part='scroll-to-end-trigger'][data-disabled]:empty::before {
303
+ background-color: GrayText;
304
+ }
305
+ }
210
306
  }
@@ -93,7 +93,7 @@
93
93
 
94
94
  /* 还没出字的那一段页面上只有这一竖,让它闪着,等的人才分得清是在等还是卡住了 */
95
95
  [data-scope='markdown-stream'][data-part='root'][data-caret]::after {
96
- animation: xh-markdown-stream-caret var(--xh-markdown-stream-caret-duration, var(--xh-caret-duration)) steps(1, end) infinite;
96
+ animation: xh-markdown-stream-caret var(--xh-markdown-stream-caret-duration, var(--xh-motion-loop-caret)) steps(1, end) infinite;
97
97
  }
98
98
 
99
99
  /* 减少动效:等待时的光标停在实心不闪,「还在等」这件事仍然看得出来。