@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/tag.css CHANGED
@@ -5,6 +5,9 @@
5
5
 
6
6
  /* 定义 tag 样式。 */
7
7
 
8
+ /* 共享关键帧由 family/motion.css 提供,本皮肤 @import 它,单独引入仍成立。 */
9
+ @import '../family/motion.css';
10
+
8
11
  @layer xihan.components {
9
12
  /* 皮肤在场的标记:开发模式下按 scope 探一次,取不到就说明这份皮肤没被引入。 */
10
13
  [data-scope='tag'] {
@@ -31,7 +34,7 @@
31
34
  padding-inline: var(--xh-tag-px, var(--xh-_tag-px));
32
35
  padding-block: var(--xh-tag-py, var(--xh-_tag-py));
33
36
  border: var(--xh-stroke-thin) solid var(--xh-tag-border, var(--xh-material-soft-border));
34
- /* 状态 chip 的身份是胶囊(§6.3 pill 只给状态 chip 与一维对象) */
37
+ /* 状态 chip 的身份是胶囊(pill 只给状态 chip 与一维对象) */
35
38
  border-radius: var(--xh-tag-radius, var(--xh-shape-pill));
36
39
  background: var(--xh-tag-bg, var(--xh-material-soft-bg));
37
40
  box-shadow: var(--xh-tag-shadow, var(--xh-material-soft-shadow));
@@ -51,6 +54,12 @@
51
54
  display: none;
52
55
  }
53
56
 
57
+ /* 关掉的标签先原地淡出,播完连接层才写 hidden。
58
+ 标签组与选择框的标签行里删掉的那一枚,由列表动效放回原处的替身也是 closed,同一段淡出 */
59
+ [data-scope='tag'][data-part='root'][data-state='closed'] {
60
+ animation: xh-fade-out var(--xh-motion-duration-exit) var(--xh-motion-ease-exit) forwards;
61
+ }
62
+
54
63
  /* 文字过长时截断,关闭钮才始终留在标签里 */
55
64
  [data-scope='tag'][data-part='label'] {
56
65
  overflow: hidden;
@@ -81,7 +90,7 @@
81
90
  line-height: var(--xh-leading-none);
82
91
  cursor: pointer;
83
92
  transition:
84
- background var(--xh-motion-duration-micro) var(--xh-motion-ease-enter),
93
+ background-color var(--xh-motion-duration-micro) var(--xh-motion-ease-enter),
85
94
  scale var(--xh-motion-duration-release) var(--xh-motion-ease-release);
86
95
  }
87
96
 
@@ -112,7 +121,7 @@
112
121
  transition-timing-function: var(--xh-motion-ease-press);
113
122
  }
114
123
 
115
- /* 按住的叉落着焦点(§9.3 focus-visible + pressed 保留焦点环):按压面是从字色兑出的 22% 底,
124
+ /* 按住的叉落着焦点(focus-visible + pressed 保留焦点环):按压面是从字色兑出的 22% 底,
116
125
  压在淡底 / 选中面上把面往字色那头带了一档,默认环与这块混色面在浅色档上只剩 2.2–2.9。
117
126
  环改取叉自己的字色:按压面正是从这支色兑出来的,字色压在它上面的对比与字压在标签面上同源,
118
127
  六族语气与深浅两态都过 3:1;实心档本来就取字色,这条与它同一口径 */
@@ -161,6 +170,21 @@
161
170
  color: var(--xh-tag-fg, var(--xh-_tone-on, var(--xh-fg-on-brand)));
162
171
  }
163
172
 
173
+ /* 实心档是一块彩色面(连接层打 data-xh-ink-surface):面内的图标与作者内容按这块底取墨色。
174
+ 底色随语气与禁用换,这里跟着换 */
175
+ [data-scope='tag'][data-part='root'][data-xh-ink-surface] {
176
+ --xh-ink-surface: var(--xh-tag-bg, var(--xh-bg-brand));
177
+ }
178
+
179
+ [data-scope='tag'][data-part='root'][data-xh-ink-surface][data-tone] {
180
+ --xh-ink-surface: var(--xh-tag-bg, var(--xh-_tone, var(--xh-bg-brand)));
181
+ }
182
+
183
+ [data-scope='tag'][data-part='root'][data-xh-ink-surface][data-disabled] {
184
+ /* 置灰面是墨色淡底:选墨只看分量、不看透明度,取它的不透明档 */
185
+ --xh-ink-surface: var(--xh-tag-bg-disabled, var(--xh-bg-muted-opaque));
186
+ }
187
+
164
188
  [data-scope='tag'][data-part='root'][data-variant='subtle'] {
165
189
  border-color: var(--xh-tag-border, var(--xh-material-soft-border));
166
190
  background: var(--xh-tag-bg, var(--xh-material-soft-bg));
@@ -244,17 +268,6 @@
244
268
  }
245
269
  }
246
270
 
