@xihan-ui/styles 3.2.0 → 4.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 (232) hide show
  1. package/CHANGELOG.md +441 -0
  2. package/component-tokens.d.ts +229 -60
  3. package/components.tokens.json +5124 -1555
  4. package/css/accordion.css +47 -20
  5. package/css/alert.css +14 -15
  6. package/css/anchor.css +2 -2
  7. package/css/approval.css +37 -13
  8. package/css/avatar-group.css +9 -12
  9. package/css/avatar.css +20 -18
  10. package/css/back-top.css +21 -7
  11. package/css/badge.css +5 -5
  12. package/css/breadcrumb.css +18 -16
  13. package/css/button-group.css +4 -6
  14. package/css/button.css +4 -7
  15. package/css/calendar-picker.css +177 -94
  16. package/css/calendar-range-picker.css +206 -121
  17. package/css/card.css +34 -6
  18. package/css/carousel.css +65 -49
  19. package/css/cascader.css +41 -29
  20. package/css/checkbox-group.css +9 -6
  21. package/css/checkbox.css +5 -4
  22. package/css/citation.css +7 -2
  23. package/css/clipboard.css +20 -4
  24. package/css/collapsible.css +29 -14
  25. package/css/color-field.css +4 -4
  26. package/css/color-picker.css +77 -23
  27. package/css/color-slider.css +10 -8
  28. package/css/color-swatch-picker.css +5 -5
  29. package/css/combobox.css +14 -10
  30. package/css/command.css +13 -8
  31. package/css/context-menu.css +10 -5
  32. package/css/date-field.css +4 -4
  33. package/css/date-picker.css +165 -102
  34. package/css/date-range-picker.css +186 -123
  35. package/css/description.css +10 -6
  36. package/css/descriptions.css +47 -19
  37. package/css/dialog.css +50 -35
  38. package/css/drawer.css +75 -21
  39. package/css/editable.css +15 -41
  40. package/css/empty-state.css +21 -3
  41. package/css/field-array.css +4 -1
  42. package/css/field.css +17 -18
  43. package/css/fieldset.css +33 -13
  44. package/css/file-upload.css +65 -32
  45. package/css/float-button.css +25 -15
  46. package/css/floating-panel.css +1 -1
  47. package/css/form.css +24 -10
  48. package/css/grid-list.css +1 -1
  49. package/css/highlight.css +4 -4
  50. package/css/hover-card.css +19 -12
  51. package/css/image-viewer.css +77 -27
  52. package/css/image.css +12 -4
  53. package/css/infinite-scroll.css +8 -4
  54. package/css/input-group.css +74 -26
  55. package/css/kbd.css +1 -1
  56. package/css/label.css +27 -11
  57. package/css/layout.css +17 -10
  58. package/css/list.css +13 -9
  59. package/css/listbox.css +12 -7
  60. package/css/loading-bar.css +3 -0
  61. package/css/mention.css +10 -8
  62. package/css/menu.css +10 -5
  63. package/css/menubar.css +13 -8
  64. package/css/navigation-menu.css +2 -2
  65. package/css/notification.css +114 -31
  66. package/css/number-animation.css +2 -2
  67. package/css/number-field.css +60 -37
  68. package/css/page-header.css +63 -26
  69. package/css/pagination.css +35 -38
  70. package/css/password-input.css +10 -66
  71. package/css/pin-input.css +18 -26
  72. package/css/popconfirm.css +20 -11
  73. package/css/popover.css +18 -12
  74. package/css/progress.css +14 -13
  75. package/css/prompt-input.css +3 -3
  76. package/css/question-flow.css +33 -7
  77. package/css/radio-group.css +120 -55
  78. package/css/rating.css +31 -14
  79. package/css/select.css +14 -10
  80. package/css/separator.css +22 -4
  81. package/css/side-nav.css +16 -11
  82. package/css/signature-pad.css +23 -9
  83. package/css/skeleton.css +7 -7
  84. package/css/slider.css +71 -42
  85. package/css/sparkline.css +8 -2
  86. package/css/spinner.css +40 -20
  87. package/css/statistic.css +14 -14
  88. package/css/steps.css +115 -84
  89. package/css/switch.css +9 -7
  90. package/css/table.css +27 -10
  91. package/css/tabs.css +35 -12
  92. package/css/tag-group.css +17 -6
  93. package/css/tag.css +54 -29
  94. package/css/tags-input.css +38 -19
  95. package/css/text-field.css +5 -5
  96. package/css/time-field.css +4 -4
  97. package/css/time-picker.css +150 -64
  98. package/css/time-range-picker.css +91 -62
  99. package/css/timeline.css +37 -20
  100. package/css/timer.css +3 -3
  101. package/css/toggle-group.css +4 -4
  102. package/css/tool-call.css +6 -4
  103. package/css/toolbar.css +6 -5
  104. package/css/tooltip.css +15 -16
  105. package/css/tour.css +14 -7
  106. package/css/transfer.css +22 -16
  107. package/css/tree-select.css +10 -10
  108. package/css/tree.css +26 -25
  109. package/css/typography.css +28 -25
  110. package/dist/css/accordion.css +47 -20
  111. package/dist/css/alert.css +14 -15
  112. package/dist/css/anchor.css +2 -2
  113. package/dist/css/approval.css +37 -13
  114. package/dist/css/avatar-group.css +9 -12
  115. package/dist/css/avatar.css +20 -18
  116. package/dist/css/back-top.css +21 -7
  117. package/dist/css/badge.css +5 -5
  118. package/dist/css/breadcrumb.css +18 -16
  119. package/dist/css/button-group.css +4 -6
  120. package/dist/css/button.css +4 -7
  121. package/dist/css/calendar-picker.css +177 -94
  122. package/dist/css/calendar-range-picker.css +206 -121
  123. package/dist/css/card.css +34 -6
  124. package/dist/css/carousel.css +65 -49
  125. package/dist/css/cascader.css +41 -29
  126. package/dist/css/checkbox-group.css +9 -6
  127. package/dist/css/checkbox.css +5 -4
  128. package/dist/css/citation.css +7 -2
  129. package/dist/css/clipboard.css +20 -4
  130. package/dist/css/collapsible.css +29 -14
  131. package/dist/css/color-field.css +4 -4
  132. package/dist/css/color-picker.css +77 -23
  133. package/dist/css/color-slider.css +10 -8
  134. package/dist/css/color-swatch-picker.css +5 -5
  135. package/dist/css/combobox.css +14 -10
  136. package/dist/css/command.css +13 -8
  137. package/dist/css/context-menu.css +10 -5
  138. package/dist/css/date-field.css +4 -4
  139. package/dist/css/date-picker.css +165 -102
  140. package/dist/css/date-range-picker.css +186 -123
  141. package/dist/css/description.css +10 -6
  142. package/dist/css/descriptions.css +47 -19
  143. package/dist/css/dialog.css +50 -35
  144. package/dist/css/drawer.css +75 -21
  145. package/dist/css/editable.css +15 -41
  146. package/dist/css/empty-state.css +21 -3
  147. package/dist/css/field-array.css +4 -1
  148. package/dist/css/field.css +17 -18
  149. package/dist/css/fieldset.css +33 -13
  150. package/dist/css/file-upload.css +65 -32
  151. package/dist/css/float-button.css +25 -15
  152. package/dist/css/floating-panel.css +1 -1
  153. package/dist/css/form.css +24 -10
  154. package/dist/css/grid-list.css +1 -1
  155. package/dist/css/highlight.css +4 -4
  156. package/dist/css/hover-card.css +19 -12
  157. package/dist/css/image-viewer.css +77 -27
  158. package/dist/css/image.css +12 -4
  159. package/dist/css/infinite-scroll.css +8 -4
  160. package/dist/css/input-group.css +74 -26
  161. package/dist/css/kbd.css +1 -1
  162. package/dist/css/label.css +27 -11
  163. package/dist/css/layout.css +17 -10
  164. package/dist/css/list.css +13 -9
  165. package/dist/css/listbox.css +12 -7
  166. package/dist/css/loading-bar.css +3 -0
  167. package/dist/css/mention.css +10 -8
  168. package/dist/css/menu.css +10 -5
  169. package/dist/css/menubar.css +13 -8
  170. package/dist/css/navigation-menu.css +2 -2
  171. package/dist/css/notification.css +114 -31
  172. package/dist/css/number-animation.css +2 -2
  173. package/dist/css/number-field.css +60 -37
  174. package/dist/css/page-header.css +63 -26
  175. package/dist/css/pagination.css +35 -38
  176. package/dist/css/password-input.css +10 -66
  177. package/dist/css/pin-input.css +18 -26
  178. package/dist/css/popconfirm.css +20 -11
  179. package/dist/css/popover.css +18 -12
  180. package/dist/css/progress.css +14 -13
  181. package/dist/css/prompt-input.css +3 -3
  182. package/dist/css/question-flow.css +33 -7
  183. package/dist/css/radio-group.css +120 -55
  184. package/dist/css/rating.css +31 -14
  185. package/dist/css/select.css +14 -10
  186. package/dist/css/separator.css +22 -4
  187. package/dist/css/side-nav.css +16 -11
  188. package/dist/css/signature-pad.css +23 -9
  189. package/dist/css/skeleton.css +7 -7
  190. package/dist/css/slider.css +71 -42
  191. package/dist/css/sparkline.css +8 -2
  192. package/dist/css/spinner.css +40 -20
  193. package/dist/css/statistic.css +14 -14
  194. package/dist/css/steps.css +115 -84
  195. package/dist/css/switch.css +9 -7
  196. package/dist/css/table.css +27 -10
  197. package/dist/css/tabs.css +35 -12
  198. package/dist/css/tag-group.css +17 -6
  199. package/dist/css/tag.css +54 -29
  200. package/dist/css/tags-input.css +38 -19
  201. package/dist/css/text-field.css +5 -5
  202. package/dist/css/time-field.css +4 -4
  203. package/dist/css/time-picker.css +150 -64
  204. package/dist/css/time-range-picker.css +91 -62
  205. package/dist/css/timeline.css +37 -20
  206. package/dist/css/timer.css +3 -3
  207. package/dist/css/toggle-group.css +4 -4
  208. package/dist/css/tool-call.css +6 -4
  209. package/dist/css/toolbar.css +6 -5
  210. package/dist/css/tooltip.css +15 -16
  211. package/dist/css/tour.css +14 -7
  212. package/dist/css/transfer.css +22 -16
  213. package/dist/css/tree-select.css +10 -10
  214. package/dist/css/tree.css +26 -25
  215. package/dist/css/typography.css +28 -25
  216. package/dist/family/action-control.css +30 -24
  217. package/dist/family/chart.css +57 -0
  218. package/dist/family/collection-item.css +12 -8
  219. package/dist/family/field-chrome.css +28 -19
  220. package/dist/family/loading-ring.css +20 -13
  221. package/dist/family/swatch.css +4 -4
  222. package/dist/family/tag-list.css +6 -0
  223. package/family/action-control.css +30 -24
  224. package/family/chart.css +57 -0
  225. package/family/collection-item.css +12 -8
  226. package/family/field-chrome.css +28 -19
  227. package/family/loading-ring.css +20 -13
  228. package/family/swatch.css +4 -4
  229. package/family/tag-list.css +6 -0
  230. package/index.css +3580 -2060
  231. package/index.unlayered.css +3579 -2060
  232. package/package.json +2 -2
