@xihan-ui/styles 3.1.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 (290) hide show
  1. package/CHANGELOG.md +470 -0
  2. package/component-tokens.d.ts +230 -60
  3. package/components.tokens.json +5156 -1557
  4. package/css/accordion.css +47 -20
  5. package/css/alert.css +16 -17
  6. package/css/anchor.css +2 -2
  7. package/css/approval.css +41 -17
  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 +13 -12
  15. package/css/calendar-picker.css +178 -95
  16. package/css/calendar-range-picker.css +207 -122
  17. package/css/card.css +34 -6
  18. package/css/carousel.css +94 -46
  19. package/css/cartesian-chart.css +11 -11
  20. package/css/cascader.css +51 -39
  21. package/css/checkbox-group.css +9 -6
  22. package/css/checkbox.css +5 -4
  23. package/css/citation.css +9 -4
  24. package/css/clipboard.css +20 -4
  25. package/css/code-view.css +6 -6
  26. package/css/collapsible.css +29 -14
  27. package/css/color-field.css +4 -4
  28. package/css/color-picker.css +77 -23
  29. package/css/color-slider.css +10 -8
  30. package/css/color-swatch-picker.css +14 -9
  31. package/css/combobox.css +26 -14
  32. package/css/command.css +14 -9
  33. package/css/context-menu.css +10 -5
  34. package/css/date-field.css +12 -6
  35. package/css/date-picker.css +178 -109
  36. package/css/date-range-picker.css +199 -130
  37. package/css/description.css +10 -6
  38. package/css/descriptions.css +47 -19
  39. package/css/dialog.css +50 -35
  40. package/css/diff-view.css +8 -8
  41. package/css/drawer.css +75 -21
  42. package/css/editable.css +15 -41
  43. package/css/empty-state.css +21 -3
  44. package/css/field-array.css +5 -2
  45. package/css/field.css +17 -18
  46. package/css/fieldset.css +33 -13
  47. package/css/file-upload.css +66 -33
  48. package/css/float-button.css +60 -35
  49. package/css/floating-panel.css +1 -1
  50. package/css/form.css +30 -16
  51. package/css/graph-chart.css +2 -2
  52. package/css/grid-list.css +1 -1
  53. package/css/highlight.css +5 -5
  54. package/css/hover-card.css +19 -12
  55. package/css/image-viewer.css +77 -27
  56. package/css/image.css +13 -5
  57. package/css/infinite-scroll.css +8 -4
  58. package/css/input-group.css +74 -26
  59. package/css/kbd.css +1 -1
  60. package/css/label.css +27 -11
  61. package/css/layout.css +17 -10
  62. package/css/list.css +13 -9
  63. package/css/listbox.css +12 -7
  64. package/css/loading-bar.css +3 -0
  65. package/css/mention.css +11 -9
  66. package/css/menu.css +10 -5
  67. package/css/menubar.css +13 -8
  68. package/css/message-feed.css +1 -1
  69. package/css/navigation-menu.css +2 -2
  70. package/css/notification.css +132 -49
  71. package/css/number-animation.css +2 -2
  72. package/css/number-field.css +75 -52
  73. package/css/page-header.css +64 -27
  74. package/css/pagination.css +35 -38
  75. package/css/password-input.css +12 -68
  76. package/css/pin-input.css +18 -26
  77. package/css/popconfirm.css +23 -14
  78. package/css/popover.css +18 -12
  79. package/css/progress.css +14 -13
  80. package/css/prompt-input.css +3 -3
  81. package/css/question-flow.css +41 -15
  82. package/css/radar-chart.css +6 -6
  83. package/css/radio-group.css +120 -55
  84. package/css/rating.css +32 -15
  85. package/css/select.css +16 -12
  86. package/css/separator.css +24 -6
  87. package/css/side-nav.css +29 -24
  88. package/css/signature-pad.css +23 -9
  89. package/css/skeleton.css +12 -12
  90. package/css/slider.css +77 -48
  91. package/css/sortable.css +2 -2
  92. package/css/sparkline.css +8 -2
  93. package/css/spinner.css +40 -20
  94. package/css/statistic.css +14 -14
  95. package/css/steps.css +115 -84
  96. package/css/switch.css +9 -7
  97. package/css/table.css +29 -12
  98. package/css/tabs.css +35 -12
  99. package/css/tag-group.css +17 -6
  100. package/css/tag.css +54 -29
  101. package/css/tags-input.css +39 -20
  102. package/css/text-field.css +5 -5
  103. package/css/time-field.css +4 -4
  104. package/css/time-picker.css +150 -64
  105. package/css/time-range-picker.css +91 -62
  106. package/css/timeline.css +37 -20
  107. package/css/timer.css +3 -3
  108. package/css/toggle-group.css +4 -4
  109. package/css/tool-call.css +13 -11
  110. package/css/toolbar.css +6 -5
  111. package/css/tooltip.css +16 -17
  112. package/css/tour.css +14 -7
  113. package/css/transfer.css +22 -16
  114. package/css/tree-select.css +12 -12
  115. package/css/tree.css +26 -25
  116. package/css/typography.css +28 -25
  117. package/dist/css/accordion.css +296 -0
  118. package/dist/css/affix.css +47 -0
  119. package/dist/css/alert.css +246 -0
  120. package/dist/css/anchor.css +252 -0
  121. package/dist/css/approval.css +525 -0
  122. package/dist/css/avatar-group.css +96 -0
  123. package/dist/css/avatar.css +100 -0
  124. package/dist/css/back-top.css +175 -0
  125. package/dist/css/badge.css +205 -0
  126. package/dist/css/bar-code.css +62 -0
  127. package/dist/css/breadcrumb.css +232 -0
  128. package/dist/css/button-group.css +261 -0
  129. package/dist/css/button.css +216 -0
  130. package/dist/css/calendar-picker.css +550 -0
  131. package/dist/css/calendar-range-picker.css +639 -0
  132. package/dist/css/card.css +249 -0
  133. package/dist/css/carousel.css +726 -0
  134. package/dist/css/cartesian-chart.css +830 -0
  135. package/dist/css/cascader.css +973 -0
  136. package/dist/css/checkbox-group.css +361 -0
  137. package/dist/css/checkbox.css +258 -0
  138. package/dist/css/citation.css +475 -0
  139. package/dist/css/clipboard.css +331 -0
  140. package/dist/css/code-view.css +374 -0
  141. package/dist/css/collapsible.css +200 -0
  142. package/dist/css/color-field.css +176 -0
  143. package/dist/css/color-picker.css +649 -0
  144. package/dist/css/color-slider.css +283 -0
  145. package/dist/css/color-swatch-picker.css +250 -0
  146. package/dist/css/color-swatch.css +35 -0
  147. package/dist/css/combobox.css +578 -0
  148. package/dist/css/command.css +404 -0
  149. package/dist/css/context-menu.css +425 -0
  150. package/dist/css/date-field.css +317 -0
  151. package/dist/css/date-picker.css +931 -0
  152. package/dist/css/date-range-picker.css +949 -0
  153. package/dist/css/description.css +71 -0
  154. package/dist/css/descriptions.css +327 -0
  155. package/dist/css/dialog.css +470 -0
  156. package/dist/css/diff-view.css +513 -0
  157. package/dist/css/download-trigger.css +151 -0
  158. package/dist/css/drawer.css +606 -0
  159. package/dist/css/editable.css +269 -0
  160. package/dist/css/empty-state.css +181 -0
  161. package/dist/css/field-array.css +229 -0
  162. package/dist/css/field.css +165 -0
  163. package/dist/css/fieldset.css +122 -0
  164. package/dist/css/file-upload.css +462 -0
  165. package/dist/css/flex.css +441 -0
  166. package/dist/css/float-button.css +579 -0
  167. package/dist/css/floating-panel.css +429 -0
  168. package/dist/css/focus.css +46 -0
  169. package/dist/css/forced-colors.css +93 -0
  170. package/dist/css/form.css +407 -0
  171. package/dist/css/funnel-chart.css +106 -0
  172. package/dist/css/graph-chart.css +205 -0
  173. package/dist/css/grid-list.css +235 -0
  174. package/dist/css/grid.css +1201 -0
  175. package/dist/css/heatmap.css +552 -0
  176. package/dist/css/hierarchy-chart.css +298 -0
  177. package/dist/css/highlight.css +41 -0
  178. package/dist/css/hover-card.css +233 -0
  179. package/dist/css/icon.css +225 -0
  180. package/dist/css/image-cropper.css +373 -0
  181. package/dist/css/image-viewer.css +588 -0
  182. package/dist/css/image.css +106 -0
  183. package/dist/css/infinite-scroll.css +81 -0
  184. package/dist/css/input-group.css +323 -0
  185. package/dist/css/json-viewer.css +379 -0
  186. package/dist/css/kbd.css +72 -0
  187. package/dist/css/label.css +94 -0
  188. package/dist/css/layers.css +7 -0
  189. package/dist/css/layout.css +379 -0
  190. package/dist/css/liquid.css +106 -0
  191. package/dist/css/list.css +156 -0
  192. package/dist/css/listbox.css +395 -0
  193. package/dist/css/loading-bar.css +144 -0
  194. package/dist/css/log.css +306 -0
  195. package/dist/css/markdown-stream.css +149 -0
  196. package/dist/css/marquee.css +378 -0
  197. package/dist/css/masonry.css +70 -0
  198. package/dist/css/matrix-code.css +67 -0
  199. package/dist/css/mention.css +395 -0
  200. package/dist/css/menu.css +369 -0
  201. package/dist/css/menubar.css +461 -0
  202. package/dist/css/message-feed.css +318 -0
  203. package/dist/css/navigation-menu.css +513 -0
  204. package/dist/css/notification.css +865 -0
  205. package/dist/css/number-animation.css +44 -0
  206. package/dist/css/number-field.css +275 -0
  207. package/dist/css/overlay-arrow.css +56 -0
  208. package/dist/css/page-header.css +221 -0
  209. package/dist/css/pagination.css +447 -0
  210. package/dist/css/password-input.css +335 -0
  211. package/dist/css/pie-chart.css +247 -0
  212. package/dist/css/pin-input.css +191 -0
  213. package/dist/css/pointer.css +36 -0
  214. package/dist/css/popconfirm.css +329 -0
  215. package/dist/css/popover.css +285 -0
  216. package/dist/css/progress.css +502 -0
  217. package/dist/css/prompt-input.css +260 -0
  218. package/dist/css/question-flow.css +579 -0
  219. package/dist/css/radar-chart.css +233 -0
  220. package/dist/css/radio-group.css +663 -0
  221. package/dist/css/rating.css +311 -0
  222. package/dist/css/reasoning.css +343 -0
  223. package/dist/css/reset.css +117 -0
  224. package/dist/css/resizable.css +242 -0
  225. package/dist/css/sankey-chart.css +174 -0
  226. package/dist/css/scroll-area.css +240 -0
  227. package/dist/css/scrollbar.css +204 -0
  228. package/dist/css/select.css +616 -0
  229. package/dist/css/separator.css +140 -0
  230. package/dist/css/side-nav.css +481 -0
  231. package/dist/css/signature-pad.css +193 -0
  232. package/dist/css/skeleton.css +161 -0
  233. package/dist/css/slider.css +403 -0
  234. package/dist/css/sortable.css +228 -0
  235. package/dist/css/sparkline.css +170 -0
  236. package/dist/css/spinner.css +256 -0
  237. package/dist/css/splitter.css +159 -0
  238. package/dist/css/statistic.css +137 -0
  239. package/dist/css/steps.css +658 -0
  240. package/dist/css/switch.css +353 -0
  241. package/dist/css/table.css +1162 -0
  242. package/dist/css/tabs.css +967 -0
  243. package/dist/css/tag-group.css +258 -0
  244. package/dist/css/tag.css +335 -0
  245. package/dist/css/tags-input.css +341 -0
  246. package/dist/css/text-field.css +197 -0
  247. package/dist/css/time-field.css +277 -0
  248. package/dist/css/time-picker.css +793 -0
  249. package/dist/css/time-range-picker.css +775 -0
  250. package/dist/css/timeline.css +440 -0
  251. package/dist/css/timer.css +123 -0
  252. package/dist/css/timestamp.css +34 -0
  253. package/dist/css/toggle-group.css +424 -0
  254. package/dist/css/toggle.css +146 -0
  255. package/dist/css/tone.css +189 -0
  256. package/dist/css/tool-call.css +431 -0
  257. package/dist/css/toolbar.css +366 -0
  258. package/dist/css/tooltip.css +217 -0
  259. package/dist/css/tour.css +446 -0
  260. package/dist/css/transfer.css +644 -0
  261. package/dist/css/tree-select.css +878 -0
  262. package/dist/css/tree.css +734 -0
  263. package/dist/css/truncate.css +108 -0
  264. package/dist/css/typography.css +475 -0
  265. package/dist/css/undefined.css +58 -0
  266. package/dist/css/virtualizer.css +166 -0
  267. package/dist/css/visually-hidden.css +20 -0
  268. package/dist/css/watermark.css +82 -0
  269. package/dist/family/action-control.css +493 -0
  270. package/dist/family/chart.css +537 -0
  271. package/dist/family/check-mark.css +94 -0
  272. package/dist/family/choice-card.css +97 -0
  273. package/dist/family/collection-item.css +768 -0
  274. package/dist/family/field-chrome.css +296 -0
  275. package/dist/family/loading-ring.css +102 -0
  276. package/dist/family/material.css +72 -0
  277. package/dist/family/menu-choice.css +56 -0
  278. package/dist/family/motion.css +363 -0
  279. package/dist/family/swatch.css +59 -0
  280. package/dist/family/tag-list.css +65 -0
  281. package/family/action-control.css +33 -36
  282. package/family/chart.css +57 -0
  283. package/family/collection-item.css +12 -8
  284. package/family/field-chrome.css +28 -19
  285. package/family/loading-ring.css +20 -13
  286. package/family/swatch.css +4 -4
  287. package/family/tag-list.css +6 -0
  288. package/index.css +10349 -8756
  289. package/index.unlayered.css +10350 -8758
  290. package/package.json +165 -164