247
- /*
248
- * 高对比档:关闭钮的按压面常态靠从 currentColor 兑出来的底色表出,这一档里底色被统一换成 Canvas,
249
- * 按住那一下与静息塌成同一个样子;用系统高亮反色画回来,兜底字形读 currentColor、自己跟着换
250
- */
251
- @media (forced-colors: active) {
252
- [data-scope='tag'][data-part='close-trigger']:not(:disabled):is(:active, [data-pressed]) {
253
- background: Highlight;
254
- color: HighlightText;
255
- }
256
- }
257
-
258
271
  /* 没写内容就由皮肤画兜底字形;作者往部件里塞了自己的图形,这几条即不命中 */
259
272
  [data-scope='tag'][data-part='close-trigger']:empty::before {
260
273
  content: '';
@@ -266,4 +279,32 @@
266
279
  -webkit-mask: var(--xh-glyph-mark-close) center / contain no-repeat;
267
280
  mask: var(--xh-glyph-mark-close) center / contain no-repeat;
268
281
  }
282
+
283
+ /*
284
+ * 高对比档:关闭钮的按压面常态靠从 currentColor 兑出来的底色表出,这一档里底色被统一换成 Canvas,
285
+ * 按住那一下与静息塌成同一个样子;用系统高亮反色画回来。
286
+ * 兜底字形是 mask 挖出来的一块底色,同样会被换成 Canvas 而消失:退出强制换色、直接写系统色
287
+ * (不能取 currentColor:退出强制换色的伪元素读到的是被系统换掉之前的作者色)——
288
+ * 标签面上取 CanvasText,按住时跟着按压面换 HighlightText,禁用取 GrayText
289
+ */
290
+ @media (forced-colors: active) {
291
+ [data-scope='tag'][data-part='close-trigger']:not(:disabled):is(:active, [data-pressed]) {
292
+ background: Highlight;
293
+ color: HighlightText;
294
+ }
295
+
296
+ [data-scope='tag'][data-part='close-trigger']:empty::before {
297
+ forced-color-adjust: none;
298
+ background-color: CanvasText;
299
+ }
300
+
301
+ [data-scope='tag'][data-part='close-trigger']:not(:disabled):is(:active, [data-pressed]):empty::before {
302
+ background-color: HighlightText;
303
+ }
304
+
305
+ [data-scope='tag'][data-part='root'][data-disabled] [data-scope='tag'][data-part='close-trigger']:empty::before,
306
+ [data-scope='tag'][data-part='close-trigger']:disabled:empty::before {
307
+ background-color: GrayText;
308
+ }
309
+ }
269
310
  }
@@ -6,6 +6,8 @@
6
6
  /* TagsInput 独立皮肤同时传递引入字段视觉盒与字段内动作;full bundle 递归去重。 */
7
7
  @import '../family/field-chrome.css';
8
8
  @import '../family/action-control.css';
9
+ /* 标签的进场与退场取共享关键帧。 */
10
+ @import '../family/motion.css';
9
11
 
10
12
  @layer xihan.components {
11
13
  /* 皮肤在场的标记:开发模式下按 scope 探一次,取不到就说明这份皮肤没被引入。 */
@@ -113,6 +115,8 @@
113
115
  上限取滚动面最小的那一档,与页面上其它滚动面用同一把尺 */
114
116
  max-block-size: var(--xh-tags-input-control-max-h, var(--xh-viewport-h-sm));
115
117
  overflow-y: auto;
118
+ /* 删掉的标签由替身绝对定位在原处播完退场,定位基准是这个框(随框内滚动一起走) */
119
+ position: relative;
116
120
  }
117
121
 
118
122
  [data-scope='tags-input'][data-part='control'][hidden] {
@@ -137,7 +141,7 @@
137
141
 
138
142
  /* 撑满剩余宽度由家族的 flex: 1 1 auto 给,这里只换起算宽 */
139
143
  flex-basis: var(--xh-tags-input-input-basis, 6rem);
140
- min-inline-size: var(--xh-tags-input-input-min-w, 4rem);
144
+ min-inline-size: var(--xh-tags-input-input-min-w, var(--xh-control-input-min-w));
141
145
  /* 行盒收到标签那一行的高度以内,输入框不去顶高整个框 */
142
146
  block-size: auto;
143
147
  line-height: var(--xh-leading-tight);
@@ -151,6 +155,20 @@
151
155
  flex: none;
152
156
  align-items: center;
153
157
  max-inline-size: 100%;
158
+ /* 前面的标签增删、其余标签换到新位置时,由列表动效先反向补偿、再沿这条过渡滑过去 */
159
+ transition: translate var(--xh-motion-duration-move) var(--xh-motion-ease-continuous);
160
+ }
161
+
162
+ /* 新落下的标签原地弹出,同一批按到达顺序错开;首帧就在的直接呈现(自己或 control 带 data-instant)。
163
+ 横排胶囊不用竖向上浮:与来源方向不符,还会探出字段外壳的底边 */
164
+ [data-scope='tags-input'][data-part='item']:not([data-instant], [data-instant] > *) {
165
+ animation: xh-pop-in var(--xh-motion-duration-enter) var(--xh-motion-ease-enter-strong) backwards;
166
+ animation-delay: calc(var(--xh-_stagger-index, 0) * var(--xh-motion-stagger-step));
167
+ }
168
+
169
+ /* 删掉的标签:替身留在原处淡出,播完即移除 */
170
+ [data-scope='tags-input'][data-part='item'][data-state='closed'] {
171
+ animation: xh-fade-out var(--xh-motion-duration-exit) var(--xh-motion-ease-exit) forwards;
154
172
  }