@@ -12,11 +12,12 @@
12
12
  @import '../family/loading-ring.css';
13
13
 
14
14
  @layer xihan.motion {
15
- /* 叠放的一摞:新卡片从视口边缘外进入,同时落到自己的折叠层级。整幅位移取令牌,减弱动效下归零,只剩淡入 */
15
+ /* 叠放的一摞:新卡片从叠放外沿推进来一小段(--xh-motion-distance-lg),同时淡入、落到自己的折叠层级。
16
+ 位移不取整卡高:一句话的轻提示整张推进来又快又远,读起来是一下猛冲;减弱动效下位移归零,只剩淡入 */
16
17
  @keyframes xh-notification-stack-in {
17
18
  from {
18
19
  opacity: var(--xh-_enter-from-opacity, 0);
19
- translate: 0 calc(var(--xh-_notification-stack-dir, 1) * (var(--xh-_notification-offset, 0px) - var(--xh-motion-travel)));
20
+ translate: 0 calc(var(--xh-_notification-stack-dir, 1) * (var(--xh-_notification-offset, 0px) - var(--xh-_notification-travel, var(--xh-motion-distance-lg))));
20
21
  scale: var(--xh-notification-stack-scale, var(--xh-_notification-stack-scale));
21
22
  }
22
23
 
@@ -36,7 +37,7 @@
36
37
 
37
38
  to {
38
39
  opacity: 0;
39
- translate: 0 calc(var(--xh-_notification-stack-dir, 1) * (var(--xh-_notification-y, 0px) - var(--xh-motion-travel)));
40
+ translate: 0 calc(var(--xh-_notification-stack-dir, 1) * (var(--xh-_notification-y, 0px) - var(--xh-_notification-travel, var(--xh-motion-distance-lg))));
40
41
  scale: var(--xh-_notification-scale, 1);
41
42
  }
42
43
  }
@@ -142,7 +143,7 @@
142
143
  */
143
144
  .xh-scope-notification[data-part='group'][data-stacked] {
144
145
  inset: auto;
145
- inline-size: min(var(--xh-notification-item-w, var(--xh-overlay-max-w-lg)), calc(100vw - var(--xh-space-8)));
146
+ inline-size: min(var(--xh-notification-item-w, var(--xh-overlay-notification-w)), calc(100vw - var(--xh-space-8)));
146
147
  block-size: 0;
147
148
  padding: 0;
148
149
  }
@@ -218,8 +219,9 @@
218
219
  /*
219
220
  * 一张通知:底与描边一律中性,面走 sheet 三件套(--xh-material-elevated-bg / -border / -shadow,
220
221
  * 亮暗两档同有 1px 描边)。两种预设共用这张面,排版分开写在下面:
221
- * 卡片是两列网格,左列一枚类型字形、右列「标题 + 说明 + 操作」、叉钉在右上角;
222
- * 轻提示是一行,行首字形、文本列、操作钮与叉依次排开。
222
+ * 卡片是两列网格,左列一枚 24px 类型字形、右列「标题 + 说明 + 操作」、叉钉在右上角,
223
+ * 缺省宽 300px、四边内衬 20px(--xh-overlay-notification-p,紧凑 16px)、浮层圆角;
224
+ * 轻提示是一行,行首字形、文本列、操作钮与叉依次排开,圆角取 control、内衬纵 10 横 16。
223
225
  *
224
226
  * 卡片的槽带 item 段(--xh-notification-item-*),与摞的 --xh-notification-inset 分开。
225
227
  */
@@ -235,12 +237,12 @@
235
237
  align-items: start;
236
238
  column-gap: var(--xh-notification-item-gap, var(--xh-space-3));
237
239
  row-gap: var(--xh-notification-item-row-gap, var(--xh-space-2));
238
- inline-size: var(--xh-notification-item-w, var(--xh-overlay-max-w-lg));
240
+ inline-size: var(--xh-notification-item-w, var(--xh-overlay-notification-w));
239
241
  /* 摞是整面视口宽的定位面且带内边距,取 100% 就等于自动让出两侧留白,
240
242
  窄屏上不必再算一遍 viewport 减法 */
241
243
  max-inline-size: 100%;
242
- padding-block: var(--xh-notification-item-py, var(--xh-surface-pad-lg));
243
- padding-inline: var(--xh-notification-item-px, var(--xh-surface-pad-lg));
244
+ padding-block: var(--xh-notification-item-py, var(--xh-overlay-notification-p));
245
+ padding-inline: var(--xh-notification-item-px, var(--xh-overlay-notification-p));
244
246
  border: var(--xh-stroke-thin) solid var(--xh-notification-item-border, var(--xh-material-elevated-border));
245
247
  border-radius: var(--xh-notification-item-radius, var(--xh-shape-overlay));
246
248
  background: var(--xh-notification-item-bg, var(--xh-material-elevated-bg));
@@ -251,8 +253,8 @@
251
253
  /* 摞的定位面整面铺开且不吃指针,卡片必须自己吃回来:
252
254
  悬停按住计时、按钮可点、焦点进出,全指着这一条 */
253
255
  pointer-events: auto;
254
- /* 换位:一张卡收起或新卡插进来时,列表动效先按旧位置反向补偿,再由这条过渡带回新位置 */
255
- transition: translate var(--xh-motion-duration-move) var(--xh-motion-ease-continuous);
256
+ /* 换位(一张卡收起、被挤掉或新卡插进来)由列表动效在 transform 上播一段:时长读 move、曲线读 continuous,
257
+ 与进退场关键帧的 translate 叠加,这里不写过渡。叠成一摞时另有自己的过渡清单(见下) */
256
258
  }