@@ -0,0 +1,44 @@
1
+ /*
2
+ * Copyright (c) 2021-Present XiHanFun and contributors.
3
+ * Licensed under the MIT License. See LICENSE in the project root for license information.
4
+ */
5
+
6
+ /* 定义 number animation 样式。 */
7
+
8
+ @layer xihan.components {
9
+ /* 皮肤在场的标记:开发模式下按 scope 探一次,取不到就说明这份皮肤没被引入。 */
10
+ .xh-scope-number-animation {
11
+ --xh-number-animation-skin: 1;
12
+ }
13
+
14
+ .xh-scope-number-animation[data-part='root'] {
15
+ /* 不写尺寸就跟着上下文的字号走:这个数常常摆在别人的标题、卡片标题或统计数值槽里,
16
+ 自带一个字号只会跟摆放它的地方打架。三个档位各自换掉这个私有槽 */
17
+ --xh-_number-animation-size: inherit;
18
+
19
+ display: inline-block;
20
+ color: var(--xh-number-animation-fg, var(--xh-_tone-fg, var(--xh-fg-default)));
21
+ font-size: var(--xh-number-animation-font-size, var(--xh-_number-animation-size));
22
+ /* 等宽数字:逐位宽度一致,逐帧换数时后面的字符不会左右挪动,整块也不会一跳一跳地变宽 */
23
+ font-variant-numeric: tabular-nums;
24
+ line-height: var(--xh-leading-tight);
25
+ }
26
+
27
+ /* 上面声明了 display,会盖掉 UA 的 [hidden] 规则,收起态要在这里接回来 */
28
+ .xh-scope-number-animation[data-part='root'][hidden] {
29
+ display: none;
30
+ }
31
+
32
+ /* —— 尺寸 —— */
33
+ .xh-scope-number-animation[data-part='root'][data-size='sm'] {
34
+ --xh-_number-animation-size: var(--xh-control-font-lg);
35
+ }
36
+
37
+ .xh-scope-number-animation[data-part='root'][data-size='md'] {
38
+ --xh-_number-animation-size: var(--xh-text-heading-1-size);
39
+ }
40
+
41
+ .xh-scope-number-animation[data-part='root'][data-size='lg'] {
42
+ --xh-_number-animation-size: var(--xh-text-display-size);
43
+ }
44
+ }
@@ -0,0 +1,275 @@
1
+ /*
2
+ * Copyright (c) 2021-Present XiHanFun and contributors.
3
+ * Licensed under the MIT License. See LICENSE in the project root for license information.
4
+ */
5
+
6
+ /* NumberField 独立皮肤同时传递引入字段视觉盒与字段内动作;full bundle 递归去重。 */
7
+ @import '../family/field-chrome.css';
8
+ @import '../family/action-control.css';
9
+
10
+ @layer xihan.components {
11
+ /* 皮肤在场的标记:开发模式下按 scope 探一次,取不到就说明这份皮肤没被引入。 */
12
+ .xh-scope-number-field {
13
+ --xh-number-field-skin: 1;
14
+ }
15
+
16
+ /* 与文本框同一套堆叠:标签一行、输入行一行。
17
+ control 是必需的唯一视觉盒,输入框、加减钮与前后缀都放在里面;
18
+ 输入与前后缀在左,减、加两颗动作依次收在逻辑末端。
19
+ 组件层只把既有公开槽映射到家族合同;形态三档由家族按 control 上的 data-variant 生成,皮肤不再声明。 */
20
+ .xh-scope-number-field[data-part='root'] {
21
+ /* 作者塞进来的图标跟着控件的尺寸档走;它自己写了 size 时仍以作者的为准 */
22
+ --xh-icon-size: var(--xh-number-field-icon-size, var(--xh-glyph-size-md));
23
+
24
+ /* 尺寸档只换这几个私有槽,输入框与加减钮都从 root 继承它们,
25
+ 换档不必给每个部件各写一条选择器 */
26
+ --xh-_number-field-h: var(--xh-control-h-md);
27
+ --xh-_number-field-px: var(--xh-control-px-md);
28
+ --xh-_number-field-gap: 0;
29
+ --xh-_number-field-font-size: var(--xh-control-font-md);
30
+ --xh-_number-field-trigger-font-size: var(--xh-control-font-md);
31
+ /* 精细指针下上下叠放的两颗钮离盒边的内收:sm 档盒矮,收半档,两颗钮与 md 档等高 */
32
+ --xh-_number-field-stepper-inset: var(--xh-space-1);
33
+
34
+ display: inline-flex;
35
+ flex-direction: column;
36
+ gap: var(--xh-number-field-gap, var(--xh-space-1));
37
+
38
+ /* 不传尺寸时一律这么宽,宽度不随内容走;父容器给不出这么宽时整件跟着收,地板同步让步,不越出父容器。
39
+ 地板不高过缺省宽:使用者把缺省宽钉到底线以下时不必再放开底线 */
40
+ inline-size: var(--xh-number-field-control-w, var(--xh-control-w));
41
+ min-inline-size: min(var(--xh-number-field-control-w, var(--xh-control-w)), var(--xh-number-field-control-min-w, var(--xh-control-min-w)), 100%);
42
+ max-inline-size: 100%;
43
+ }
44
+
45
+ /* 声明了 display 就盖掉了 UA 的 [hidden]{display:none},收起态得自己还回去 */
46
+ .xh-scope-number-field[data-part='root'][hidden] {
47
+ display: none;
48
+ }
49
+
50
+ /* —— 尺寸 —— */
51
+ /* 缺省档写在上面的基础规则里 */
52
+ .xh-scope-number-field[data-part='root'][data-size='sm'] {
53
+ --xh-icon-size: var(--xh-number-field-icon-size, var(--xh-glyph-size-sm));
54
+ --xh-_number-field-h: var(--xh-control-h-sm);
55
+ --xh-_number-field-px: var(--xh-control-px-sm);
56
+ --xh-_number-field-font-size: var(--xh-control-font-sm);
57
+ --xh-_number-field-trigger-font-size: var(--xh-control-font-sm);
58
+ --xh-_number-field-stepper-inset: var(--xh-space-0_5);
59
+ }
60
+
61
+ .xh-scope-number-field[data-part='root'][data-size='lg'] {
62
+ --xh-icon-size: var(--xh-number-field-icon-size, var(--xh-glyph-size-lg));
63
+ --xh-_number-field-h: var(--xh-control-h-lg);
64
+ --xh-_number-field-px: var(--xh-control-px-lg);
65
+ --xh-_number-field-font-size: var(--xh-control-font-lg);
66
+ --xh-_number-field-trigger-font-size: var(--xh-control-font-lg);
67
+ }
68
+
69
+ .xh-scope-number-field[data-part='label'] {
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));
73
+ font-size: var(--xh-number-field-label-font-size, var(--xh-text-label-size));
74
+ font-weight: var(--xh-number-field-label-font-weight, var(--xh-text-label-weight));
75
+ }
76
+
77
+ .xh-scope-number-field[data-part='label'][data-disabled] {
78
+ color: var(--xh-number-field-label-fg-disabled, var(--xh-fg-muted));
79
+ }
80
+
81
+ /* —— 一体式 control:输入框与加减钮同框 —— */
82
+ /* control 是唯一的视觉盒:描边、底色、圆角、聚焦环、五态与悬停由 Field Chrome 家族画,
83
+ 盒内三件都退成透明分段,整枚控件从头到尾只有这一道描边。
84
+ 外观槽按所在部件取名 --xh-number-field-control-*;--xh-number-field-input-* 只管
85
+ input 自己的字色与内衬。控件不给内衬:内衬走 input 与钮各自的盒。 */
86
+ .xh-scope-number-field[data-part='control'] {
87
+ --xh-field-control-height: var(--xh-number-field-control-h, var(--xh-_number-field-h));
88
+ --xh-field-control-padding-inline: var(--xh-number-field-control-px, 0);
89
+ --xh-field-control-gap: var(--xh-number-field-control-gap, var(--xh-_number-field-gap));
90
+ --xh-field-control-min-inline-size: var(--xh-number-field-control-min-w, var(--xh-control-min-w));
91
+ --xh-field-control-radius: var(--xh-number-field-control-radius, var(--xh-shape-control));
92
+ --xh-field-bg-rest: var(--xh-number-field-control-bg, var(--xh-_field-variant-bg-rest));
93
+ --xh-field-bg-hover: var(--xh-number-field-control-bg-hover, var(--xh-_field-variant-bg-hover));
94
+ --xh-field-bg-read-only: var(--xh-number-field-control-bg-readonly, var(--xh-_field-variant-bg-read-only));
95
+ --xh-field-bg-disabled: var(--xh-number-field-control-bg-disabled, var(--xh-_field-variant-bg-disabled));
96
+ --xh-field-fg-rest: var(--xh-number-field-control-fg, var(--xh-fg-default));
97
+ --xh-field-border-rest: var(--xh-number-field-control-border, var(--xh-_field-variant-border-rest));
98
+ --xh-field-border-hover: var(--xh-number-field-control-border-hover, var(--xh-_field-variant-border-hover));
99
+ --xh-field-border-focus: var(--xh-number-field-control-border-focus, var(--xh-_field-variant-border-focus));
100
+ --xh-field-border-invalid: var(--xh-number-field-control-border-invalid, var(--xh-_field-variant-border-invalid));
101
+ --xh-field-shadow-rest: var(--xh-number-field-control-shadow, none);
102
+ /* 家族 chrome 会重写 --xh-icon-size,使用者图标槽必须经桥接槽下发才能在盒内生效 */
103
+ --xh-field-glyph-size: var(--xh-number-field-icon-size, var(--xh-_field-size-glyph-size));
104
+
105
+ position: relative;
106
+ }
107
+
108
+ /* 装饰段:货币符、单位、图标。与输入框同框,不参与分宽,弱一档前景把它与数字分开 */
109
+ .xh-scope-number-field[data-part='prefix'],
110
+ .xh-scope-number-field[data-part='suffix'] {
111
+ --xh-field-affix-fg: var(--xh-number-field-affix-fg, var(--xh-fg-muted));
112
+ --xh-field-affix-fg-disabled: var(--xh-number-field-affix-fg-disabled, var(--xh-fg-disabled));
113
+ --xh-field-affix-font-size: var(--xh-number-field-affix-font-size, var(--xh-_number-field-font-size));
114
+ }
115
+
116
+ .xh-scope-number-field[data-part='prefix'][hidden],
117
+ .xh-scope-number-field[data-part='suffix'][hidden] {
118
+ display: none;
119
+ }
120
+
121
+ /* 盒内 input:无边框无底无圆角无落影由家族重置,观感全归 control。
122
+ 数字从起始缘排起,与同一列里别的字段的文字对齐,行内内衬留给它自己(control 不给内衬);
123
+ 前后缀图标/文字直接流式排在 input 两侧,不用再绝对定位 */
124
+ .xh-scope-number-field[data-part='control'] [data-part='input']:where(.xh-scope-number-field) {
125
+ --xh-field-input-fg: var(--xh-number-field-input-fg, var(--xh-fg-default));
126
+ --xh-field-input-font-size: var(--xh-number-field-input-font-size, var(--xh-_number-field-font-size));
127
+ --xh-field-placeholder-fg: var(--xh-number-field-placeholder-fg, var(--xh-fg-subtle));
128
+ --xh-field-autofill-bg: var(--xh-number-field-input-autofill-bg, var(--xh-bg-canvas));
129
+ --xh-field-autofill-fg: var(--xh-number-field-input-autofill-fg, var(--xh-fg-default));
130
+
131
+ inline-size: var(--xh-number-field-input-w, 5em);
132
+ padding-inline: var(--xh-number-field-input-px, var(--xh-_number-field-px));
133
+ font-variant-numeric: tabular-nums;
134
+ text-align: var(--xh-number-field-input-align, start);
135
+ }
136
+
137
+ /* 盒内按钮:正方视觉盒、inset 圆角、按承载面取的悬停 / 按下阶梯、粗指针热区与 :focus-visible 关环
138
+ 全由 Action Control 的 field-inset ghost 档给,组件只映射既有覆盖槽。
139
+ 常态只剩符号,符号取次要前景(钮是辅助动作,不与数字抢层级),悬停与按下才浮出底色。
140
+ 可悬停的精细指针下平时收起、悬停或聚焦字段时显出(家族 hover-focus 档),并改成上下叠放,见下 */
141
+ .xh-scope-number-field[data-part='control'] [data-part='increment-trigger']:where(.xh-scope-number-field),
142
+ .xh-scope-number-field[data-part='control'] [data-part='decrement-trigger']:where(.xh-scope-number-field) {
143
+ --xh-action-visual-size: var(--xh-number-field-trigger-size, var(--xh-_action-profile-visual-size));
144
+ --xh-action-min-inline-size: var(--xh-number-field-trigger-size, var(--xh-_action-profile-visual-size));
145
+ --xh-action-radius: var(--xh-number-field-trigger-radius, var(--xh-shape-inset));
146
+ /* 底色阶梯由 ghost 档给(透明 → 100 → 200),使用者槽只作覆盖入口 */
147
+ --xh-action-bg-pressed: var(--xh-number-field-trigger-bg-active, var(--xh-_action-variant-bg-pressed));
148
+ --xh-action-fg-rest: var(--xh-number-field-trigger-fg, var(--xh-fg-muted));
149
+ --xh-action-fg-hover: var(--xh-number-field-trigger-fg-hover, var(--xh-fg-default));
150
+ --xh-action-border-rest: transparent;
151
+ --xh-action-highlight-rest: transparent;
152
+ --xh-action-shadow-rest: none;
153
+ --xh-action-shadow-hover: none;
154
+ --xh-action-shadow-pressed: none;
155
+ --xh-action-font-size: var(--xh-number-field-trigger-font-size, var(--xh-_number-field-trigger-font-size));
156
+ /* 配方尚未把 profile 字形档灌进 --xh-icon-size,钮内字形先按 field-inset 档逐钮取值 */
157
+ --xh-icon-size: var(--xh-_action-profile-glyph-size);
158
+
159
+ border-width: 0;
160
+ }
161
+
162
+ /* DOM 顺序不承担视觉位置:既有用法即使把减钮写在 input 前面,默认仍统一收进右侧动作组。 */
163
+ .xh-scope-number-field[data-part='control'] [data-part='decrement-trigger']:where(.xh-scope-number-field) {
164
+ order: 1;
165
+ }
166
+
167
+ .xh-scope-number-field[data-part='control'] [data-part='increment-trigger']:where(.xh-scope-number-field) {
168
+ order: 2;
169
+ }
170
+
171
+ .xh-scope-number-field[data-part='control'] [data-part='increment-trigger'][hidden]:where(.xh-scope-number-field),
172
+ .xh-scope-number-field[data-part='control'] [data-part='decrement-trigger'][hidden]:where(.xh-scope-number-field) {
173
+ display: none;
174
+ }
175
+
176
+ /* 没写内容就由皮肤画兜底字形;作者往部件里塞了自己的图形,这几条即不命中 */
177
+ .xh-scope-number-field[data-part='control'] [data-part='increment-trigger']:where(.xh-scope-number-field):empty::before {
178
+ content: '';
179
+ display: inline-block;
180
+ inline-size: var(--xh-icon-size, var(--xh-glyph-size-text));
181
+ block-size: var(--xh-icon-size, var(--xh-glyph-size-text));
182
+ vertical-align: var(--xh-glyph-baseline-shift);
183
+ background-color: currentColor;
184
+ -webkit-mask: var(--xh-glyph-mark-plus) center / contain no-repeat;
185
+ mask: var(--xh-glyph-mark-plus) center / contain no-repeat;
186
+ }
187
+
188
+ .xh-scope-number-field[data-part='control'] [data-part='decrement-trigger']:where(.xh-scope-number-field):empty::before {
189
+ content: '';
190
+ display: inline-block;
191
+ inline-size: var(--xh-icon-size, var(--xh-glyph-size-text));
192
+ block-size: var(--xh-icon-size, var(--xh-glyph-size-text));
193
+ vertical-align: var(--xh-glyph-baseline-shift);
194
+ background-color: currentColor;
195
+ -webkit-mask: var(--xh-glyph-mark-minus) center / contain no-repeat;
196
+ mask: var(--xh-glyph-mark-minus) center / contain no-repeat;
197
+ }
198
+
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);
245
+ }
246
+ }
247
+
248
+ /* 声明过任何 display 就盖掉了 UA 的 [hidden]{display:none},收起态得自己还回去。
249
+ 写在文件末尾:兜底必须排在该部件所有 display 声明之后 */
250
+ .xh-scope-number-field[data-part='control'][hidden] {
251
+ display: none;
252
+ }
253
+
254
+ @media (forced-colors: active) {
255
+ /* 兜底字形是 mask 挖出来的一块底色,这一档里底色被系统换成 Canvas,字形跟着消失。
256
+ 字形退出强制换色、直接写系统色(不能取 currentColor:退出强制换色的伪元素读到的是被系统换掉之前的作者色):
257
+ 按钮面上取 ButtonText,悬停与按下时家族把按钮涂成 Highlight、字形换 HighlightText;
258
+ 禁用取 GrayText */
259
+ .xh-scope-number-field[data-part='control'] [data-part='increment-trigger']:where(.xh-scope-number-field):empty::before,
260
+ .xh-scope-number-field[data-part='control'] [data-part='decrement-trigger']:where(.xh-scope-number-field):empty::before {
261
+ forced-color-adjust: none;
262
+ background-color: ButtonText;
263
+ }
264
+
265
+ .xh-scope-number-field[data-part='control'] [data-part='increment-trigger']:where(.xh-scope-number-field):not([data-disabled]):not([data-loading]):is(:hover, :active, [data-pressed]):empty::before,
266
+ .xh-scope-number-field[data-part='control'] [data-part='decrement-trigger']:where(.xh-scope-number-field):not([data-disabled]):not([data-loading]):is(:hover, :active, [data-pressed]):empty::before {
267
+ background-color: HighlightText;
268
+ }
269
+
270
+ .xh-scope-number-field[data-part='control'] [data-part='increment-trigger'][data-disabled]:where(.xh-scope-number-field):empty::before,
271
+ .xh-scope-number-field[data-part='control'] [data-part='decrement-trigger'][data-disabled]:where(.xh-scope-number-field):empty::before {
272
+ background-color: GrayText;
273
+ }
274
+ }
275
+ }
@@ -0,0 +1,56 @@
1
+ /*
2
+ * Copyright (c) 2021-Present XiHanFun and contributors.
3
+ * Licensed under the MIT License. See LICENSE in the project root for license information.
4
+ */
5
+
6
+ /*
7
+ * 浮层箭头的几何,八类浮层共用一份,只匹配这些组件自身的 arrow 部件。
8
+ *
9
+ * 箭头是正方形转 45°,构成尖角的是哪两条物理边,所以贴边与摘边框都写物理属性。
10
+ * 行内轴上的中心点仍写逻辑属性:定位引擎在 RTL 下已把 arrow-x 镜像成逻辑量。
11
+ *
12
+ * 底色与描边色留在各组件皮肤,它们同时把自己的内联落点槽接到这里的统一名字上。
13
+ * 引入顺序排在消费方皮肤之后;作用域使用 :where,维持原有特异性和摘边优先级。
14
+ */
15
+ @layer xihan.components {
16
+ :where(.xh-scope-context-menu, .xh-scope-hover-card, .xh-scope-menu, .xh-scope-menubar, .xh-scope-popconfirm, .xh-scope-popover, .xh-scope-tour, .xh-scope-tooltip)[data-part='arrow'] {
17
+ position: absolute;
18
+ inline-size: var(--xh-_overlay-arrow-size);
19
+ block-size: var(--xh-_overlay-arrow-size);
20
+ rotate: 45deg;
21
+ }
22
+
23
+ /* 浮层落在锚点下方:箭头贴 content 上缘,摘掉埋进 content 的下、右两条边 */
24
+ :where(.xh-scope-context-menu, .xh-scope-hover-card, .xh-scope-menu, .xh-scope-menubar, .xh-scope-popconfirm, .xh-scope-popover, .xh-scope-tour, .xh-scope-tooltip)[data-part='arrow'][data-placement^='bottom'] {
25
+ top: calc(var(--xh-_overlay-arrow-size) / -2);
26
+ inset-inline-start: calc(var(--xh-_overlay-arrow-x) - var(--xh-_overlay-arrow-size) / 2);
27
+ border-right: 0;
28
+ border-bottom: 0;
29
+ }
30
+
31
+ /* 浮层落在锚点上方:箭头贴 content 下缘,摘掉上、左两条边 */
32
+ :where(.xh-scope-context-menu, .xh-scope-hover-card, .xh-scope-menu, .xh-scope-menubar, .xh-scope-popconfirm, .xh-scope-popover, .xh-scope-tour, .xh-scope-tooltip)[data-part='arrow'][data-placement^='top'] {
33
+ bottom: calc(var(--xh-_overlay-arrow-size) / -2);
34
+ inset-inline-start: calc(var(--xh-_overlay-arrow-x) - var(--xh-_overlay-arrow-size) / 2);
35
+ border-top: 0;
36
+ border-left: 0;
37
+ }
38
+
39
+ /* 浮层落在锚点右侧:箭头贴 content 左缘,摘掉上、右两条边 */
40
+ :where(.xh-scope-context-menu, .xh-scope-hover-card, .xh-scope-menu, .xh-scope-menubar, .xh-scope-popconfirm, .xh-scope-popover, .xh-scope-tour, .xh-scope-tooltip)[data-part='arrow'][data-placement^='right'] {
41
+ top: calc(var(--xh-_overlay-arrow-y) - var(--xh-_overlay-arrow-size) / 2);
42
+ /* stylelint-disable-next-line property-disallowed-list -- 旋转是物理的,贴边跟着物理走 */
43
+ left: calc(var(--xh-_overlay-arrow-size) / -2);
44
+ border-top: 0;
45
+ border-right: 0;
46
+ }
47
+
48
+ /* 浮层落在锚点左侧:箭头贴 content 右缘,摘掉下、左两条边 */
49
+ :where(.xh-scope-context-menu, .xh-scope-hover-card, .xh-scope-menu, .xh-scope-menubar, .xh-scope-popconfirm, .xh-scope-popover, .xh-scope-tour, .xh-scope-tooltip)[data-part='arrow'][data-placement^='left'] {
50
+ top: calc(var(--xh-_overlay-arrow-y) - var(--xh-_overlay-arrow-size) / 2);
51
+ /* stylelint-disable-next-line property-disallowed-list -- 旋转是物理的,贴边跟着物理走 */
52
+ right: calc(var(--xh-_overlay-arrow-size) / -2);
53
+ border-bottom: 0;
54
+ border-left: 0;
55
+ }
56
+ }
@@ -0,0 +1,221 @@
1
+ /*
2
+ * Copyright (c) 2021-Present XiHanFun and contributors.
3
+ * Licensed under the MIT License. See LICENSE in the project root for license information.
4
+ */
5
+
6
+ /* 定义 page header 样式。 */
7
+
8
+ /* 返回钮接动作钮家族:独立引入本皮肤时同样带上家族配方,full bundle 递归去重。 */
9
+ @import '../family/action-control.css';
10
+
11
+ @layer xihan.components {
12
+ /* 皮肤在场的标记:开发模式下按 scope 探一次,取不到就说明这份皮肤没被引入。 */
13
+ .xh-scope-page-header {
14
+ --xh-page-header-skin: 1;
15
+ }
16
+
17
+ .xh-scope-page-header[data-part='root'] {
18
+ /* 尺寸档只换这三个私有槽,各段从根上继承它们,换档不必给每个部件各写一条选择器 */
19
+ --xh-_page-header-py: var(--xh-space-4);
20
+ --xh-_page-header-row-gap: var(--xh-space-1);
21
+ --xh-_page-header-title-size: var(--xh-text-heading-2-size);
22
+ /* 形态档只换这两个:不画面的那一档左右不留内衬、也不切圆角 */
23
+ --xh-_page-header-px: 0;
24
+ --xh-_page-header-radius: 0;
25
+
26
+ /* 返回、媒体、标题、副标题与操作区分列:副标题跟在标题后面同一行,中间一条竖线隔开。
27
+ 标题列按内容宽、但能收到 0,副标题列至少留下竖线与一个字:不可断的长标题在列内断行,不把页头撑出容器 */
28
+ display: grid;
29
+ grid-auto-flow: dense;
30
+ grid-template-columns: auto auto minmax(0, max-content) minmax(min-content, 1fr) auto;
31
+ align-items: center;
32
+ row-gap: var(--xh-page-header-row-gap, var(--xh-_page-header-row-gap));
33
+ padding-block: var(--xh-page-header-py, var(--xh-_page-header-py));
34
+ padding-inline: var(--xh-page-header-px, var(--xh-_page-header-px));
35
+ border-radius: var(--xh-page-header-radius, var(--xh-_page-header-radius));
36
+ color: var(--xh-page-header-fg, var(--xh-fg-default));
37
+ }
38
+
39
+ /* 上面声明了 display,会盖掉 UA 的 [hidden] 规则,收起态要在这里接回来 */
40
+ .xh-scope-page-header[data-part='root'][hidden] {
41
+ display: none;
42
+ }
43
+
44
+ /* —— 尺寸 —— */
45
+ .xh-scope-page-header[data-part='root'][data-size='sm'] {
46
+ --xh-_page-header-py: var(--xh-space-3);
47
+ --xh-_page-header-row-gap: var(--xh-space-0_5);
48
+ --xh-_page-header-title-size: var(--xh-control-font-lg);
49
+ }
50
+
51
+ .xh-scope-page-header[data-part='root'][data-size='lg'] {
52
+ --xh-_page-header-py: var(--xh-space-6);
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);
60
+ }
61
+
62
+ /* —— 分隔线 —— */
63
+ /* 只有贴底的 ghost 画这条下边线:一块切了圆角的面底下横一条直线,两头会露在圆角外面,
64
+ 有面的两档由自己的边界接手同一件事——把页头与下面的内容分开 */
65
+ .xh-scope-page-header[data-part='root'][data-variant='ghost'][data-split] {
66
+ border-block-end: var(--xh-stroke-thin) solid var(--xh-page-header-border, var(--xh-border-default));
67
+ }
68
+
69
+ /* —— 形态 —— */
70
+ /* ghost 不在这儿:它就是上面那套基础取值,贴在页面底色上不画面。
71
+ 画了面的两档左右补上与上下同档的内衬,否则内容会贴着那块面的边 */
72
+ .xh-scope-page-header[data-part='root']:is([data-variant='outline'], [data-variant='subtle']) {
73
+ --xh-_page-header-px: var(--xh-_page-header-py);
74
+ --xh-_page-header-radius: var(--xh-shape-surface);
75
+ }
76
+
77
+ /* outline 是一张静态内容面:--xh-border-default 描边撑住这块面的边界 + surface 底,不叠投影;
78
+ --xh-border-subtle 只作 ghost 贴底那条分隔线用,不当根面外边 */
79
+ .xh-scope-page-header[data-part='root'][data-variant='outline'] {
80
+ border: var(--xh-stroke-thin) solid var(--xh-page-header-border, var(--xh-border-default));
81
+ background: var(--xh-page-header-bg, var(--xh-bg-surface));
82
+ }
83
+
84
+ /* subtle 用淡底当边界:描边让位给底色但留住 1px 边位(与 outline 同一几何)、无影 */
85
+ .xh-scope-page-header[data-part='root'][data-variant='subtle'] {
86
+ border: var(--xh-stroke-thin) solid transparent;
87
+ background: var(--xh-page-header-bg, var(--xh-bg-subtle));
88
+ }
89
+
90
+ /* —— 各段 —— */
91
+ /* 面包屑占满一整行排在标题之上:它写在标记的最前面,整行铺开就把标题挤到了下一行 */
92
+ .xh-scope-page-header[data-part='breadcrumb'] {
93
+ grid-column: 1 / -1;
94
+ color: var(--xh-page-header-breadcrumb-fg, var(--xh-fg-muted));
95
+ font-size: var(--xh-page-header-breadcrumb-font-size, var(--xh-text-secondary-size));
96
+ line-height: var(--xh-leading-normal);
97
+ }
98
+
99
+ /* 头像 / 图标位:不参与伸缩,图形本身多大由作者定 */
100
+ .xh-scope-page-header[data-part='media'] {
101
+ grid-column: 2;
102
+ 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
+ }
107
+
108
+ /* 返回位是 icon ghost 档的动作钮:盒与三态面由家族给,这里只摆位置并把字色压到次级前景 */
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
+
114
+ grid-column: 1;
115
+ margin-inline-end: var(--xh-page-header-column-gap, var(--xh-space-3));
116
+ }
117
+
118
+ .xh-scope-page-header[data-part='title'] {
119
+ grid-column: 3;
120
+ margin: 0;
121
+ /* 标题不参与伸缩,长过整行时收到行宽为止,中间没有断点的长串在行尾断开,
122
+ 不把整条页头撑出容器 */
123
+ max-inline-size: 100%;
124
+ overflow-wrap: anywhere;
125
+ color: var(--xh-page-header-title-fg, var(--xh-fg-default));
126
+ font-size: var(--xh-page-header-title-font-size, var(--xh-_page-header-title-size));
127
+ /* 页面级标题:字重走标题档令牌,不直接下探字重原语 */
128
+ font-weight: var(--xh-page-header-title-font-weight, var(--xh-text-heading-2-weight));
129
+ line-height: var(--xh-leading-tight);
130
+ }
131
+
132
+ /* 副标题跟在标题后面、吃掉到操作区之间的剩余宽度,长文本在这里收窄换行;
133
+ 与标题之间一条 1 × 16px 的竖线,两侧各 12px */
134
+ .xh-scope-page-header[data-part='description'] {
135
+ grid-column: 4;
136
+ display: flex;
137
+ align-items: center;
138
+ margin: 0;
139
+ min-inline-size: 0;
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));
142
+ line-height: var(--xh-leading-normal);
143
+ }
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
+
155
+ /* 操作区贴到行尾,没有副标题占位时也一样靠边 */
156
+ .xh-scope-page-header[data-part='extra'] {
157
+ grid-column: 5;
158
+ display: flex;
159
+ flex-wrap: wrap;
160
+ align-items: center;
161
+ gap: var(--xh-page-header-extra-gap, var(--xh-space-2));
162
+ margin-inline-start: var(--xh-page-header-column-gap, var(--xh-space-3));
163
+ justify-self: end;
164
+ }
165
+
166
+ /* 页脚占满一整行,前面有内容时自然被挤到下一行;与标题行之间再让出 12px */
167
+ .xh-scope-page-header[data-part='footer'] {
168
+ grid-column: 1 / -1;
169
+ margin-block-start: var(--xh-space-3);
170
+ color: var(--xh-page-header-footer-fg, var(--xh-fg-muted));
171
+ font-size: var(--xh-page-header-footer-font-size, var(--xh-text-secondary-size));
172
+ line-height: var(--xh-leading-normal);
173
+ }
174
+
175
+ /* 窄于 sm 断点时标题区占满第二列、副标题回到标题下一行、操作区换到再下一行。
176
+ 写成 min-width 的补集:640px 本身归宽档,与其余皮肤在同一宽度切换 */
177
+ @media not all and (min-width: 640px) {
178
+ .xh-scope-page-header[data-part='root'] {
179
+ grid-template-columns: auto minmax(0, 1fr);
180
+ }
181
+
182
+ .xh-scope-page-header[data-part='media'],
183
+ .xh-scope-page-header[data-part='title'],
184
+ .xh-scope-page-header[data-part='description'] {
185
+ grid-column: 2;
186
+ }
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
+
197
+ .xh-scope-page-header[data-part='root'] > [data-part='extra']:where(.xh-scope-page-header) {
198
+ grid-column: 1 / -1;
199
+ grid-row: auto;
200
+ margin-inline-start: 0;
201
+ justify-self: start;
202
+ }
203
+ }
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
+
213
+ /* 声明过任何 display 就盖掉了 UA 的 [hidden]{display:none},收起态得自己还回去。
214
+ 写在文件末尾:兜底必须排在该部件所有 display 声明之后 */
215
+ .xh-scope-page-header[data-part='back-trigger'][hidden],
216
+ .xh-scope-page-header[data-part='media'][hidden],
217
+ .xh-scope-page-header[data-part='description'][hidden],
218
+ .xh-scope-page-header[data-part='extra'][hidden] {
219
+ display: none;
220
+ }
221
+ }