155
173
 
156
174
  [data-scope='tags-input'][data-part='item'][hidden] {
@@ -259,11 +277,11 @@
259
277
  mask: var(--xh-glyph-mark-close) center / contain no-repeat;
260
278
  }
261
279
 
262
- /* 计数:排在控件行下面靠尾端的一行小字,与标题分列 root 的两端 */
280
+ /* 计数:排在控件行下面靠尾端的一行小字,与标题分列 root 的两端。它是次级标注,取说明档字号,不随控件档 */
263
281
  [data-scope='tags-input'][data-part='count'] {
264
282
  align-self: flex-end;
265
283
  color: var(--xh-tags-input-count-fg, var(--xh-fg-muted));
266
- font-size: var(--xh-tags-input-count-font-size, var(--xh-_tags-input-item-font-size));
284
+ font-size: var(--xh-tags-input-count-font-size, var(--xh-text-caption-size));
267
285
  font-variant-numeric: tabular-nums;
268
286
  line-height: var(--xh-leading-normal);
269
287
  }
@@ -282,4 +300,23 @@
282
300
  [data-scope='tags-input'][data-part='count'][data-disabled] {
283
301
  color: var(--xh-tags-input-count-fg-disabled, var(--xh-fg-disabled));
284
302
  }
303
+
304
+ @media (forced-colors: active) {
305
+ /* 兜底字形是 mask 挖出来的一块底色,这一档里底色被系统换成 Canvas,字形跟着消失。
306
+ 字形退出强制换色、直接写系统色(不能取 currentColor:退出强制换色的伪元素读到的是被系统换掉之前的作者色):
307
+ 按钮面上取 ButtonText,悬停与按下时家族把按钮涂成 Highlight、字形换 HighlightText;
308
+ 禁用取 GrayText */
309
+ [data-scope='tags-input'][data-part='clear-trigger']:empty::before {
310
+ forced-color-adjust: none;
311
+ background-color: ButtonText;
312
+ }
313
+
314
+ [data-scope='tags-input'][data-part='clear-trigger']:not([data-disabled]):not([data-loading]):is(:hover, :active, [data-pressed]):empty::before {
315
+ background-color: HighlightText;
316
+ }
317
+
318
+ [data-scope='tags-input'][data-part='clear-trigger'][data-disabled]:empty::before {
319
+ background-color: GrayText;
320
+ }
321
+ }
285
322
  }
@@ -175,4 +175,23 @@
175
175
  [data-scope='text-field'][data-part='count'][data-disabled] {
176
176
  color: var(--xh-text-field-count-fg-disabled, var(--xh-fg-disabled));
177
177
  }
178
+
179
+ @media (forced-colors: active) {
180
+ /* 兜底字形是 mask 挖出来的一块底色,这一档里底色被系统换成 Canvas,字形跟着消失。
181
+ 字形退出强制换色、直接写系统色(不能取 currentColor:退出强制换色的伪元素读到的是被系统换掉之前的作者色):
182
+ 按钮面上取 ButtonText,悬停与按下时家族把按钮涂成 Highlight、字形换 HighlightText;
183
+ 禁用取 GrayText */
184
+ [data-scope='text-field'][data-part='clear-trigger']:empty::before {
185
+ forced-color-adjust: none;
186
+ background-color: ButtonText;
187
+ }
188
+
189
+ [data-scope='text-field'][data-part='clear-trigger']:not([data-disabled]):not([data-loading]):is(:hover, :active, [data-pressed]):empty::before {
190
+ background-color: HighlightText;
191
+ }
192
+
193
+ [data-scope='text-field'][data-part='clear-trigger'][data-disabled]:empty::before {
194
+ background-color: GrayText;
195
+ }
196
+ }
178
197
  }
@@ -139,7 +139,7 @@
139
139
  /* 触屏上连点两下不该被当成缩放手势 */
140
140
  touch-action: manipulation;
141
141
  transition:
142
- background var(--xh-motion-duration-micro) var(--xh-motion-ease-enter),
142
+ background-color var(--xh-motion-duration-micro) var(--xh-motion-ease-enter),
143
143
  color var(--xh-motion-duration-micro) var(--xh-motion-ease-enter);
144
144
  }
145
145
 
@@ -255,4 +255,23 @@
255
255
  white-space: nowrap;
256
256
  pointer-events: none;
257
257
  }
258
+
259
+ @media (forced-colors: active) {
260
+ /* 兜底字形是 mask 挖出来的一块底色,这一档里底色被系统换成 Canvas,字形跟着消失。
261
+ 字形退出强制换色、直接写系统色(不能取 currentColor:退出强制换色的伪元素读到的是被系统换掉之前的作者色):
262
+ 按钮面上取 ButtonText,悬停与按下时家族把按钮涂成 Highlight、字形换 HighlightText;
263
+ 禁用取 GrayText */
264
+ [data-scope='time-field'][data-part='clear-trigger']:empty::before {
265
+ forced-color-adjust: none;
266
+ background-color: ButtonText;
267
+ }
268
+
269
+ [data-scope='time-field'][data-part='clear-trigger']:not([data-disabled]):not([data-loading]):is(:hover, :active, [data-pressed]):empty::before {
270
+ background-color: HighlightText;
271
+ }
272
+
273
+ [data-scope='time-field'][data-part='clear-trigger'][data-disabled]:empty::before {
274
+ background-color: GrayText;
275
+ }
276
+ }
258
277
  }