257
259
 
258
260
  /* 轻提示:一行排开,行首那一格贴着内容盒的起始角,文本列与两颗钮在行里垂直居中。
@@ -263,8 +265,10 @@
263
265
  align-items: flex-start;
264
266
  column-gap: var(--xh-notification-item-gap, var(--xh-space-2));
265
267
  inline-size: var(--xh-notification-item-w, var(--xh-overlay-toast-w));
266
- padding-block: var(--xh-notification-item-py, var(--xh-space-3));
268
+ padding-block: var(--xh-notification-item-py, var(--xh-space-2_5));
267
269
  padding-inline: var(--xh-notification-item-px, var(--xh-space-4));
270
+ /* 一行短消息不是一块面板,形状取 control */
271
+ border-radius: var(--xh-notification-item-radius, var(--xh-shape-control));
268
272
  font-size: var(--xh-notification-item-font-size, var(--xh-text-label-size));
269
273
  /* 叠摞几何常驻:单独摆放时是恒等位移与比例,放进叠放的一摞后由那边换成层深,
270
274
  两处用同一套画法,卡片进出一摞时栅格不跳 */
@@ -301,6 +305,53 @@
301
305
  animation: xh-sheet-out var(--xh-motion-duration-exit) var(--xh-motion-ease-exit) forwards;
302
306
  }
303
307
 
308
+ /* 还在台上就被移出队列的卡片(超出上限被挤掉、dismiss / dismissAll 直接删)没有自己的退场,
309
+ 列表动效在原处放一个替身(data-state="closed"),同一条退场播完即撤 */
310
+ .xh-scope-notification[data-part='item'][data-state='closed'] {
311
+ animation: xh-sheet-out var(--xh-motion-duration-exit) var(--xh-motion-ease-exit) forwards;
312
+ }
313
+
314
+ /*
315
+ * 逐条排开的卡片预设:从所贴的那条边整张推进来,边推边淡入——贴行尾的从行尾进、贴行首的从行首进,
316
+ * 居中的三个位从各自贴的那条边(顶 / 底)进,中线那一行只上浮一小段。位移是卡片自身的整宽或整高
317
+ * (--xh-motion-travel),减弱动效下归零,只剩淡入。退场只淡出,不往回推:空位由换位把后面的卡平滑收拢。
318
+ * 方向从所在那一摞的 data-placement 选过来,九个位是固定的枚举
319
+ */
320
+ .xh-scope-notification[data-part='group']:not([data-stacked]) .xh-scope-notification[data-part='item'][data-preset='card'] {
321
+ --xh-_enter-from-opacity: 0;
322
+ --xh-_slide-from-x: 0;
323
+ --xh-_slide-from-y: var(--xh-motion-distance-lg);
324
+ }
325
+
326
+ .xh-scope-notification[data-part='group']:not([data-stacked])[data-placement$='-end'] .xh-scope-notification[data-part='item'][data-preset='card'] {
327
+ --xh-_slide-from-x: calc(var(--xh-motion-travel) * var(--xh-direction-sign));
328
+ --xh-_slide-from-y: 0;
329
+ }
330
+
331
+ .xh-scope-notification[data-part='group']:not([data-stacked])[data-placement$='-start'] .xh-scope-notification[data-part='item'][data-preset='card'] {
332
+ --xh-_slide-from-x: calc(var(--xh-motion-travel) * var(--xh-direction-sign) * -1);
333
+ --xh-_slide-from-y: 0;
334
+ }
335
+
336
+ .xh-scope-notification[data-part='group']:not([data-stacked])[data-placement='top'] .xh-scope-notification[data-part='item'][data-preset='card'] {
337
+ --xh-_slide-from-y: calc(var(--xh-motion-travel) * -1);
338
+ }
339
+
340
+ .xh-scope-notification[data-part='group']:not([data-stacked])[data-placement='bottom'] .xh-scope-notification[data-part='item'][data-preset='card'] {
341
+ --xh-_slide-from-y: var(--xh-motion-travel);
342
+ }
343
+
344
+ .xh-scope-notification[data-part='group']:not([data-stacked]) .xh-scope-notification[data-part='item'][data-preset='card'][data-state='visible'] {
345
+ animation:
346
+ xh-slide-in var(--xh-motion-duration-enter) var(--xh-motion-ease-enter-strong) backwards,
347
+ xh-slide-fade-in var(--xh-motion-duration-enter) var(--xh-motion-ease-enter) backwards;
348
+ animation-delay: calc(var(--xh-_stagger-index, 0) * var(--xh-motion-stagger-step));
349
+ }
350
+
351
+ .xh-scope-notification[data-part='group']:not([data-stacked]) .xh-scope-notification[data-part='item'][data-preset='card']:is([data-state='dismissing'], [data-state='closed']) {
352
+ animation: xh-fade-out var(--xh-motion-duration-exit) var(--xh-motion-ease-exit) forwards;
353
+ }
354
+
304
355
  /*
305
356
  * 叠放的一摞:最新一条在最前,后层按层深逐层收拢——层深由叠摞测量写进来,每往后一层乘一次
306
357
  * --xh-motion-scale-stack;减弱动效下那支令牌为 1,层与层只靠位移分开。
@@ -310,6 +361,7 @@
310
361
  --xh-_notification-stack-scale: max(0, 1 - var(--xh-_notification-depth, 0) * (1 - var(--xh-motion-scale-stack)));
311
362
  --xh-_notification-y: var(--xh-_notification-offset, 0px);
312
363
  --xh-_notification-scale: var(--xh-notification-stack-scale, var(--xh-_notification-stack-scale));
364
+ --xh-_notification-travel: var(--xh-motion-distance-lg);
313
365
 
314
366
  position: absolute;
315
367
  inset-inline: 0;
@@ -347,6 +399,12 @@
347
399
  animation: xh-notification-stack-out var(--xh-motion-duration-exit) var(--xh-motion-ease-exit) forwards;
348
400
  }
349
401
 
402
+ /* 后层的卡片(到时先走的旧条目)与被挤掉的那条的替身原地淡出:它们压在最前那张后面,
403
+ 再沿叠放方向退就会从前面那张底下穿过去。叠摞测量在它开始退场时已把它移出排位,其余几条同时补上来 */
404
+ .xh-scope-notification[data-part='group'][data-stacked] .xh-scope-notification[data-part='item']:is([data-state='dismissing']:not([data-frontmost]), [data-state='closed']) {
405
+ animation: xh-fade-out var(--xh-motion-duration-exit) var(--xh-motion-ease-exit) forwards;
406
+ }
407
+
350
408
  /* 收拢的后层只露出一截边:高度压成最前那一条,内容淡出,免得几层字叠在一起 */
