@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,140 @@
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
+ /* 定义 separator 样式。 */
7
+
8
+ @layer xihan.components {
9
+ /* 皮肤在场的标记:开发模式下按 scope 探一次,取不到就说明这份皮肤没被引入。 */
10
+ .xh-scope-separator {
11
+ --xh-separator-skin: 1;
12
+ }
13
+
14
+ /*
15
+ * 线的颜色与线型都先收进两个私有槽,再由 root(只有它一个时)与 line(有分节文字时)
16
+ * 各自取用:换档只改槽,画在哪个节点上互不影响。
17
+ */
18
+ .xh-scope-separator[data-part='root'] {
19
+ --xh-_separator-color: var(--xh-separator-color, var(--xh-border-default));
20
+ --xh-_separator-dash: var(--xh-separator-dash-length, var(--xh-space-1_5));
21
+ --xh-_separator-dash-gap: var(--xh-separator-dash-gap, var(--xh-space-1_5));
22
+ --xh-_separator-paint: var(--xh-_separator-color);
23
+
24
+ border: 0;
25
+ border-radius: var(--xh-separator-radius, var(--xh-shape-pill));
26
+ background: var(--xh-_separator-paint);
27
+ }
28
+
29
+ /* 分隔线自带上下(竖向为左右)留白:横向上下各 20px,竖向左右各 12px,放进内容里不必另包一层加边距 */
30
+ .xh-scope-separator[data-part='root'][data-orientation='horizontal'] {
31
+ inline-size: 100%;
32
+ block-size: var(--xh-separator-thickness, var(--xh-stroke-thin));
33
+ margin-block: var(--xh-separator-my, var(--xh-space-5));
34
+ }
35
+
36
+ .xh-scope-separator[data-part='root'][data-orientation='vertical'] {
37
+ align-self: stretch;
38
+ inline-size: var(--xh-separator-thickness, var(--xh-stroke-thin));
39
+ block-size: 100%;
40
+ /* 父容器没有高度时也留一截与文字等高的线 */
41
+ min-block-size: var(--xh-glyph-size-text);
42
+ margin-inline: var(--xh-separator-mx, var(--xh-space-3));
43
+ }
44
+
45
+ /* —— 形态 ——
46
+ 三档只换线的深浅,缺省档写在上面的基础规则里。使用者槽排在档值前面,
47
+ 写了 --xh-separator-color 的那一条仍然压过档值 */
48
+ .xh-scope-separator[data-part='root'][data-variant='subtle'] {
49
+ --xh-_separator-color: var(--xh-separator-color, var(--xh-material-soft-separator));
50
+ }
51
+
52
+ .xh-scope-separator[data-part='root'][data-variant='strong'] {
53
+ --xh-_separator-color: var(--xh-separator-color, var(--xh-border-strong));
54
+ }
55
+
56
+ /* —— 虚线 ——
57
+ 实线段与空白段交替铺;方向由 data-orientation 选,表达式只写这两条 */
58
+ .xh-scope-separator[data-part='root'][data-dashed][data-orientation='horizontal'] {
59
+ --xh-_separator-paint: repeating-linear-gradient(
60
+ to right,
61
+ var(--xh-_separator-color) 0 var(--xh-_separator-dash),
62
+ transparent var(--xh-_separator-dash) calc(var(--xh-_separator-dash) + var(--xh-_separator-dash-gap))
63
+ );
64
+ }
65
+
66
+ .xh-scope-separator[data-part='root'][data-dashed][data-orientation='vertical'] {
67
+ --xh-_separator-paint: repeating-linear-gradient(
68
+ to bottom,
69
+ var(--xh-_separator-color) 0 var(--xh-_separator-dash),
70
+ transparent var(--xh-_separator-dash) calc(var(--xh-_separator-dash) + var(--xh-_separator-dash-gap))
71
+ );
72
+ }
73
+
74
+ /* —— 带分节文字的三段形态 ——
75
+ 渲染了 content 之后 root 改当容器:自己不再画线,线交给两条 line。
76
+ 形态由部件在不在决定,没有开关 */
77
+ .xh-scope-separator[data-part='root']:has([data-part='content']) {
78
+ display: flex;
79
+ align-items: center;
80
+ inline-size: 100%;
81
+ block-size: auto;
82
+ gap: var(--xh-separator-gap, var(--xh-space-4));
83
+ /* 文字自带一行行高,上下留白收一半,整段占的高度与单线时相当 */
84
+ margin-block: var(--xh-separator-my, var(--xh-space-2_5));
85
+ background: none;
86
+ }
87
+
88
+ .xh-scope-separator[data-part='root'][data-orientation='vertical']:has([data-part='content']) {
89
+ flex-direction: column;
90
+ inline-size: auto;
91
+ block-size: 100%;
92
+ }
93
+
94
+ /* 两条线等分剩下的地方;粗细与颜色跟 root 单节点时同源 */
95
+ .xh-scope-separator[data-part='line'] {
96
+ flex: 1 1 0;
97
+ border-radius: var(--xh-separator-radius, var(--xh-shape-pill));
98
+ background: var(--xh-_separator-paint);
99
+ }
100
+
101
+ .xh-scope-separator[data-part='line'][data-orientation='horizontal'] {
102
+ block-size: var(--xh-separator-thickness, var(--xh-stroke-thin));
103
+ }
104
+
105
+ .xh-scope-separator[data-part='line'][data-orientation='vertical'] {
106
+ inline-size: var(--xh-separator-thickness, var(--xh-stroke-thin));
107
+ }
108
+
109
+ /* 分节文字:不参与等分,也不折行 */
110
+ .xh-scope-separator[data-part='content'] {
111
+ flex: none;
112
+ color: var(--xh-separator-content-fg, var(--xh-fg-default));
113
+ font-size: var(--xh-separator-content-font-size, var(--xh-text-body-size));
114
+ font-weight: var(--xh-separator-content-font-weight, var(--xh-font-weight-medium));
115
+ line-height: var(--xh-leading-normal);
116
+ white-space: nowrap;
117
+ }
118
+
119
+ /* 文字靠边:靠哪边就把那一侧的线收成一小截,另一侧照旧等分 */
120
+ .xh-scope-separator[data-part='root'][data-align='start'] > [data-part='line']:where(.xh-scope-separator):first-child,
121
+ .xh-scope-separator[data-part='root'][data-align='end'] > [data-part='line']:where(.xh-scope-separator):last-child {
122
+ flex: 0 0 var(--xh-separator-align-length, var(--xh-space-6));
123
+ }
124
+
125
+ /* 强制色:线是底色(与虚线的渐变)画的,系统会把底色换成 Canvas,线就此消失。
126
+ 线退出强制换色、颜色直接取 CanvasText,实线与虚线同一条槽 */
127
+ @media (forced-colors: active) {
128
+ .xh-scope-separator:is([data-part='root'], [data-part='line']) {
129
+ --xh-_separator-color: CanvasText;
130
+
131
+ forced-color-adjust: none;
132
+ }
133
+ }
134
+
135
+ /* 声明过任何 display 就盖掉了 UA 的 [hidden]{display:none},收起态得自己还回去。
136
+ 写在文件末尾:兜底必须排在该部件所有 display 声明之后 */
137
+ .xh-scope-separator[data-part='root'][hidden] {
138
+ display: none;
139
+ }
140
+ }
@@ -0,0 +1,481 @@
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
+ /* 定义 side nav 样式。 */
7
+
8
+ /* 共享关键帧由 family/motion.css 提供,行走 Collection Item 家族,搜索框的重置与占位前景走字段家族;
9
+ 本皮肤 @import 它们,单独引入仍成立。 */
10
+ @import '../family/field-chrome.css';
11
+ @import '../family/collection-item.css';
12
+ @import '../family/motion.css';
13
+
14
+ /* 图标栏的名称提示就是库内的 Tooltip(data-scope="tooltip" 的 positioner 与 content),
15
+ 反白面、进退场与各环境档都由它的皮肤给;本皮肤 @import 它,单独引入仍成立 */
16
+ @import './tooltip.css';
17
+
18
+ @layer xihan.components {
19
+ /* 皮肤在场的标记:开发模式下按 scope 探一次,取不到就说明这份皮肤没被引入。 */
20
+ .xh-scope-side-nav {
21
+ --xh-side-nav-skin: 1;
22
+ }
23
+
24
+ /* 私有槽同时声明在根与定位层上:折叠态的弹出面板被搬到 portal 落点,
25
+ 不是根的后代,继承不过去。面板里的行与栏内那些消费的是同一批槽 */
26
+ .xh-scope-side-nav:is([data-part='root'], [data-part='positioner']) {
27
+ /* 行外的字形按档取尺,缺省 md,随 data-size 换档并同样声明在定位层上(弹出面板里的行也拿得到);
28
+ 行内的由家族随 data-xh-collection-size 下发。这支只管作者放进行里的图标:
29
+ 侧栏自绘的状态字形(分支行尾的展开方向 chevron)是指示符,branch-indicator 在自己身上
30
+ 把 --xh-icon-size 改接到 --xh-control-indicator-* 一族的盒尺 */
31
+ --xh-icon-size: var(--xh-side-nav-icon-size, var(--xh-glyph-size-md));
32
+
33
+ /* 尺寸档只换这三个私有槽,行从这两处继承它们,换档不必给每个部件各写一条选择器。
34
+ 行高取导航行的尺(比同档控件高一截) */
35
+ --xh-_side-nav-row-h: var(--xh-nav-row-h-md);
36
+ /* 面板内的搜索框是字段,高度仍走控件尺 */
37
+ --xh-_side-nav-input-h: var(--xh-control-h-md);
38
+ --xh-_side-nav-row-px: var(--xh-control-px-md);
39
+ --xh-_side-nav-row-gap: var(--xh-control-gap-md);
40
+ --xh-_side-nav-row-font-size: var(--xh-control-font-md);
41
+ }
42
+
43
+ /* —— 尺寸 —— */
44
+ /* 缺省档写在上面那条里 */
45
+ .xh-scope-side-nav:is([data-part='root'], [data-part='positioner'])[data-size='sm'] {
46
+ --xh-icon-size: var(--xh-side-nav-icon-size, var(--xh-glyph-size-sm));
47
+ --xh-_side-nav-row-h: var(--xh-nav-row-h-sm);
48
+ --xh-_side-nav-input-h: var(--xh-control-h-sm);
49
+ --xh-_side-nav-row-px: var(--xh-control-px-sm);
50
+ --xh-_side-nav-row-gap: var(--xh-control-gap-sm);
51
+ --xh-_side-nav-row-font-size: var(--xh-control-font-sm);
52
+ }
53
+
54
+ .xh-scope-side-nav:is([data-part='root'], [data-part='positioner'])[data-size='lg'] {
55
+ --xh-icon-size: var(--xh-side-nav-icon-size, var(--xh-glyph-size-lg));
56
+ --xh-_side-nav-row-h: var(--xh-nav-row-h-lg);
57
+ --xh-_side-nav-input-h: var(--xh-control-h-lg);
58
+ --xh-_side-nav-row-px: var(--xh-control-px-lg);
59
+ --xh-_side-nav-row-gap: var(--xh-control-gap-lg);
60
+ --xh-_side-nav-row-font-size: var(--xh-control-font-lg);
61
+ }
62
+
63
+ /* 展开与折叠两档宽度缺省取侧栏令牌,与 Layout 的侧栏同源 */
64
+ .xh-scope-side-nav[data-part='root'] {
65
+ inline-size: var(--xh-side-nav-w, var(--xh-sider-w));
66
+ display: flex;
67
+ flex-direction: column;
68
+ gap: var(--xh-side-nav-gap, var(--xh-space-1));
69
+ padding: var(--xh-side-nav-p, var(--xh-space-2));
70
+ color: var(--xh-side-nav-fg, var(--xh-fg-default));
71
+ /* 占位式侧栏折叠是屏内的尺寸变化:与 Layout 侧栏同一段 move、同一条曲线,放在侧栏里时两者一起收放 */
72
+ transition: inline-size var(--xh-motion-duration-move) var(--xh-motion-ease-continuous);
73
+ }
74
+
75
+ /* 折叠成图标栏:整栏收窄;行文字先淡出,收窄落定之后才裁掉(见下) */
76
+ .xh-scope-side-nav[data-part='root'][data-collapsed] {
77
+ inline-size: var(--xh-side-nav-collapsed-w, var(--xh-sider-collapsed-w));
78
+ }
79
+
80
+ /* 搜索框:面板内嵌搜索的写法——不画字段外壳,通栏一行,高与字号随尺寸档,只画一道面内分隔的下划线;
81
+ 重置与占位前景由字段家族按 data-xh-field-input 给,行内内衬与行同一支槽 */
82
+ .xh-scope-side-nav[data-part='input'] {
83
+ --xh-field-placeholder-fg: var(--xh-side-nav-placeholder-fg, var(--xh-fg-subtle));
84
+
85
+ flex: none;
86
+ min-inline-size: 0;
87
+ block-size: var(--xh-side-nav-input-h, var(--xh-_side-nav-input-h));
88
+ padding-block: 0;
89
+ padding-inline: var(--xh-side-nav-input-px, var(--xh-_side-nav-row-px));
90
+ border: none;
91
+ border-block-end: var(--xh-stroke-thin) solid var(--xh-side-nav-search-divider, var(--xh-material-solid-separator));
92
+ background: none;
93
+ color: inherit;
94
+ font-family: inherit;
95
+ font-size: var(--xh-side-nav-input-font-size, var(--xh-_side-nav-row-font-size));
96
+ line-height: var(--xh-leading-normal);
97
+ transition: opacity var(--xh-motion-duration-micro) var(--xh-motion-ease-enter);
98
+ }
99
+
100
+ /* 聚焦不画环:插入符就是焦点指示。框没有外壳,全局那圈键盘焦点环只会压在通栏一行上 */
101
+ .xh-scope-side-nav[data-part='input']:focus-visible {
102
+ outline: none;
103
+ }
104
+
105
+ /* 自动填充:引擎给填过的框强加一套系统色,盖得过 background 与 color。
106
+ 底改用 inset 阴影铺回来,字改用 -webkit-text-fill-color 接回来;
107
+ 两个选择器名分写两条,一条列表里只要有一个名字不被认识整条就被丢弃 */
108
+ .xh-scope-side-nav[data-part='input']:autofill {
109
+ box-shadow: inset 0 0 0 100vmax var(--xh-side-nav-input-autofill-bg, var(--xh-bg-surface));
110
+ -webkit-text-fill-color: var(--xh-side-nav-input-autofill-fg, var(--xh-fg-default));
111
+ }
112
+
113
+ .xh-scope-side-nav[data-part='input']:-webkit-autofill {
114
+ box-shadow: inset 0 0 0 100vmax var(--xh-side-nav-input-autofill-bg, var(--xh-bg-surface));
115
+ -webkit-text-fill-color: var(--xh-side-nav-input-autofill-fg, var(--xh-fg-default));
116
+ }
117
+
118
+ /* 折叠一开始搜索框就与行文字一起淡出,展开等整栏宽度落定才淡入;落成图标栏之后让位:
119
+ 留着高度、不可见也不可聚焦(过滤此时暂停),下面的行不上下跳 */
120
+ .xh-scope-side-nav[data-part='root']:is([data-collapsed], [data-animating]) [data-part='input']:where(.xh-scope-side-nav) {
121
+ opacity: 0;
122
+ }
123
+
124
+ .xh-scope-side-nav[data-part='root'][data-collapsed]:not([data-animating]) [data-part='input']:where(.xh-scope-side-nav) {
125
+ visibility: hidden;
126
+ }
127
+
128
+ /* 搜索一条都没命中的占位:list 的兄弟,只一句次要文字,面归侧栏所在的宿主 */
129
+ .xh-scope-side-nav[data-part='empty'] {
130
+ padding-block: var(--xh-side-nav-empty-py, var(--xh-space-3));
131
+ padding-inline: var(--xh-side-nav-empty-px, var(--xh-_side-nav-row-px));
132
+ color: var(--xh-side-nav-empty-fg, var(--xh-fg-muted));
133
+ font-size: var(--xh-side-nav-empty-font-size, var(--xh-_side-nav-row-font-size));
134
+ text-align: center;
135
+ }
136
+
137
+ /* 三层列表同一副排法:顶层、分组里的与分支的子层都是 ul,行与行之间同一个 gap,不带 UA 的缩进与外边距 */
138
+ .xh-scope-side-nav[data-part='list'],
139
+ .xh-scope-side-nav[data-part='group-list'],
140
+ .xh-scope-side-nav[data-part='branch-content'] {
141
+ display: flex;
142
+ flex-direction: column;
143
+ gap: var(--xh-side-nav-gap, var(--xh-space-1));
144
+ margin: 0;
145
+ padding: 0;
146
+ list-style: none;
147
+ }
148
+
149
+ /* 子层靠嵌套缩进,层级越深自然越靠里 */
150
+ .xh-scope-side-nav[data-part='branch-content'] {
151
+ padding-inline-start: var(--xh-side-nav-indent, var(--xh-space-4));
152
+ }
153
+
154
+ .xh-scope-side-nav[data-part='branch-content'][hidden] {
155
+ display: none;
156
+ }
157
+
158
+ /* 分组是上一层列表里的一条:标题与组内列表上下排,间距与行距同一个 gap */
159
+ .xh-scope-side-nav[data-part='group'] {
160
+ display: flex;
161
+ flex-direction: column;
162
+ gap: var(--xh-side-nav-gap, var(--xh-space-1));
163
+ list-style: none;
164
+ }
165
+
166
+ .xh-scope-side-nav[data-part='group-label'] {
167
+ position: relative;
168
+ padding-block: var(--xh-side-nav-group-label-py, var(--xh-space-1));
169
+ padding-inline: var(--xh-side-nav-group-label-px, var(--xh-_side-nav-row-px));
170
+ font-size: var(--xh-text-caption-size);
171
+ font-weight: var(--xh-text-label-weight);
172
+ color: var(--xh-fg-subtle);
173
+ user-select: none;
174
+ transition: color var(--xh-motion-duration-micro) var(--xh-motion-ease-enter);
175
+ }
176
+
177
+ /* 图标栏里分组标题没有落点:字淡成透明、仍参与播报,标题留着自己的高度,下面的行不上下跳;
178
+ 折叠一开始就淡出,展开等整栏宽度落定才淡入。落成图标栏之后在这一格里画一道细分隔,分组仍看得出来 */
179
+ .xh-scope-side-nav[data-part='root']:is([data-collapsed], [data-animating]) [data-part='group-label']:where(.xh-scope-side-nav) {
180
+ overflow: hidden;
181
+ color: transparent;
182
+ white-space: nowrap;
183
+ }
184
+
185
+ .xh-scope-side-nav[data-part='root'][data-collapsed]:not([data-animating]) [data-part='group-label']:where(.xh-scope-side-nav)::after {
186
+ content: '';
187
+ position: absolute;
188
+ inset-inline: var(--xh-_side-nav-row-px);
189
+ inset-block-start: calc(50% - var(--xh-stroke-thin) / 2);
190
+ block-size: var(--xh-stroke-thin);
191
+ background: var(--xh-border-subtle);
192
+ }
193
+
194
+ .xh-scope-side-nav[data-part='branch'] {
195
+ display: flex;
196
+ flex-direction: column;
197
+ gap: var(--xh-side-nav-gap, var(--xh-space-1));
198
+ list-style: none;
199
+ }
200
+
201
+ /* 叶子行的列表项:链接自己撑满,这一层只负责列表语义 */
202
+ .xh-scope-side-nav[data-part='item'] {
203
+ display: flex;
204
+ flex-direction: column;
205
+ list-style: none;
206
+ }
207
+
208
+ /* —— 行:分支按钮与链接同一副长相 ——
209
+ 两种行都走 Collection Item 的 page 语境(页内持久集合):悬停 / 高亮 / 按下面(白底承载 hover 100 →
210
+ pressed 200,只换面不缩放)、当前页(品牌淡底 + 淡底前景 + 起始侧 2px 指示条,current+hover 20% /
211
+ +pressed 28%)、展开路径(与 hover 同档的中性面,不用品牌色、不加粗)与禁用面都由家族按 data-current /
212
+ data-in-path / aria-disabled 给出。这里只把公开槽映射到桥接槽。
213
+ 布局保持 flex 而不用家族网格:一行里可以并排作者自己的图标与徽标,间距统一由行的 gap 给,
214
+ 家族按槽下发的外边距(--xh-collection-gap)归零;行高由 min-block-size 撑起,家族的块向内衬归零 */
215
+ .xh-scope-side-nav[data-part='branch-trigger'],
216
+ .xh-scope-side-nav[data-part='link'] {
217
+ --xh-collection-block-padding: 0;
218
+ --xh-collection-inline-padding: var(--xh-side-nav-link-px, var(--xh-_side-nav-row-px));
219
+ --xh-collection-gap: 0;
220
+ --xh-collection-font-size: var(--xh-side-nav-link-font-size, var(--xh-_side-nav-row-font-size));
221
+ --xh-collection-radius: var(--xh-side-nav-link-radius, var(--xh-shape-surface));
222
+ /* 作者的图标尺槽经桥接槽下发到行,家族缺省按 data-xh-collection-size 取档 */
223
+ --xh-collection-glyph-size: var(--xh-side-nav-icon-size, var(--xh-_collection-glyph-size));
224
+ --xh-collection-fg-rest: var(--xh-side-nav-row-fg, currentColor);
225
+ --xh-collection-fg-hover: var(--xh-side-nav-row-fg, currentColor);
226
+ --xh-collection-fg-keyboard-highlight: var(--xh-side-nav-row-fg, currentColor);
227
+ --xh-collection-fg-pressed: var(--xh-side-nav-row-fg, currentColor);
228
+ --xh-collection-bg-hover: var(--xh-side-nav-row-bg-hover, var(--xh-bg-subtle));
229
+ --xh-collection-bg-keyboard-highlight: var(--xh-side-nav-row-bg-hover, var(--xh-bg-subtle));
230
+ --xh-collection-bg-pressed: var(--xh-side-nav-row-bg-pressed, var(--xh-bg-subtle-hover));
231
+ /* 当前页:页内持久集合的标记是品牌淡底行面 + 淡底前景;侧栏另把字重提到 semibold,整列扫读时当前项一眼可见 */
232
+ --xh-collection-bg-current: var(--xh-side-nav-row-bg-active, var(--xh-bg-brand-subtle));
233
+ --xh-collection-fg-current: var(--xh-side-nav-row-fg-active, var(--xh-fg-on-brand-subtle));
234
+ --xh-collection-fg-current-hover: var(--xh-side-nav-row-fg-active, var(--xh-fg-on-brand-subtle));
235
+ --xh-collection-fg-current-highlight: var(--xh-side-nav-row-fg-active, var(--xh-fg-on-brand-subtle));
236
+ --xh-collection-fg-current-pressed: var(--xh-side-nav-row-fg-active, var(--xh-fg-on-brand-subtle));
237
+ --xh-collection-font-weight-current: var(--xh-side-nav-row-font-weight-active, var(--xh-font-weight-semibold));
238
+ --xh-collection-font-weight-current-hover: var(--xh-side-nav-row-font-weight-active, var(--xh-font-weight-semibold));
239
+ --xh-collection-font-weight-current-highlight: var(--xh-side-nav-row-font-weight-active, var(--xh-font-weight-semibold));
240
+ --xh-collection-font-weight-current-pressed: var(--xh-side-nav-row-font-weight-active, var(--xh-font-weight-semibold));
241
+ --xh-collection-indicator-fg-current: var(--xh-side-nav-indicator-color, var(--xh-fg-brand));
242
+ --xh-collection-indicator-fg-current-hover: var(--xh-side-nav-indicator-color, var(--xh-fg-brand));
243
+ --xh-collection-indicator-fg-current-highlight: var(--xh-side-nav-indicator-color, var(--xh-fg-brand));
244
+ --xh-collection-indicator-fg-current-pressed: var(--xh-side-nav-indicator-color, var(--xh-fg-brand));
245
+ /* 展开路径:中性面,字色缺省由品牌色改回行的常态色 */
246
+ --xh-collection-bg-open-path: var(--xh-side-nav-row-bg-in-path, var(--xh-bg-subtle));
247
+ --xh-collection-fg-open-path: var(--xh-side-nav-row-fg-in-path, var(--xh-side-nav-row-fg, currentColor));
248
+ /* data-highlighted 跟的是连接层记的焦点行(指针点选也会落焦):只换面,焦点环在 :focus-visible 下再接回 */
249
+ --xh-collection-outline-keyboard-highlight: transparent;
250
+ --xh-collection-outline-current-highlight: transparent;
251
+
252
+ display: flex;
253
+ align-items: center;
254
+ gap: var(--xh-side-nav-link-gap, var(--xh-_side-nav-row-gap));
255
+ inline-size: 100%;
256
+ min-block-size: var(--xh-side-nav-link-h, var(--xh-_side-nav-row-h));
257
+ border: none;
258
+ text-align: start;
259
+ text-decoration: none;
260
+ }
261
+
262
+ /* 键盘焦点出现时环才接回并立即到位,不压在背景过渡的中间帧上 */
263
+ .xh-scope-side-nav[data-part='branch-trigger']:focus-visible:not(:hover),
264
+ .xh-scope-side-nav[data-part='link']:focus-visible:not(:hover) {
265
+ --xh-collection-outline-keyboard-highlight: var(--xh-ring-focus);
266
+ --xh-collection-outline-current-highlight: var(--xh-ring-focus);
267
+
268
+ transition: none;
269
+ }
270
+
271
+ .xh-scope-side-nav[data-part='branch-text'],
272
+ .xh-scope-side-nav[data-part='link-text'] {
273
+ flex: 1;
274
+ min-inline-size: 0;
275
+ overflow: hidden;
276
+ text-overflow: ellipsis;
277
+ white-space: nowrap;
278
+ transition: opacity var(--xh-motion-duration-micro) var(--xh-motion-ease-enter);
279
+ }
280
+
281
+ /* 行文字与展开箭头的淡变:折叠一开始就淡出,此时仍在行里、由收窄的行宽裁着;展开时等整栏宽度落定才淡入。
282
+ 弹出面板里的行不在此列 */
283
+ .xh-scope-side-nav[data-part='root']:is([data-collapsed], [data-animating]) [data-part='branch-text']:where(.xh-scope-side-nav):not([data-popout] :where(.xh-scope-side-nav)),
284
+ .xh-scope-side-nav[data-part='root']:is([data-collapsed], [data-animating]) [data-part='link-text']:where(.xh-scope-side-nav):not([data-popout] :where(.xh-scope-side-nav)),
285
+ .xh-scope-side-nav[data-part='root']:is([data-collapsed], [data-animating]) [data-part='branch-indicator']:where(.xh-scope-side-nav):not([data-popout] :where(.xh-scope-side-nav)) {
286
+ opacity: 0;
287
+ }
288
+
289
+ /* 落成图标栏(收窄落定):行文字裁到看不见但仍参与播报,行内容居中,不裁半个字。
290
+ 用 clip-path 而不是 display:none——图标栏里按钮与链接的可及名就是这段文字,
291
+ 藏成 display:none 它们就一个名字都没有了。
292
+ white-space: nowrap 防止 1px 宽把文本挤成竖排。
293
+ 弹出面板里的行不在此列——面板是正常宽度的浮层,文字照常显示 */
294
+ .xh-scope-side-nav[data-part='root'][data-collapsed]:not([data-animating]) [data-part='branch-text']:where(.xh-scope-side-nav):not([data-popout] :where(.xh-scope-side-nav)),
295
+ .xh-scope-side-nav[data-part='root'][data-collapsed]:not([data-animating]) [data-part='link-text']:where(.xh-scope-side-nav):not([data-popout] :where(.xh-scope-side-nav)) {
296
+ position: absolute;
297
+ inline-size: 1px;
298
+ block-size: 1px;
299
+ padding: 0;
300
+ margin: -1px;
301
+ overflow: hidden;
302
+ clip-path: inset(50%);
303
+ white-space: nowrap;
304
+ border: 0;
305
+ }
306
+
307
+ /* 展开指示是纯装饰(aria-hidden),落成图标栏之后整个不占位 */
308
+ .xh-scope-side-nav[data-part='root'][data-collapsed]:not([data-animating]) [data-part='branch-indicator']:where(.xh-scope-side-nav):not([data-popout] :where(.xh-scope-side-nav)) {
309
+ display: none;
310
+ }
311
+
312
+ .xh-scope-side-nav[data-part='root'][data-collapsed]:not([data-animating]) [data-part='branch-trigger']:where(.xh-scope-side-nav):not([data-popout] :where(.xh-scope-side-nav)),
313
+ .xh-scope-side-nav[data-part='root'][data-collapsed]:not([data-animating]) [data-part='link']:where(.xh-scope-side-nav):not([data-popout] :where(.xh-scope-side-nav)) {
314
+ --xh-collection-inline-padding: 0;
315
+
316
+ justify-content: center;
317
+ }
318
+
319
+ /* 弹出面板的定位层:坐标由连接层写在行内样式上,这里只管层号与命中区。
320
+ 它被搬到浮层落点、不在侧栏子树内,所以卡片外观仍归面板本身;
321
+ 这里不设 display,UA 的 [hidden]{display:none} 就仍然压得住收起态 */
322
+ .xh-scope-side-nav[data-part='positioner'] {
323
+ /* 落定那一侧的可用高度,由定位引擎经内联自定义属性写进来,面板继承它限高;
324
+ 引擎没算(尚未落位 / 无引擎 / 贴边归零)时不额外限高 */
325
+ --xh-_side-nav-available-h: 100vh;
326
+ /* 落定那一侧的可用宽度,同样由定位引擎经内联自定义属性写进来,行内轴据此夹取;
327
+ 引擎没算(尚未落位 / 无引擎 / 贴边归零)时退到视口宽 */
328
+ --xh-_side-nav-available-w: 100vw;
329
+
330
+ /* 弹出面板从锚点一侧短移入,方向按实际落位只激活一支;先清零,截断父层定位层的方向继承 */
331
+ --xh-_overlay-enter-up: 0;
332
+ --xh-_overlay-enter-down: 0;
333
+ --xh-_overlay-enter-left: 0;
334
+ --xh-_overlay-enter-right: 0;
335
+
336
+ position: fixed;
337
+ z-index: var(--xh-side-nav-popout-layer, var(--xh-_layer, var(--xh-layer-popover)));
338
+ pointer-events: auto;
339
+ }
340
+
341
+ /* 物理 placement 与定位引擎同一套,不随书写方向翻 */
342
+ .xh-scope-side-nav[data-part='positioner'][data-placement^='top'] {
343
+ --xh-_overlay-enter-down: 1;
344
+ }
345
+
346
+ .xh-scope-side-nav[data-part='positioner'][data-placement^='bottom'] {
347
+ --xh-_overlay-enter-up: 1;
348
+ }
349
+
350
+ .xh-scope-side-nav[data-part='positioner'][data-placement^='left'] {
351
+ --xh-_overlay-enter-right: 1;
352
+ }
353
+
354
+ .xh-scope-side-nav[data-part='positioner'][data-placement^='right'] {
355
+ --xh-_overlay-enter-left: 1;
356
+ }
357
+
358
+ /* 还没落位就先藏着:visibility 而非 display,display:none 会让引擎量不到面板尺寸 */
359
+ .xh-scope-side-nav[data-part='positioner'][data-hidden] {
360
+ visibility: hidden;
361
+ }
362
+
363
+ /* 折叠态的弹出面板:贴着触发按钮旁侧的浮层卡片。
364
+ 面板自己不吃子层缩进(padding 整圈盖掉),面板内的嵌套子层照常缩进 */
365
+ .xh-scope-side-nav[data-part='branch-content'][data-popout] {
366
+ min-inline-size: var(--xh-side-nav-popout-min-w, var(--xh-overlay-menu-min-w));
367
+ /* 静态档与落位后的可用宽度取小:窄视口下面板伸出去,最右侧的内容就点不到了 */
368
+ max-inline-size: min(var(--xh-side-nav-popout-max-w, var(--xh-overlay-max-w)), var(--xh-_side-nav-available-w));
369
+ padding: var(--xh-side-nav-popout-p, var(--xh-space-1));
370
+ border: var(--xh-stroke-thin) solid var(--xh-side-nav-popout-border, var(--xh-border-default));
371
+ border-radius: var(--xh-side-nav-popout-radius, var(--xh-shape-overlay));
372
+ background: var(--xh-side-nav-popout-bg, var(--xh-bg-surface));
373
+ box-shadow: var(--xh-side-nav-popout-shadow, var(--xh-elevation-floating));
374
+
375
+ /* 子导航条目数没有上限,矮视口下不限高就整块伸出视口且滚不到。
376
+ 浮层滚动面:到底后不把滚动链穿透给页面;细条由 reset 层给 */
377
+ max-block-size: min(var(--xh-side-nav-popout-max-h, var(--xh-overlay-menu-max-h)), var(--xh-_side-nav-available-h));
378
+ overflow-y: auto;
379
+ overscroll-behavior: contain;
380
+ }
381
+
382
+ /* 弹出分支是锚定在分支行旁侧的一列导航,与菜单同属锚定列表:从锚点一侧短移淡入,不缩放 */
383
+ .xh-scope-side-nav[data-part='branch-content'][data-popout][data-state='open'] {
384
+ animation: xh-overlay-slide-in var(--xh-motion-duration-enter) var(--xh-motion-ease-enter-strong);
385
+ }
386
+
387
+ /* 退场:收起那一帧 hidden 由退场闸门押后,这里才播得出来。forwards 把末态钉住,
388
+ 免得动画结束到收起落下来之间闪一下原样 */
389
+ .xh-scope-side-nav[data-part='branch-content'][data-popout][data-state='closed'] {
390
+ animation: xh-overlay-slide-out var(--xh-motion-duration-exit) var(--xh-motion-ease-exit) forwards;
391
+ }
392
+
393
+ /* 箭头是行尾的后缀:auto 外边距把它顶到行尾,家族按 suffix 槽下发的外边距已在行上归零。
394
+ 盒里的 chevron 是指示符:盒按指示符档定尺(comfortable 16 / compact 14,与 Tree / TreeSelect
395
+ 的 branch-indicator 同款定尺盒),--xh-icon-size 在自己身上改接到盒的尺,兜底字形与作者塞进盒里的
396
+ XhIcon 读同一把尺、与盒同边长;不读家族按档下发到行的 --xh-icon-size——那支只管作者放进行里的
397
+ 图标,按图标档取的 20px 比指示符档大一圈。盒自己定尺而不随字形撑开:转 90° 时才不抖 */
398
+ .xh-scope-side-nav[data-part='branch-indicator'] {
399
+ --xh-icon-size: var(--xh-side-nav-branch-indicator-size, var(--xh-control-indicator-size));
400
+
401
+ margin-inline-start: auto;
402
+ display: inline-flex;
403
+ flex: none;
404
+ align-items: center;
405
+ justify-content: center;
406
+ inline-size: var(--xh-side-nav-branch-indicator-size, var(--xh-control-indicator-size));
407
+ block-size: var(--xh-side-nav-branch-indicator-size, var(--xh-control-indicator-size));
408
+ /* 收起时指向行尾、展开时转向下方,与逻辑书写方向一致:rtl 下行尾在左侧,收起的箭头转半圈;
409
+ 旋转角乘书写方向的符号(ltr 0deg、rtl 180deg),按就近的 dir 走 */
410
+ rotate: calc(90deg - 90deg * var(--xh-direction-sign));
411
+ transition:
412
+ rotate var(--xh-motion-duration-nudge) var(--xh-motion-ease-enter-strong),
413
+ opacity var(--xh-motion-duration-micro) var(--xh-motion-ease-enter);
414
+ }
415
+
416
+ .xh-scope-side-nav[data-part='branch-indicator'][data-state='open'] {
417
+ rotate: 90deg;
418
+ }
419
+
420
+ /* 没写内容就由皮肤画兜底字形;作者往部件里塞了自己的图形,这几条即不命中。
421
+ 尺寸读部件自己改接过的 --xh-icon-size:chevron 与盒同边长(见上面那块) */
422
+ .xh-scope-side-nav[data-part='branch-indicator']:empty::before {
423
+ content: '';
424
+ display: inline-block;
425
+ inline-size: var(--xh-icon-size, var(--xh-glyph-size-text));
426
+ block-size: var(--xh-icon-size, var(--xh-glyph-size-text));
427
+ vertical-align: var(--xh-glyph-baseline-shift);
428
+ background-color: currentColor;
429
+ -webkit-mask: var(--xh-glyph-mark-chevron-right) center / contain no-repeat;
430
+ mask: var(--xh-glyph-mark-chevron-right) center / contain no-repeat;
431
+ }
432
+
433
+ /* 声明过任何 display 就盖掉了 UA 的 [hidden]{display:none},收起态得自己还回去。
434
+ 写在文件末尾:兜底必须排在该部件所有 display 声明之后 */
435
+ .xh-scope-side-nav[data-part='root'][hidden],
436
+ .xh-scope-side-nav[data-part='list'][hidden],
437
+ .xh-scope-side-nav[data-part='group'][hidden],
438
+ .xh-scope-side-nav[data-part='group-list'][hidden],
439
+ .xh-scope-side-nav[data-part='branch'][hidden],
440
+ .xh-scope-side-nav[data-part='branch-trigger'][hidden],
441
+ .xh-scope-side-nav[data-part='item'][hidden],
442
+ .xh-scope-side-nav[data-part='link'][hidden],
443
+ .xh-scope-side-nav[data-part='branch-indicator'][hidden] {
444
+ display: none;
445
+ }
446
+
447
+ @media (forced-colors: active) {
448
+ /* 图标栏里分组之间那道细分隔画的是一块底色,这一档里底色被统一换成 Canvas、整道消失;换成 GrayText 画回来 */
449
+ .xh-scope-side-nav[data-part='root'][data-collapsed]:not([data-animating]) [data-part='group-label']:where(.xh-scope-side-nav)::after {
450
+ background: GrayText;
451
+ }
452
+ }
453
+
454
+ @media print {
455
+ /* 打印:定位层与遮罩是交互期才存在的东西,落到纸上只会盖住底下的正文;搜索框同理,纸上没法输入。
456
+ 收起写在这份皮肤里而不是 reset:reset 层排在组件层之前,组件层里任何一条 display 都压得住它。 */
457
+ .xh-scope-side-nav[data-part='positioner'],
458
+ .xh-scope-side-nav[data-part='input'] {
459
+ display: none;
460
+ }
461
+ }
462
+
463
+ @media (forced-colors: active) {
464
+ /* 兜底字形是 mask 挖出来的一块底色,这一档里底色被系统换成 Canvas,字形跟着消失。
465
+ 字形退出强制换色、直接写系统色(不能取 currentColor:退出强制换色的伪元素读到的是被系统换掉之前的作者色):
466
+ 条目面上取 CanvasText;按下与没被高亮时的悬停,家族把条目涂成 Highlight,字形换 HighlightText;
467
+ 禁用取 GrayText */
468
+ .xh-scope-side-nav[data-part='branch-indicator']:empty::before {
469
+ forced-color-adjust: none;
470
+ background-color: CanvasText;
471
+ }
472
+
473
+ .xh-scope-side-nav[data-part='branch-trigger']:not([aria-disabled='true'], [data-disabled], [aria-busy='true'], [data-error]):is(:active, [data-pressed], :hover:not(:focus-visible, [data-highlighted])) .xh-scope-side-nav[data-part='branch-indicator']:empty::before {
474
+ background-color: HighlightText;
475
+ }
476
+
477
+ .xh-scope-side-nav[data-part='branch-trigger']:is([aria-disabled='true'], [data-disabled]) .xh-scope-side-nav[data-part='branch-indicator']:empty::before {
478
+ background-color: GrayText;
479
+ }
480
+ }
481
+ }