@@ -63,6 +63,7 @@
63
63
  --xh-_time-picker-control-px: var(--xh-control-px-md);
64
64
  --xh-_time-picker-gap: var(--xh-control-gap-md);
65
65
  --xh-_time-picker-font-size: var(--xh-control-font-md);
66
+ --xh-_time-picker-item-py: var(--xh-list-option-py-md);
66
67
 
67
68
  /* 段位强调随语气走:当前段是「当前项」,淡底 + 淡底前景;对号使用普通表面上的前景色。
68
69
  没写 data-tone 时这几个 --xh-_tone* 没被声明,退回品牌色 */
@@ -95,6 +96,7 @@
95
96
  --xh-_time-picker-control-px: var(--xh-control-px-sm);
96
97
  --xh-_time-picker-gap: var(--xh-control-gap-sm);
97
98
  --xh-_time-picker-font-size: var(--xh-control-font-sm);
99
+ --xh-_time-picker-item-py: var(--xh-list-option-py-sm);
98
100
  }
99
101
 
100
102
  [data-scope='time-picker']:is([data-part='root'], [data-part='positioner'])[data-size='lg'] {
@@ -103,6 +105,7 @@
103
105
  --xh-_time-picker-control-px: var(--xh-control-px-lg);
104
106
  --xh-_time-picker-gap: var(--xh-control-gap-lg);
105
107
  --xh-_time-picker-font-size: var(--xh-control-font-lg);
108
+ --xh-_time-picker-item-py: var(--xh-list-option-py-lg);
106
109
  }
107
110
 
108
111
  /* 声明了 display 就盖掉了 UA 的 [hidden]{display:none},收起态得自己还回去 */
@@ -189,7 +192,7 @@
189
192
  /* 段是 role=spinbutton 的展示节点,双击选中一段文字只会碍事 */
190
193
  user-select: none;
191
194
  transition:
192
- background var(--xh-motion-duration-micro) var(--xh-motion-ease-enter),
195
+ background-color var(--xh-motion-duration-micro) var(--xh-motion-ease-enter),
193
196
  color var(--xh-motion-duration-micro) var(--xh-motion-ease-enter);
194
197
  }
195
198
 
@@ -320,9 +323,8 @@
320
323
  outline: none;
321
324
  }
322
325
 
323
- [data-scope='time-picker'][data-part='content'][data-state='open'] {
324
- /* 只在展开态挂着:随状态属性一起消失,不长期占着合成层 */
325
- will-change: opacity, translate;
326
+ /* 挂载时就开着的那一段(data-instant)属于首帧,直接呈现 */
327
+ [data-scope='time-picker'][data-part='content'][data-state='open']:not([data-instant]) {
326
328
  animation: xh-overlay-slide-in var(--xh-motion-duration-enter) var(--xh-motion-ease-enter-strong);
327
329
  }
328
330
 
@@ -343,7 +345,7 @@
343
345
  overflow-y: auto;
344
346
  /* 浮层滚动面:滚到头不把页面一起带走 */
345
347
  overscroll-behavior: contain;
346
- border-inline-end: var(--xh-stroke-thin) solid var(--xh-time-picker-column-divider, var(--xh-material-frosted-separator));
348
+ border-inline-end: var(--xh-stroke-thin) solid var(--xh-time-picker-column-divider, var(--xh-material-solid-separator));
347
349
  }
348
350
 