351
409
  .xh-scope-notification[data-part='group'][data-stacked] .xh-scope-notification[data-part='item'][data-stack-index]:not([data-frontmost]):not([data-expanded]) {
352
410
  block-size: var(--xh-_notification-front-height, auto);
@@ -394,7 +452,7 @@
394
452
  .xh-scope-notification[data-part='item'][data-preset='toast']::after {
395
453
  content: '';
396
454
  position: absolute;
397
- inset-block-start: var(--xh-notification-item-py, var(--xh-space-3));
455
+ inset-block-start: var(--xh-notification-item-py, var(--xh-space-2_5));
398
456
  inset-inline-start: var(--xh-notification-item-px, var(--xh-space-4));
399
457
  inline-size: var(--xh-icon-size, var(--xh-glyph-size-text));
400
458
  block-size: var(--xh-icon-size, var(--xh-glyph-size-text));
@@ -431,9 +489,11 @@
431
489
  }
432
490
 
433
491
  /* 卡片:独占第一列第一行,并与标题首行顶对齐:盒高取一行标题的行高,
434
- 字形在盒里居中,标题字号改了也不会错位 */
492
+ 字形在盒里居中,标题字号改了也不会错位。卡片的类型字形 24px,与 16px 标题的一行(24px)同高 */
435
493
  .xh-scope-notification[data-part='item-indicator'] {
436
- --xh-icon-size: var(--xh-notification-indicator-size, var(--xh-glyph-size-md));
494
+ --xh-icon-size: var(--xh-notification-indicator-size, var(--xh-glyph-size-lg));
495
+ /* 加载环随语气色(加载环配方缺省取品牌色),与语气字形同一支 */
496
+ --xh-_loading-ring-fg: var(--xh-notification-indicator-fg, var(--xh-_tone-fg));
437
497
 
438
498
  grid-column: 1;
439
499
  grid-row: 1;
@@ -441,13 +501,15 @@
441
501
  display: inline-flex;
442
502
  align-items: center;
443
503
  justify-content: center;
444
- block-size: calc(var(--xh-notification-title-font-size, var(--xh-text-label-size)) * var(--xh-leading-tight));
445
- inline-size: var(--xh-notification-indicator-size, var(--xh-glyph-size-md));
504
+ block-size: calc(var(--xh-notification-title-font-size, var(--xh-text-heading-3-size)) * var(--xh-leading-normal));
505
+ inline-size: var(--xh-notification-indicator-size, var(--xh-glyph-size-lg));
446
506
  color: var(--xh-notification-indicator-fg, var(--xh-_tone-fg));
447
507
  }
448
508
 
449
- /* 轻提示:方盒自带一圈内衬,与间距合起来让出字形到正文的那段距离 */
509
+ /* 轻提示:字形取 md 档 20px;方盒自带一圈内衬,与间距合起来让出字形到正文的那段距离 */
450
510
  .xh-scope-notification[data-part='item'][data-preset='toast'] [data-part='item-indicator']:where(.xh-scope-notification) {
511
+ --xh-icon-size: var(--xh-notification-indicator-size, var(--xh-glyph-size-md));
512
+
451
513
  flex: none;
452
514
  box-sizing: content-box;
453
515
  inline-size: var(--xh-icon-size, var(--xh-glyph-size-text));
@@ -523,19 +585,24 @@
523
585
  display: none;
524
586
  }
525
587
 
588
+ /* 卡片标题:面板标题档、正文色,一行 24px 与左列字形同高 */
526
589
  .xh-scope-notification[data-part='item-title'] {
527
590
  /* 作者可能把它写成 h2/p,外边距得先归零,否则卡片内的行距对不上 */
528
591
  margin: 0;
529
592
  color: var(--xh-notification-title-fg, var(--xh-fg-default));
530
- font-size: var(--xh-notification-title-font-size, var(--xh-text-label-size));
531
- font-weight: var(--xh-notification-title-font-weight, var(--xh-font-weight-semibold));
532
- line-height: var(--xh-notification-title-leading, var(--xh-leading-tight));
593
+ font-size: var(--xh-notification-title-font-size, var(--xh-text-heading-3-size));
594
+ font-weight: var(--xh-notification-title-font-weight, var(--xh-text-heading-3-weight));
595
+ line-height: var(--xh-notification-title-leading, var(--xh-leading-normal));
533
596
  }
534
597
 
535
- /* 轻提示的语气落到标题与行首字形:一句话的结果,颜色本身就是信息 */
598
+ /* 轻提示的语气落到标题与行首字形:一句话的结果,颜色本身就是信息。
599
+ 一行短消息取正文 14px / medium,不用卡片的面板标题档 */
536
600
  .xh-scope-notification[data-part='item'][data-preset='toast'] [data-part='item-title']:where(.xh-scope-notification) {
537
601
  min-inline-size: 0;
538
602
  color: var(--xh-notification-title-fg, var(--xh-_tone-fg));
603
+ font-size: var(--xh-notification-title-font-size, var(--xh-text-body-size));
604
+ font-weight: var(--xh-notification-title-font-weight, var(--xh-font-weight-medium));
605
+ line-height: var(--xh-notification-title-leading, var(--xh-leading-tight));
539
606
  }
540
607
 
541
608
  /* 卡片的叉钉在右上角,标题得给它让位;说明与操作在第二行往下,不受影响。
@@ -555,13 +622,16 @@
555
622
  max-block-size: var(--xh-notification-description-max-h, var(--xh-viewport-h-md));
556
623
  overflow-y: auto;
557
624
  overscroll-behavior: contain;
558
- color: var(--xh-notification-description-fg, var(--xh-fg-muted));
559
- font-size: var(--xh-notification-description-font-size, var(--xh-text-secondary-size));
625
+ /* 卡片的说明就是正文:14px 正文色 */
626
+ color: var(--xh-notification-description-fg, var(--xh-fg-default));
627
+ font-size: var(--xh-notification-description-font-size, var(--xh-text-body-size));
560
628
  }