349
351
  [data-scope='time-picker'][data-part='preset-group'][hidden] {
@@ -357,7 +359,7 @@
357
359
  --xh-collection-block-padding: var(--xh-time-picker-preset-py, var(--xh-space-1));
358
360
  --xh-collection-inline-padding: var(--xh-time-picker-preset-px, var(--xh-space-3));
359
361
  --xh-collection-font-size: var(--xh-text-secondary-size);
360
- --xh-collection-radius: var(--xh-time-picker-preset-radius, var(--xh-shape-control));
362
+ --xh-collection-radius: var(--xh-time-picker-preset-radius, var(--xh-shape-inset));
361
363
  /* 面板是实体面(floating),正文取页面前景 */
362
364
  --xh-collection-fg-rest: var(--xh-time-picker-preset-fg, var(--xh-fg-default));
363
365
  --xh-collection-fg-hover: var(--xh-time-picker-preset-fg, var(--xh-fg-default));
@@ -383,7 +385,7 @@
383
385
  /* 对号的末端轨始终留着,切换选中时文字与整列宽度都不移动。 */
384
386
  padding-inline-end: calc(
385
387
  var(--xh-time-picker-preset-px, var(--xh-space-3))
386
- + var(--xh-time-picker-preset-check-size, var(--xh-glyph-size-sm))
388
+ + var(--xh-time-picker-preset-check-size, var(--xh-control-indicator-size))
387
389
  + var(--xh-space-1)
388
390
  );
389
391
  white-space: nowrap;
@@ -404,8 +406,8 @@
404
406
  position: absolute;
405
407
  inset-block-start: 50%;
406
408
  inset-inline-end: var(--xh-time-picker-preset-px, var(--xh-space-3));
407
- inline-size: var(--xh-time-picker-preset-check-size, var(--xh-glyph-size-sm));
408
- block-size: var(--xh-time-picker-preset-check-size, var(--xh-glyph-size-sm));
409
+ inline-size: var(--xh-time-picker-preset-check-size, var(--xh-control-indicator-size));
410
+ block-size: var(--xh-time-picker-preset-check-size, var(--xh-control-indicator-size));
409
411
  background-color: var(--xh-time-picker-preset-check-fg, var(--xh-_time-picker-check-fg));
410
412
  opacity: 0;
411
413
  translate: 0 -50%;
@@ -452,7 +454,7 @@
452
454
 
453
455
  /* 每列后面紧跟着它自己的贴层条子节点,相邻选择器接不到下一列,按「前面有过列」取第二列起 */
454
456
  [data-scope='time-picker'][data-part='column'] ~ [data-scope='time-picker'][data-part='column'] {
455
- border-inline-start: var(--xh-stroke-thin) solid var(--xh-time-picker-column-divider, var(--xh-material-frosted-separator));
457
+ border-inline-start: var(--xh-stroke-thin) solid var(--xh-time-picker-column-divider, var(--xh-material-solid-separator));
456
458
  }
457
459
 
458
460
  /* 焦点落在列上有两种情形:指针打开、这一段还空着、还没有任何格当锚点,或整列被界裁空。
@@ -474,13 +476,13 @@
474
476
  [data-scope='time-picker'][data-part='item'] {
475
477
  --xh-_time-picker-item-rail: max(
476
478
  var(--xh-time-picker-item-px, var(--xh-space-0_5)),
477
- calc(var(--xh-time-picker-item-check-size, var(--xh-glyph-size-sm)) + var(--xh-space-0_5))
479
+ calc(var(--xh-time-picker-item-check-size, var(--xh-control-indicator-size)) + var(--xh-space-0_5))
478
480
  );
479
- --xh-collection-block-padding: var(--xh-time-picker-item-py, 0);
481
+ --xh-collection-block-padding: var(--xh-time-picker-item-py, var(--xh-_time-picker-item-py));
480
482
  /* 两侧留同宽轨:对号绝对落在末端,数字仍在整格的数学中心。 */
481
483
  --xh-collection-inline-padding: var(--xh-_time-picker-item-rail);
482
484
  --xh-collection-font-size: var(--xh-time-picker-item-font-size, var(--xh-_time-picker-font-size));
483
- --xh-collection-radius: var(--xh-time-picker-item-radius, var(--xh-shape-control));
485
+ --xh-collection-radius: var(--xh-time-picker-item-radius, var(--xh-shape-inset));
484
486
  --xh-collection-fg-rest: var(--xh-time-picker-item-fg, var(--xh-material-frosted-fg));
485
487
  --xh-collection-fg-hover: var(--xh-time-picker-item-fg, var(--xh-material-frosted-fg));
486
488
  --xh-collection-fg-keyboard-highlight: var(--xh-time-picker-item-fg, var(--xh-material-frosted-fg));
@@ -507,9 +509,9 @@
507
509
  flex: none;
508
510
  align-items: center;
509
511
  justify-content: center;
510
- block-size: var(--xh-time-picker-item-h, var(--xh-overlay-column-item-h));
512
+ block-size: var(--xh-time-picker-item-h, auto);
511
513
  /* 居中的单个数字格没有截断层,行高保持紧排,列内多露几格 */
512
- line-height: var(--xh-leading-none);
514
+ line-height: var(--xh-leading-normal);
513
515
  white-space: nowrap;
514
516
  user-select: none;
515
517
  }
@@ -532,8 +534,8 @@
532
534
  position: absolute;
533
535
  inset-block-start: 50%;
534
536
  inset-inline-end: var(--xh-space-0_5);
535
- inline-size: var(--xh-time-picker-item-check-size, var(--xh-glyph-size-sm));
536
- block-size: var(--xh-time-picker-item-check-size, var(--xh-glyph-size-sm));
537
+ inline-size: var(--xh-time-picker-item-check-size, var(--xh-control-indicator-size));
538
+ block-size: var(--xh-time-picker-item-check-size, var(--xh-control-indicator-size));
537
539
  background-color: var(--xh-time-picker-item-check-fg, var(--xh-_time-picker-check-fg));
538
540
  opacity: 0;
539
541
  translate: 0 -50%;
@@ -566,6 +568,12 @@
566
568
  forced-color-adjust: none;
567
569
  }
568
570
 
571
+ /* 按下与没被高亮时的悬停,家族把条目涂成 Highlight,对号跟着换 HighlightText */
572
+ [data-scope='time-picker'][data-part='preset']:not([aria-disabled='true'], [data-disabled], [aria-busy='true'], [data-error]):is(:active, [data-pressed], :hover:not(:focus-visible, [data-highlighted]))::after,
573
+ [data-scope='time-picker'][data-part='item']:not([aria-disabled='true'], [data-disabled], [aria-busy='true'], [data-error]):is(:active, [data-pressed], :hover:not(:focus-visible, [data-highlighted]))::after {
574
+ background-color: HighlightText;
575
+ }
576
+
569
577
  [data-scope='time-picker'][data-part='preset'][data-disabled]::after,