561
629
 
562
- /* 轻提示的说明只是一行短上下文,行高收紧到正文之下 */
630
+ /* 轻提示的说明只是一行短上下文:说明档 13px 次级色,行高收紧到正文之下 */
563
631
  .xh-scope-notification[data-part='item'][data-preset='toast'] [data-part='item-description']:where(.xh-scope-notification) {
564
632
  min-inline-size: 0;
633
+ color: var(--xh-notification-description-fg, var(--xh-fg-muted));
634
+ font-size: var(--xh-notification-description-font-size, var(--xh-text-secondary-size));
565
635
  line-height: var(--xh-notification-description-leading, var(--xh-leading-normal));
566
636
  }
567
637
 
@@ -669,8 +739,9 @@
669
739
  display: none;
670
740
  }
671
741
 
672
- /* 关闭钮是只有字形的离散动作钮:盒几何、悬停 / 按下与 0.97 按压、粗指针热区、焦点环、禁用面全由 Action Control
673
- 的 icon ghost 档给(卡片投 sm:32px 正方盒;轻提示投 xs:24px,走行级动作钮那一档),组件只映射既有使用者槽。
742
+ /* 关闭钮是只有字形的离散动作钮:盒几何、悬停 / 按下与按压、粗指针热区、焦点环、禁用面全由 Action Control
743
+ 的 icon ghost 档给(卡片投 sm;轻提示投 xs,走行级动作钮那一档),组件只映射既有使用者槽。
744
+ 叉一律 12px(--xh-glyph-size-xs),比钮的随档字形低一档。
674
745
  静息透明,sheet 白面承载 hover 100 → pressed 200,写了语气时悬停底跟着语气走(--xh-_tone-subtle) */
675
746
  .xh-scope-notification[data-part='item-close-trigger'] {
676
747
  --xh-action-visual-size: var(--xh-notification-close-size, var(--xh-_action-profile-visual-size));
@@ -687,14 +758,26 @@
687
758
  --xh-action-shadow-rest: none;
688
759
  --xh-action-shadow-hover: none;
689
760
  --xh-action-shadow-pressed: none;
690
- /* 叉的字形按钮档取值,与行首那枚 md 档的类型字形分开 */
691
- --xh-icon-size: var(--xh-notification-icon-size, var(--xh-_action-profile-glyph-size));
761
+ /* 叉的字形与行首那枚类型字形分开取尺 */
762
+ --xh-icon-size: var(--xh-notification-icon-size, var(--xh-glyph-size-xs));
692
763
  }
693
764
 
694
- /* 卡片:钉在右上角的内衬处,不参与网格排布——留在流里它会变成正文下面的第三行 */
765
+ /* 卡片:钉在右上角,不参与网格排布——留在流里它会变成正文下面的第三行。
766
+ 距右取面内动作的内缩;竖向与标题首行同一条中线:上内衬加上「标题行高 − 钮边长」的一半
767
+ (舒适档 20 + (24 − 28) / 2 = 18、紧凑档 16 + (24 − 24) / 2 = 16),作者改了贴边槽仍按它两向一起贴 */
695
768
  .xh-scope-notification[data-part='item'][data-preset='card'] [data-part='item-close-trigger']:where(.xh-scope-notification) {
696
769
  position: absolute;
697
- inset-block-start: var(--xh-notification-close-inset, var(--xh-surface-action-inset));
770
+ inset-block-start: var(
771
+ --xh-notification-close-inset,
772
+ calc(
773
+ var(--xh-notification-item-py, var(--xh-overlay-notification-p)) +
774
+ (
775
+ var(--xh-notification-title-font-size, var(--xh-text-heading-3-size)) *
776
+ var(--xh-notification-title-leading, var(--xh-leading-normal)) -
777
+ var(--xh-notification-close-size, var(--xh-control-h-sm))
778
+ ) / 2
779
+ )
780
+ );
698
781
  inset-inline-end: var(--xh-notification-close-inset, var(--xh-surface-action-inset));
699
782
  }
700
783
 
@@ -35,10 +35,10 @@
35
35
  }
36
36
 
37
37
  .xh-scope-number-animation[data-part='root'][data-size='md'] {
38
- --xh-_number-animation-size: var(--xh-text-heading-2-size);
38
+ --xh-_number-animation-size: var(--xh-text-heading-1-size);
39
39
  }
40
40
 
41
41
  .xh-scope-number-animation[data-part='root'][data-size='lg'] {
42
- --xh-_number-animation-size: var(--xh-text-heading-1-size);
42
+ --xh-_number-animation-size: var(--xh-text-display-size);
43
43
  }
44
44
  }
@@ -28,9 +28,8 @@
28
28
  --xh-_number-field-gap: 0;
29
29
  --xh-_number-field-font-size: var(--xh-control-font-md);
30
30
  --xh-_number-field-trigger-font-size: var(--xh-control-font-md);
31
-
32
- /* 盒内那道分隔线的长度:取钮高的一半,线的上下各留一截空白,不与钮等高 */
33
- --xh-_number-field-divider-h: 50%;
31
+ /* 精细指针下上下叠放的两颗钮离盒边的内收:sm 档盒矮,收半档,两颗钮与 md 档等高 */
32
+ --xh-_number-field-stepper-inset: var(--xh-space-1);
34
33
 
35
34
  display: inline-flex;
36
35
  flex-direction: column;
@@ -56,6 +55,7 @@
56
55
  --xh-_number-field-px: var(--xh-control-px-sm);
57
56
  --xh-_number-field-font-size: var(--xh-control-font-sm);
58
57
  --xh-_number-field-trigger-font-size: var(--xh-control-font-sm);
58
+ --xh-_number-field-stepper-inset: var(--xh-space-0_5);
59
59
  }
60
60
 
61
61
  .xh-scope-number-field[data-part='root'][data-size='lg'] {
@@ -67,13 +67,15 @@
67
67
  }
68
68
 
69
69
  .xh-scope-number-field[data-part='label'] {
70
- color: var(--xh-number-field-label-fg, var(--xh-fg-default));
70
+ /* 竖排时标签与控件之间的距离:根的 gap 之上补一段差值,--xh-number-field-label-gap 给多少最终就是多少 */
71
+ margin-block-end: calc(var(--xh-number-field-label-gap, var(--xh-space-2)) - var(--xh-number-field-gap, var(--xh-space-1)));
72
+ color: var(--xh-number-field-label-fg, var(--xh-fg-muted));
71
73
  font-size: var(--xh-number-field-label-font-size, var(--xh-text-label-size));
72
74
  font-weight: var(--xh-number-field-label-font-weight, var(--xh-text-label-weight));
73
75
  }