570
578
  [data-scope='time-picker'][data-part='item'][data-disabled]::after {
571
579
  background-color: GrayText;
@@ -610,6 +618,25 @@
610
618
  -webkit-mask: var(--xh-glyph-mark-clock) center / contain no-repeat;
611
619
  mask: var(--xh-glyph-mark-clock) center / contain no-repeat;
612
620
  }
621
+
622
+ @media (forced-colors: active) {
623
+ /* 兜底字形是 mask 挖出来的一块底色,这一档里底色被系统换成 Canvas,字形跟着消失。
624
+ 字形退出强制换色、直接写系统色(不能取 currentColor:退出强制换色的伪元素读到的是被系统换掉之前的作者色):
625
+ 按钮面上取 ButtonText,悬停与按下时家族把按钮涂成 Highlight、字形换 HighlightText;
626
+ 禁用取 GrayText */
627
+ [data-scope='time-picker']:is([data-part='clear-trigger'], [data-part='trigger']):empty::before {
628
+ forced-color-adjust: none;
629
+ background-color: ButtonText;
630
+ }
631
+
632
+ [data-scope='time-picker']:is([data-part='clear-trigger'], [data-part='trigger']):not([data-disabled]):not([data-loading]):is(:hover, :active, [data-pressed]):empty::before {
633
+ background-color: HighlightText;
634
+ }
635
+
636
+ [data-scope='time-picker']:is([data-part='clear-trigger'], [data-part='trigger'])[data-disabled]:empty::before {
637
+ background-color: GrayText;
638
+ }
639
+ }
613
640
  }
614
641
 
615
642
  @layer xihan.motion {
@@ -70,6 +70,7 @@
70
70
  --xh-_time-range-picker-control-px: var(--xh-control-px-md);
71
71
  --xh-_time-range-picker-gap: var(--xh-control-gap-md);
72
72
  --xh-_time-range-picker-font-size: var(--xh-control-font-md);
73
+ --xh-_time-range-picker-item-py: var(--xh-list-option-py-md);
73
74
 
74
75
  /* 段位强调随语气走:当前段是「当前项」,淡底 + 淡底前景;对号使用普通表面上的前景色。
75
76
  没写 data-tone 时这几个 --xh-_tone* 没被声明,退回品牌色 */
@@ -102,6 +103,7 @@
102
103
  --xh-_time-range-picker-control-px: var(--xh-control-px-sm);
103
104
  --xh-_time-range-picker-gap: var(--xh-control-gap-sm);
104
105
  --xh-_time-range-picker-font-size: var(--xh-control-font-sm);
106
+ --xh-_time-range-picker-item-py: var(--xh-list-option-py-sm);
105
107
  }
106
108
 
107
109
  [data-scope='time-range-picker']:is([data-part='root'], [data-part='positioner'])[data-size='lg'] {
@@ -110,6 +112,7 @@
110
112
  --xh-_time-range-picker-control-px: var(--xh-control-px-lg);
111
113
  --xh-_time-range-picker-gap: var(--xh-control-gap-lg);
112
114
  --xh-_time-range-picker-font-size: var(--xh-control-font-lg);
115
+ --xh-_time-range-picker-item-py: var(--xh-list-option-py-lg);
113
116
  }
114
117
 
115
118
  /* 声明了 display 就盖掉了 UA 的 [hidden]{display:none},收起态得自己还回去 */
@@ -222,7 +225,7 @@
222
225
  /* 段是 role=spinbutton 的展示节点,双击选中一段文字只会碍事 */
223
226
  user-select: none;
224
227
  transition:
225
- background var(--xh-motion-duration-micro) var(--xh-motion-ease-enter),
228
+ background-color var(--xh-motion-duration-micro) var(--xh-motion-ease-enter),
226
229
  color var(--xh-motion-duration-micro) var(--xh-motion-ease-enter);
227
230
  }
228
231
 
@@ -359,9 +362,8 @@
359
362
  outline: none;
360
363
  }
361
364
 
362
- [data-scope='time-range-picker'][data-part='content'][data-state='open'] {
363
- /* 只在展开态挂着:随状态属性一起消失,不长期占着合成层 */
364
- will-change: opacity, translate;
365
+ /* 挂载时就开着的那一段(data-instant)属于首帧,直接呈现 */
366
+ [data-scope='time-range-picker'][data-part='content'][data-state='open']:not([data-instant]) {
365
367
  animation: xh-overlay-slide-in var(--xh-motion-duration-enter) var(--xh-motion-ease-enter-strong);
366
368
  }
367
369
 
@@ -382,7 +384,7 @@
382
384
  overflow-y: auto;
383
385
  /* 浮层滚动面:滚到头不把页面一起带走 */
384
386
  overscroll-behavior: contain;
385
- border-inline-end: var(--xh-stroke-thin) solid var(--xh-time-range-picker-column-divider, var(--xh-material-frosted-separator));
387
+ border-inline-end: var(--xh-stroke-thin) solid var(--xh-time-range-picker-column-divider, var(--xh-material-solid-separator));
386
388
  }
387
389
 
388
390
  [data-scope='time-range-picker'][data-part='preset-group'][hidden] {
@@ -396,7 +398,7 @@
396
398
  --xh-collection-block-padding: var(--xh-time-range-picker-preset-py, var(--xh-space-1));
397
399
  --xh-collection-inline-padding: var(--xh-time-range-picker-preset-px, var(--xh-space-3));
398
400
  --xh-collection-font-size: var(--xh-text-secondary-size);
399
- --xh-collection-radius: var(--xh-time-range-picker-preset-radius, var(--xh-shape-control));
401
+ --xh-collection-radius: var(--xh-time-range-picker-preset-radius, var(--xh-shape-inset));
400
402
  /* 面板是实体面(floating),正文取页面前景 */
401
403
  --xh-collection-fg-rest: var(--xh-time-range-picker-preset-fg, var(--xh-fg-default));
402
404
  --xh-collection-fg-hover: var(--xh-time-range-picker-preset-fg, var(--xh-fg-default));
@@ -422,7 +424,7 @@
422
424
  /* 对号的末端轨始终留着,切换选中时文字与整列宽度都不移动。 */
423
425
  padding-inline-end: calc(
424
426
  var(--xh-time-range-picker-preset-px, var(--xh-space-3))
425
- + var(--xh-time-range-picker-preset-check-size, var(--xh-glyph-size-sm))
427
+ + var(--xh-time-range-picker-preset-check-size, var(--xh-control-indicator-size))
426
428
  + var(--xh-space-1)
427
429
  );
428
430
  white-space: nowrap;
@@ -443,8 +445,8 @@
443
445
  position: absolute;
444
446
  inset-block-start: 50%;
445
447
  inset-inline-end: var(--xh-time-range-picker-preset-px, var(--xh-space-3));
446
- inline-size: var(--xh-time-range-picker-preset-check-size, var(--xh-glyph-size-sm));
447
- block-size: var(--xh-time-range-picker-preset-check-size, var(--xh-glyph-size-sm));
448
+ inline-size: var(--xh-time-range-picker-preset-check-size, var(--xh-control-indicator-size));
449
+ block-size: var(--xh-time-range-picker-preset-check-size, var(--xh-control-indicator-size));
448
450
  background-color: var(--xh-time-range-picker-preset-check-fg, var(--xh-_time-range-picker-check-fg));
449
451
  opacity: 0;
450
452
  translate: 0 -50%;
@@ -499,7 +501,7 @@
499
501
  [data-scope='time-range-picker'][data-part='column-group'] + [data-scope='time-range-picker'][data-part='column-group'] {
500
502
  margin-inline-start: var(--xh-time-range-picker-column-group-gap, var(--xh-space-2));
501
503
  padding-inline-start: var(--xh-time-range-picker-column-group-gap, var(--xh-space-2));
502
- border-inline-start: var(--xh-stroke-thin) solid var(--xh-time-range-picker-column-group-divider, var(--xh-material-frosted-separator));
504
+ border-inline-start: var(--xh-stroke-thin) solid var(--xh-time-range-picker-column-group-divider, var(--xh-material-solid-separator));
503
505
  }
504
506
 
505
507
  /* 组顶上的小标题:独占一行,字号走辅助文本档 */
@@ -548,7 +550,7 @@
548
550
 
549
551
  /* 每列后面紧跟着它自己的贴层条子节点,相邻选择器接不到下一列,按「前面有过列」取第二列起 */
550
552
  [data-scope='time-range-picker'][data-part='column'] ~ [data-scope='time-range-picker'][data-part='column'] {
551
- border-inline-start: var(--xh-stroke-thin) solid var(--xh-time-range-picker-column-divider, var(--xh-material-frosted-separator));
553
+ border-inline-start: var(--xh-stroke-thin) solid var(--xh-time-range-picker-column-divider, var(--xh-material-solid-separator));
552
554
  }
553
555
 
554
556
  /* 焦点落在列上有两种情形:指针打开、这一段还空着、还没有任何格当锚点,或整列被界裁空。
@@ -570,13 +572,13 @@
570
572
  [data-scope='time-range-picker'][data-part='item'] {
571
573
  --xh-_time-range-picker-item-rail: max(
572
574
  var(--xh-time-range-picker-item-px, var(--xh-space-0_5)),
573
- calc(var(--xh-time-range-picker-item-check-size, var(--xh-glyph-size-sm)) + var(--xh-space-0_5))
575
+ calc(var(--xh-time-range-picker-item-check-size, var(--xh-control-indicator-size)) + var(--xh-space-0_5))
574
576
  );
575
- --xh-collection-block-padding: var(--xh-time-range-picker-item-py, 0);
577
+ --xh-collection-block-padding: var(--xh-time-range-picker-item-py, var(--xh-_time-range-picker-item-py));
576
578
  /* 两侧留同宽轨:对号绝对落在末端,数字仍在整格的数学中心。 */
577
579
  --xh-collection-inline-padding: var(--xh-_time-range-picker-item-rail);
578
580
  --xh-collection-font-size: var(--xh-time-range-picker-item-font-size, var(--xh-_time-range-picker-font-size));
579
- --xh-collection-radius: var(--xh-time-range-picker-item-radius, var(--xh-shape-control));
581
+ --xh-collection-radius: var(--xh-time-range-picker-item-radius, var(--xh-shape-inset));
580
582
  --xh-collection-fg-rest: var(--xh-time-range-picker-item-fg, var(--xh-material-frosted-fg));
581
583
  --xh-collection-fg-hover: var(--xh-time-range-picker-item-fg, var(--xh-material-frosted-fg));
582
584
  --xh-collection-fg-keyboard-highlight: var(--xh-time-range-picker-item-fg, var(--xh-material-frosted-fg));
@@ -603,9 +605,9 @@
603
605
  flex: none;
604
606
  align-items: center;
605
607
  justify-content: center;
606
- block-size: var(--xh-time-range-picker-item-h, var(--xh-overlay-column-item-h));
608
+ block-size: var(--xh-time-range-picker-item-h, auto);
607
609
  /* 居中的单个数字格没有截断层,行高保持紧排,列内多露几格 */
608
- line-height: var(--xh-leading-none);
610
+ line-height: var(--xh-leading-normal);
609
611
  white-space: nowrap;
610
612
  user-select: none;
611
613
  }