74
76
 
75
77
  .xh-scope-number-field[data-part='label'][data-disabled] {
76
- color: var(--xh-number-field-label-fg-disabled, var(--xh-fg-subtle));
78
+ color: var(--xh-number-field-label-fg-disabled, var(--xh-fg-muted));
77
79
  }
78
80
 
79
81
  /* —— 一体式 control:输入框与加减钮同框 —— */
@@ -96,8 +98,6 @@
96
98
  --xh-field-border-hover: var(--xh-number-field-control-border-hover, var(--xh-_field-variant-border-hover));
97
99
  --xh-field-border-focus: var(--xh-number-field-control-border-focus, var(--xh-_field-variant-border-focus));
98
100
  --xh-field-border-invalid: var(--xh-number-field-control-border-invalid, var(--xh-_field-variant-border-invalid));
99
- --xh-field-ring-focus: var(--xh-ring-focus);
100
- --xh-field-ring-invalid: var(--xh-ring-invalid);
101
101
  --xh-field-shadow-rest: var(--xh-number-field-control-shadow, none);
102
102
  /* 家族 chrome 会重写 --xh-icon-size,使用者图标槽必须经桥接槽下发才能在盒内生效 */
103
103
  --xh-field-glyph-size: var(--xh-number-field-icon-size, var(--xh-_field-size-glyph-size));
@@ -119,7 +119,7 @@
119
119
  }
120
120
 
121
121
  /* 盒内 input:无边框无底无圆角无落影由家族重置,观感全归 control。
122
- 数字居中排在两个按钮之间,行内内衬留给它自己(control 不给内衬);
122
+ 数字从起始缘排起,与同一列里别的字段的文字对齐,行内内衬留给它自己(control 不给内衬);
123
123
  前后缀图标/文字直接流式排在 input 两侧,不用再绝对定位 */
124
124
  .xh-scope-number-field[data-part='control'] [data-part='input']:where(.xh-scope-number-field) {
125
125
  --xh-field-input-fg: var(--xh-number-field-input-fg, var(--xh-fg-default));
@@ -131,12 +131,13 @@
131
131
  inline-size: var(--xh-number-field-input-w, 5em);
132
132
  padding-inline: var(--xh-number-field-input-px, var(--xh-_number-field-px));
133
133
  font-variant-numeric: tabular-nums;
134
- text-align: var(--xh-number-field-input-align, center);
134
+ text-align: var(--xh-number-field-input-align, start);
135
135
  }
136
136
 
137
- /* 盒内按钮:正方视觉盒、inset 圆角、悬停 100 / 按下 200 与 0.97 按压、粗指针热区与
138
- :focus-visible 关环全由 Action Control 的 field-inset ghost 档给,组件只映射既有覆盖槽。
139
- 常态只剩符号,符号取默认前景,悬停与按下才浮出底色 */
137
+ /* 盒内按钮:正方视觉盒、inset 圆角、按承载面取的悬停 / 按下阶梯、粗指针热区与 :focus-visible 关环
138
+ 全由 Action Control 的 field-inset ghost 档给,组件只映射既有覆盖槽。
139
+ 常态只剩符号,符号取次要前景(钮是辅助动作,不与数字抢层级),悬停与按下才浮出底色。
140
+ 可悬停的精细指针下平时收起、悬停或聚焦字段时显出(家族 hover-focus 档),并改成上下叠放,见下 */
140
141
  .xh-scope-number-field[data-part='control'] [data-part='increment-trigger']:where(.xh-scope-number-field),
141
142
  .xh-scope-number-field[data-part='control'] [data-part='decrement-trigger']:where(.xh-scope-number-field) {
142
143
  --xh-action-visual-size: var(--xh-number-field-trigger-size, var(--xh-_action-profile-visual-size));
@@ -144,7 +145,7 @@
144
145
  --xh-action-radius: var(--xh-number-field-trigger-radius, var(--xh-shape-inset));
145
146
  /* 底色阶梯由 ghost 档给(透明 → 100 → 200),使用者槽只作覆盖入口 */
146
147
  --xh-action-bg-pressed: var(--xh-number-field-trigger-bg-active, var(--xh-_action-variant-bg-pressed));
147
- --xh-action-fg-rest: var(--xh-number-field-trigger-fg, var(--xh-fg-default));
148
+ --xh-action-fg-rest: var(--xh-number-field-trigger-fg, var(--xh-fg-muted));
148
149
  --xh-action-fg-hover: var(--xh-number-field-trigger-fg-hover, var(--xh-fg-default));
149
150
  --xh-action-border-rest: transparent;
150
151
  --xh-action-highlight-rest: transparent;
@@ -172,25 +173,6 @@
172
173
  display: none;
173
174
  }
174
175
 
175
- /* 右侧动作组与输入之间的细线:把「按的」与「填的」分成两块。
176
- 线不画在钮的边框上:边框会跟着钮的圆角与悬停底走,而这道线要独立于钮的各态,长度也短于钮自己。
177
- ::before 已被兜底字形占着,::after 在粗指针下是家族给的 44px 热区,几何只能落在
178
- background-image 上:一条 1px × 半高的渐变贴在逻辑起始侧,底色换态时它仍叠在上层。
179
- 线只画在动作组第一颗减钮的逻辑起始侧;background-position 是物理轴,RTL 另给一条换边。 */
180
- .xh-scope-number-field[data-part='control']:has([data-part='input']) [data-part='decrement-trigger']:where(.xh-scope-number-field) {
181
- background-image: linear-gradient(
182
- var(--xh-number-field-trigger-divider, var(--xh-material-soft-separator)),
183
- var(--xh-number-field-trigger-divider, var(--xh-material-soft-separator))
184
- );
185
- background-repeat: no-repeat;
186
- background-position: 0 50%;
187
- background-size: var(--xh-stroke-thin) var(--xh-number-field-trigger-divider-h, var(--xh-_number-field-divider-h));
188
- }
189
-
190
- [dir='rtl'] .xh-scope-number-field[data-part='control']:has([data-part='input']) [data-part='decrement-trigger']:where(.xh-scope-number-field) {
191
- background-position: 100% 50%;
192
- }
193
-
194
176
  /* 没写内容就由皮肤画兜底字形;作者往部件里塞了自己的图形,这几条即不命中 */
195
177
  .xh-scope-number-field[data-part='control'] [data-part='increment-trigger']:where(.xh-scope-number-field):empty::before {
196
178
  content: '';
@@ -214,11 +196,52 @@
214
196
  mask: var(--xh-glyph-mark-minus) center / contain no-repeat;
215
197
  }
216
198
 
217
- /* 高对比档整层丢弃 background-image,分隔线改用系统色重画,并关掉这一颗钮的强制换色 */
218
- @media (forced-colors: active) {
219
- .xh-scope-number-field[data-part='control']:has([data-part='input']) [data-part='decrement-trigger']:where(.xh-scope-number-field) {
220
- background-image: linear-gradient(ButtonText, ButtonText);
221
- forced-color-adjust: none;
199
+ /* 可悬停的精细指针:两颗钮上下叠在盒的逻辑末端,各占盒高一半(四周内收一截),宽取指示符大档;
200
+ 显出时铺一层淡底,悬停 / 按下沿淡底阶梯升一档、两档,字形换成上下箭头、取指示符最小档:
201
+ 一颗钮只有盒内高的一半减内收(sm / md 11px,紧凑 9px),小档 12px 的字形会比钮高出一截。
202
+ 两颗钮共边相接,按下只换面不缩放。钮浮在盒上、不占流:盒的末端让出钮那一截,
203
+ 输入与后缀不会排到钮底下,钮收起时也不跳。粗指针与不能悬停的设备仍是两颗正方钮横排在末端、常显,
204
+ 那里一颗叠放的钮只有半个控件高,够不着触控目标尺寸 */
205
+ @media (hover: hover) and (pointer: fine) {
206
+ .xh-scope-number-field[data-part='control']:has([data-part='increment-trigger'], [data-part='decrement-trigger']) {
207
+ padding-inline-end: calc(
208
+ var(--xh-number-field-stepper-w, var(--xh-control-indicator-lg))
209
+ + 2 * var(--xh-number-field-stepper-inset, var(--xh-_number-field-stepper-inset))
210
+ );
211
+ }
212
+
213
+ .xh-scope-number-field[data-part='control'] [data-part='increment-trigger']:where(.xh-scope-number-field),
214
+ .xh-scope-number-field[data-part='control'] [data-part='decrement-trigger']:where(.xh-scope-number-field) {
215
+ --xh-action-bg-rest: var(--xh-number-field-stepper-bg, var(--xh-bg-subtle));
216
+ --xh-action-bg-hover: var(--xh-number-field-stepper-bg-hover, var(--xh-bg-subtle-hover));
217
+ --xh-action-bg-pressed: var(--xh-number-field-trigger-bg-active, var(--xh-bg-subtle-active));
218
+ --xh-action-bg-disabled: var(--xh-number-field-stepper-bg, var(--xh-bg-subtle));
219
+ --xh-action-scale-pressed: none;
220
+ --xh-icon-size: var(--xh-control-indicator-xs);
221
+
222
+ position: absolute;
223
+ inset-inline-end: var(--xh-number-field-stepper-inset, var(--xh-_number-field-stepper-inset));
224
+ inline-size: var(--xh-number-field-stepper-w, var(--xh-control-indicator-lg));
225
+ min-inline-size: 0;
226
+ block-size: calc(50% - var(--xh-number-field-stepper-inset, var(--xh-_number-field-stepper-inset)));
227
+ }
228
+
229
+ .xh-scope-number-field[data-part='control'] [data-part='increment-trigger']:where(.xh-scope-number-field) {
230
+ inset-block-start: var(--xh-number-field-stepper-inset, var(--xh-_number-field-stepper-inset));
231
+ }
232
+
233
+ .xh-scope-number-field[data-part='control'] [data-part='decrement-trigger']:where(.xh-scope-number-field) {
234
+ inset-block-end: var(--xh-number-field-stepper-inset, var(--xh-_number-field-stepper-inset));
235
+ }
236
+
237
+ .xh-scope-number-field[data-part='control'] [data-part='increment-trigger']:where(.xh-scope-number-field):empty::before {
238
+ -webkit-mask-image: var(--xh-glyph-mark-chevron-up);
239
+ mask-image: var(--xh-glyph-mark-chevron-up);
240
+ }
241
+
242
+ .xh-scope-number-field[data-part='control'] [data-part='decrement-trigger']:where(.xh-scope-number-field):empty::before {
243
+ -webkit-mask-image: var(--xh-glyph-mark-chevron-down);
244
+ mask-image: var(--xh-glyph-mark-chevron-down);
222
245
  }
223
246
  }
224
247
 
@@ -5,6 +5,9 @@
5
5
 
6
6
  /* 定义 page header 样式。 */
7
7
 
8
+ /* 返回钮接动作钮家族:独立引入本皮肤时同样带上家族配方,full bundle 递归去重。 */
9
+ @import '../family/action-control.css';
10
+
8
11
  @layer xihan.components {
9
12
  /* 皮肤在场的标记:开发模式下按 scope 探一次,取不到就说明这份皮肤没被引入。 */
10
13
  .xh-scope-page-header {
@@ -14,16 +17,17 @@
14
17
  .xh-scope-page-header[data-part='root'] {
15
18
  /* 尺寸档只换这三个私有槽,各段从根上继承它们,换档不必给每个部件各写一条选择器 */
16
19
  --xh-_page-header-py: var(--xh-space-4);
17
- --xh-_page-header-row-gap: var(--xh-space-2);
18
- --xh-_page-header-title-size: var(--xh-text-heading-3-size);
20
+ --xh-_page-header-row-gap: var(--xh-space-1);
21
+ --xh-_page-header-title-size: var(--xh-text-heading-2-size);
19
22
  /* 形态档只换这两个:不画面的那一档左右不留内衬、也不切圆角 */
20
23
  --xh-_page-header-px: 0;
21
24
  --xh-_page-header-radius: 0;
22
25
 
23
- /* 返回、媒体、标题区与操作区分列;标题与说明上下排列。 */
26
+ /* 返回、媒体、标题、副标题与操作区分列:副标题跟在标题后面同一行,中间一条竖线隔开。
27
+ 标题列按内容宽、但能收到 0,副标题列至少留下竖线与一个字:不可断的长标题在列内断行,不把页头撑出容器 */
24
28
  display: grid;
25
29
  grid-auto-flow: dense;
26
- grid-template-columns: auto auto minmax(0, 1fr) auto;
30
+ grid-template-columns: auto auto minmax(0, max-content) minmax(min-content, 1fr) auto;
27
31
  align-items: center;
28
32
  row-gap: var(--xh-page-header-row-gap, var(--xh-_page-header-row-gap));
29
33
  padding-block: var(--xh-page-header-py, var(--xh-_page-header-py));
@@ -40,21 +44,26 @@
40
44
  /* —— 尺寸 —— */
41
45
  .xh-scope-page-header[data-part='root'][data-size='sm'] {
42
46
  --xh-_page-header-py: var(--xh-space-3);
43
- --xh-_page-header-row-gap: var(--xh-space-1);
47
+ --xh-_page-header-row-gap: var(--xh-space-0_5);
44
48
  --xh-_page-header-title-size: var(--xh-control-font-lg);
45
49
  }
46
50
 
47
51
  .xh-scope-page-header[data-part='root'][data-size='lg'] {
48
52
  --xh-_page-header-py: var(--xh-space-6);
49
- --xh-_page-header-row-gap: var(--xh-space-3);
50
- --xh-_page-header-title-size: var(--xh-text-heading-2-size);
53
+ --xh-_page-header-row-gap: var(--xh-space-2);
54
+ --xh-_page-header-title-size: var(--xh-text-heading-1-size);
55
+ }
56
+
57
+ /* 带面包屑的缺省档上下收一档:面包屑本身已在标题之上占了一行 */
58
+ .xh-scope-page-header[data-part='root']:not([data-size='sm'], [data-size='lg']):has(> [data-part='breadcrumb']) {
59
+ --xh-_page-header-py: var(--xh-space-3);
51
60
  }
52
61
 
53
62
  /* —— 分隔线 —— */
54
63
  /* 只有贴底的 ghost 画这条下边线:一块切了圆角的面底下横一条直线,两头会露在圆角外面,
55
64
  有面的两档由自己的边界接手同一件事——把页头与下面的内容分开 */
56
65
  .xh-scope-page-header[data-part='root'][data-variant='ghost'][data-split] {
57
- border-block-end: var(--xh-stroke-thin) solid var(--xh-page-header-border, var(--xh-border-subtle));
66
+ border-block-end: var(--xh-stroke-thin) solid var(--xh-page-header-border, var(--xh-border-default));
58
67
  }
59
68
 
60
69
  /* —— 形态 —— */
@@ -96,13 +105,14 @@
96
105
  justify-content: center;
97
106
  }
98
107
 
99
- /* 返回位只摆位置与对齐,外观归作者自己的按钮 */
108
+ /* 返回位是 icon ghost 档的动作钮:盒与三态面由家族给,这里只摆位置并把字色压到次级前景 */
100
109
  .xh-scope-page-header[data-part='back-trigger'] {
110
+ --xh-action-fg-rest: var(--xh-page-header-back-fg, var(--xh-fg-muted));
111
+ --xh-action-fg-hover: var(--xh-page-header-back-fg-hover, var(--xh-fg-default));
112
+ --xh-action-fg-pressed: var(--xh-page-header-back-fg-hover, var(--xh-fg-default));
113
+
101
114
  grid-column: 1;
102
115
  margin-inline-end: var(--xh-page-header-column-gap, var(--xh-space-3));
103
- display: inline-flex;
104
- align-items: center;
105
- justify-content: center;
106
116
  }
107
117
 
108
118
  .xh-scope-page-header[data-part='title'] {
@@ -115,23 +125,36 @@
115
125
  color: var(--xh-page-header-title-fg, var(--xh-fg-default));
116
126
  font-size: var(--xh-page-header-title-font-size, var(--xh-_page-header-title-size));
117
127
  /* 页面级标题:字重走标题档令牌,不直接下探字重原语 */
118
- font-weight: var(--xh-page-header-title-font-weight, var(--xh-text-heading-3-weight));
128
+ font-weight: var(--xh-page-header-title-font-weight, var(--xh-text-heading-2-weight));
119
129
  line-height: var(--xh-leading-tight);
120
130
  }
121
131
 
122
- /* 副标题吃掉标题与操作之间的剩余宽度,长文本在这里收窄换行 */
132
+ /* 副标题跟在标题后面、吃掉到操作区之间的剩余宽度,长文本在这里收窄换行;
133
+ 与标题之间一条 1 × 16px 的竖线,两侧各 12px */
123
134
  .xh-scope-page-header[data-part='description'] {
124
- grid-column: 3;
135
+ grid-column: 4;
136
+ display: flex;
137
+ align-items: center;
125
138
  margin: 0;
126
139
  min-inline-size: 0;
127
- color: var(--xh-page-header-description-fg, var(--xh-fg-muted));
128
- font-size: var(--xh-page-header-description-font-size, var(--xh-text-secondary-size));
140
+ color: var(--xh-page-header-description-fg, var(--xh-fg-subtle));
141
+ font-size: var(--xh-page-header-description-font-size, var(--xh-text-body-size));
129
142
  line-height: var(--xh-leading-normal);
130
143
  }
131
144
 
145
+ .xh-scope-page-header[data-part='title'] + .xh-scope-page-header[data-part='description']::before {
146
+ content: '';
147
+ flex: none;
148
+ align-self: center;
149
+ inline-size: var(--xh-stroke-thin);
150
+ block-size: var(--xh-glyph-size-sm);
151
+ margin-inline: var(--xh-space-3);
152
+ background: var(--xh-page-header-divider, var(--xh-border-default));
153
+ }
154
+
132
155
  /* 操作区贴到行尾,没有副标题占位时也一样靠边 */
133
156
  .xh-scope-page-header[data-part='extra'] {
134
- grid-column: 4;
157
+ grid-column: 5;
135
158
  display: flex;
136
159
  flex-wrap: wrap;
137
160
  align-items: center;
@@ -140,21 +163,17 @@
140
163
  justify-self: end;
141
164
  }
142
165
 
143
- /* 页脚占满一整行,前面有内容时自然被挤到下一行 */
166
+ /* 页脚占满一整行,前面有内容时自然被挤到下一行;与标题行之间再让出 12px */
144
167
  .xh-scope-page-header[data-part='footer'] {
145
168
  grid-column: 1 / -1;
169
+ margin-block-start: var(--xh-space-3);
146
170
  color: var(--xh-page-header-footer-fg, var(--xh-fg-muted));
147
171
  font-size: var(--xh-page-header-footer-font-size, var(--xh-text-secondary-size));
148
172
  line-height: var(--xh-leading-normal);
149
173
  }
150
174
 
151
- .xh-scope-page-header[data-part='root']:has(> [data-part='description'])
152
- > :is([data-part='back-trigger'], [data-part='media'], [data-part='extra']):where(.xh-scope-page-header) {
153
- grid-row: span 2;
154
- }
155
-
156
- /* 窄于 sm 断点时标题区占满第二列、操作区换到下一行。写成 min-width 的补集:640px 本身归宽档,
157
- 与其余皮肤在同一宽度切换 */
175
+ /* 窄于 sm 断点时标题区占满第二列、副标题回到标题下一行、操作区换到再下一行。
176
+ 写成 min-width 的补集:640px 本身归宽档,与其余皮肤在同一宽度切换 */
158
177
  @media not all and (min-width: 640px) {
159
178
  .xh-scope-page-header[data-part='root'] {
160
179
  grid-template-columns: auto minmax(0, 1fr);
@@ -166,6 +185,15 @@
166
185
  grid-column: 2;
167
186
  }
168
187
 
188
+ .xh-scope-page-header[data-part='title'] + .xh-scope-page-header[data-part='description']::before {
189
+ display: none;
190
+ }
191
+
192
+ .xh-scope-page-header[data-part='root']:has(> [data-part='description'])
193
+ > :is([data-part='back-trigger'], [data-part='media']):where(.xh-scope-page-header) {
194
+ grid-row: span 2;
195
+ }
196
+
169
197
  .xh-scope-page-header[data-part='root'] > [data-part='extra']:where(.xh-scope-page-header) {
170
198
  grid-column: 1 / -1;
171
199
  grid-row: auto;
@@ -174,10 +202,19 @@
174
202
  }
175
203
  }
176
204
 
205
+ /* 强制色:标题与副标题之间的竖线是底色画的,系统换掉底色线就消失,改写 CanvasText */
206
+ @media (forced-colors: active) {
207
+ .xh-scope-page-header[data-part='title'] + .xh-scope-page-header[data-part='description']::before {
208
+ forced-color-adjust: none;
209
+ background: CanvasText;
210
+ }
211
+ }
212
+
177
213
  /* 声明过任何 display 就盖掉了 UA 的 [hidden]{display:none},收起态得自己还回去。
178
214
  写在文件末尾:兜底必须排在该部件所有 display 声明之后 */
179
215
  .xh-scope-page-header[data-part='back-trigger'][hidden],
180
216
  .xh-scope-page-header[data-part='media'][hidden],
217
+ .xh-scope-page-header[data-part='description'][hidden],
181
218
  .xh-scope-page-header[data-part='extra'][hidden] {
182
219
  display: none;
183
220
  }