@@ -628,8 +630,8 @@
628
630
  position: absolute;
629
631
  inset-block-start: 50%;
630
632
  inset-inline-end: var(--xh-space-0_5);
631
- inline-size: var(--xh-time-range-picker-item-check-size, var(--xh-glyph-size-sm));
632
- block-size: var(--xh-time-range-picker-item-check-size, var(--xh-glyph-size-sm));
633
+ inline-size: var(--xh-time-range-picker-item-check-size, var(--xh-control-indicator-size));
634
+ block-size: var(--xh-time-range-picker-item-check-size, var(--xh-control-indicator-size));
633
635
  background-color: var(--xh-time-range-picker-item-check-fg, var(--xh-_time-range-picker-check-fg));
634
636
  opacity: 0;
635
637
  translate: 0 -50%;
@@ -662,6 +664,12 @@
662
664
  forced-color-adjust: none;
663
665
  }
664
666
 
667
+ /* 按下与没被高亮时的悬停,家族把条目涂成 Highlight,对号跟着换 HighlightText */
668
+ [data-scope='time-range-picker'][data-part='preset']:not([aria-disabled='true'], [data-disabled], [aria-busy='true'], [data-error]):is(:active, [data-pressed], :hover:not(:focus-visible, [data-highlighted]))::after,
669
+ [data-scope='time-range-picker'][data-part='item']:not([aria-disabled='true'], [data-disabled], [aria-busy='true'], [data-error]):is(:active, [data-pressed], :hover:not(:focus-visible, [data-highlighted]))::after {
670
+ background-color: HighlightText;
671
+ }
672
+
665
673
  [data-scope='time-range-picker'][data-part='preset'][data-disabled]::after,
666
674
  [data-scope='time-range-picker'][data-part='item'][data-disabled]::after {
667
675
  background-color: GrayText;
@@ -706,6 +714,25 @@
706
714
  -webkit-mask: var(--xh-glyph-mark-clock) center / contain no-repeat;
707
715
  mask: var(--xh-glyph-mark-clock) center / contain no-repeat;
708
716
  }
717
+
718
+ @media (forced-colors: active) {
719
+ /* 兜底字形是 mask 挖出来的一块底色,这一档里底色被系统换成 Canvas,字形跟着消失。
720
+ 字形退出强制换色、直接写系统色(不能取 currentColor:退出强制换色的伪元素读到的是被系统换掉之前的作者色):
721
+ 按钮面上取 ButtonText,悬停与按下时家族把按钮涂成 Highlight、字形换 HighlightText;
722
+ 禁用取 GrayText */
723
+ [data-scope='time-range-picker']:is([data-part='clear-trigger'], [data-part='trigger']):empty::before {
724
+ forced-color-adjust: none;
725
+ background-color: ButtonText;
726
+ }
727
+
728
+ [data-scope='time-range-picker']:is([data-part='clear-trigger'], [data-part='trigger']):not([data-disabled]):not([data-loading]):is(:hover, :active, [data-pressed]):empty::before {
729
+ background-color: HighlightText;
730
+ }
731
+
732
+ [data-scope='time-range-picker']:is([data-part='clear-trigger'], [data-part='trigger'])[data-disabled]:empty::before {
733
+ background-color: GrayText;
734
+ }
735
+ }
709
736
  }
710
737
 
711
738
  @layer xihan.motion {
package/css/timeline.css CHANGED
@@ -107,7 +107,7 @@
107
107
  /* 语气色由每条自己的数据给,同一条的语气改了(事情办成了、出错了)走一遍过渡,
108
108
  整列圆点不在数据回来的那一帧集体跳色 */
109
109
  transition:
110
- background var(--xh-motion-duration-micro) var(--xh-motion-ease-enter),
110
+ background-color var(--xh-motion-duration-micro) var(--xh-motion-ease-enter),
111
111
  color var(--xh-motion-duration-micro) var(--xh-motion-ease-enter);
112
112
  }
113
113