@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,606 @@
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
+ /* 定义 drawer 样式。 */
7
+
8
+ /* 共享关键帧由 family/motion.css 提供,本皮肤 @import 它,单独引入仍成立。 */
9
+ @import '../family/motion.css';
10
+ @import '../family/action-control.css';
11
+
12
+ @layer xihan.components {
13
+ /* 皮肤在场的标记:开发模式下按 scope 探一次,取不到就说明这份皮肤没被引入。 */
14
+ .xh-scope-drawer {
15
+ --xh-drawer-skin: 1;
16
+ }
17
+
18
+ /* root 留在页面原地,只是 data-side / data-state 的落点,不该凭空多出一层盒子把
19
+ trigger 从作者的 flex / grid 行里挤出去,故 display: contents。 */
20
+ .xh-scope-drawer[data-part='root'] {
21
+ /* 作者塞进面板里的图标按控件档取;触发器与关闭钮另由家族配方按各自的档下发字形尺 */
22
+ --xh-icon-size: var(--xh-drawer-icon-size, var(--xh-glyph-size-md));
23
+
24
+ display: contents;
25
+ }
26
+
27
+ /* 浮层被搬到 portal 落点,继承不到 root 上的槽:这把尺在被搬走的那一侧再声明一次,
28
+ 作者塞进面板里的图标才和皮肤画的兜底字形一样大 */
29
+ .xh-scope-drawer[data-part='content'] {
30
+ --xh-icon-size: var(--xh-drawer-icon-size, var(--xh-glyph-size-md));
31
+ }
32
+
33
+ /* 声明了 display 就盖掉了 UA 的 [hidden]{display:none},作者手写 hidden 时得还回去 */
34
+ .xh-scope-drawer[data-part='root'][hidden] {
35
+ display: none;
36
+ }
37
+
38
+ /*
39
+ * 触发器是页面上的独立文字按钮:盒型、md 档几何、outline 四态面、0.97 按压并换底与粗指针命中区
40
+ * 由家族配方按连接层投影的 data-xh-action-variant / -size 给出(此前自写描边盒型,hover 落 200 / active 落 300)。
41
+ * 这里只把公开槽桥接到矩阵之前(使用者槽 → 形态矩阵 → 家族缺省)与几何槽映射。
42
+ */
43
+ .xh-scope-drawer[data-part='trigger'] {
44
+ --xh-action-gap: var(--xh-drawer-trigger-gap, var(--xh-_action-profile-gap));
45
+ --xh-action-visual-size: var(--xh-drawer-trigger-h, var(--xh-_action-profile-visual-size));
46
+ --xh-action-padding-inline: var(--xh-drawer-trigger-px, var(--xh-_action-profile-padding-inline));
47
+ --xh-action-radius: var(--xh-drawer-trigger-radius, var(--xh-shape-control));
48
+ --xh-action-font-size: var(--xh-drawer-trigger-font-size, var(--xh-_action-profile-font-size));
49
+ --xh-action-bg-rest: var(--xh-drawer-trigger-bg, var(--xh-_action-variant-bg-rest));
50
+ --xh-action-bg-hover: var(--xh-drawer-trigger-bg-hover, var(--xh-_action-variant-bg-hover));
51
+ --xh-action-bg-pressed: var(--xh-drawer-trigger-bg-active, var(--xh-_action-variant-bg-pressed));
52
+ --xh-action-bg-focus-visible: var(--xh-drawer-trigger-bg, var(--xh-_action-variant-bg-focus-visible));
53
+ --xh-action-fg-rest: var(--xh-drawer-trigger-fg, var(--xh-_action-variant-fg-rest));
54
+ --xh-action-fg-hover: var(--xh-drawer-trigger-fg, var(--xh-_action-variant-fg-hover));
55
+ --xh-action-fg-pressed: var(--xh-drawer-trigger-fg, var(--xh-_action-variant-fg-pressed));
56
+ --xh-action-fg-focus-visible: var(--xh-drawer-trigger-fg, var(--xh-_action-variant-fg-focus-visible));
57
+ --xh-action-border-rest: var(--xh-drawer-trigger-border, var(--xh-_action-variant-border-rest));
58
+ --xh-action-border-hover: var(--xh-drawer-trigger-border-hover, var(--xh-_action-variant-border-hover));
59
+ --xh-action-border-pressed: var(--xh-drawer-trigger-border-hover, var(--xh-_action-variant-border-pressed));
60
+ --xh-action-border-focus-visible: var(--xh-drawer-trigger-border, var(--xh-_action-variant-border-focus-visible));
61
+ /* 作者塞进按钮的图标随档取字形尺(md = 20px) */
62
+ --xh-icon-size: var(--xh-drawer-icon-size, var(--xh-_action-profile-glyph-size));
63
+
64
+ /* 触发器的文字与 Button 同一字重(家族配方不管字重) */
65
+ font-weight: var(--xh-drawer-trigger-font-weight, var(--xh-text-label-weight));
66
+ }
67
+
68
+ .xh-scope-drawer[data-part='trigger'][hidden] {
69
+ display: none;
70
+ }
71
+
72
+ /* 抽屉展开期间触发按钮压住不弹起:面板贴在视口边上,它和按钮往往离得很远,
73
+ 按钮自己得说明"这一扇是我开的"。open 与家族 hover 同档中性:
74
+ 白底承载的 --xh-bg-subtle(100)+ 悬停描边,聚焦时这块面留着 */
75
+ .xh-scope-drawer[data-part='trigger'][data-state='open'] {
76
+ --xh-action-bg-rest: var(--xh-drawer-trigger-bg-open, var(--xh-bg-subtle));
77
+ --xh-action-bg-focus-visible: var(--xh-drawer-trigger-bg-open, var(--xh-bg-subtle));
78
+ --xh-action-border-rest: var(--xh-drawer-trigger-border-open, var(--xh-border-control-hover));
79
+ --xh-action-border-focus-visible: var(--xh-drawer-trigger-border-open, var(--xh-border-control-hover));
80
+ }
81
+
82
+ /* 面是实心的,环色与面同族,画在面里就看不出来;环改取面自己的前景色 */
83
+ .xh-scope-drawer[data-part='trigger'][data-xh-action-variant='solid']:focus-visible {
84
+ --xh-action-ring-color-focus-visible: currentColor;
85
+ }
86
+
87
+ .xh-scope-drawer[data-part='backdrop'] {
88
+ position: fixed;
89
+ inset: 0;
90
+ z-index: var(--xh-drawer-backdrop-layer, var(--xh-_layer, var(--xh-layer-drawer)));
91
+ background: var(--xh-drawer-backdrop-bg, var(--xh-bg-overlay));
92
+ }
93
+
94
+ /* 挂在局部容器里:遮罩、定位层与面板一起从视口坐标换成容器坐标,只罩住那个容器。
95
+ 作者要给那个容器加 position(relative 之类),否则 absolute 会往上找到别的定位祖先——
96
+ 这一条写进了示例与 props 说明。
97
+ content 必须一起换:它的贴边是 inset-block/inline 参照包含块算的,留在 fixed 上就会
98
+ 照旧贴视口边,遮罩缩进容器、面板却跑到屏幕边上——与 contained 的承诺正好相反 */
99
+ .xh-scope-drawer[data-part='backdrop'][data-contained],
100
+ .xh-scope-drawer[data-part='positioner'][data-contained],
101
+ .xh-scope-drawer[data-part='content'][data-contained] {
102
+ position: absolute;
103
+ }
104
+
105
+ /* 挂在局部容器里的面板碰不到屏幕边,安全区那一段让位收回去:留着会在容器内白让出一条。
106
+ 三段排版读的那几支安全区私有槽一并归零 */
107
+ .xh-scope-drawer[data-part='content'][data-contained] {
108
+ --xh-_drawer-safe-top: var(--xh-space-0);
109
+ --xh-_drawer-safe-bottom: var(--xh-space-0);
110
+ --xh-_drawer-safe-inline: var(--xh-space-0);
111
+
112
+ padding-block-start: var(--xh-drawer-py, var(--xh-_drawer-header-pt));
113
+ padding-block-end: var(--xh-drawer-py, var(--xh-overlay-sheet-footer-py));
114
+ padding-inline: var(--xh-drawer-px, var(--xh-surface-px-sm));
115
+ }
116
+
117
+ /* 同一层底色之上再糊背后的页面;与 dialog 同写法,两个前缀都写 */
118
+ .xh-scope-drawer[data-part='backdrop'][data-variant='blur'] {
119
+ -webkit-backdrop-filter: blur(var(--xh-drawer-backdrop-blur, var(--xh-overlay-backdrop-blur)));
120
+ backdrop-filter: blur(var(--xh-drawer-backdrop-blur, var(--xh-overlay-backdrop-blur)));
121
+ }
122
+
123
+ /* 去掉底色,只留下这一层吃指针:交互外关闭与滚动锁定照旧 */
124
+ .xh-scope-drawer[data-part='backdrop'][data-variant='transparent'] {
125
+ background: transparent;
126
+ }
127
+
128
+ /* 挂载时就开着的那一段(data-instant)属于首帧,遮罩与面板都直接呈现 */
129
+ .xh-scope-drawer[data-part='backdrop'][data-state='open']:not([data-instant]) {
130
+ animation: xh-fade-in var(--xh-motion-duration-enter) var(--xh-motion-ease-enter);
131
+ }
132
+
133
+ /* 退场补 forwards:动画播完到宿主真正卸载之间还有一帧,不定住终态遮罩会闪回全黑 */
134
+ .xh-scope-drawer[data-part='backdrop'][data-state='closed'] {
135
+ animation: xh-fade-out var(--xh-motion-duration-exit) var(--xh-motion-ease-exit) forwards;
136
+ }
137
+
138
+ /* positioner 只负责把浮层抬到抽屉层,贴边一概不管(原因见 content)。
139
+ 铺满视口是为了在自己这层里罩住 content,但不吃指针:非模态抽屉展开时
140
+ 页面其余部分还要能点,模态的拦截由 backdrop 负责。 */
141
+ .xh-scope-drawer[data-part='positioner'] {
142
+ position: fixed;
143
+ inset: 0;
144
+ z-index: var(--xh-drawer-layer, var(--xh-_layer, var(--xh-layer-drawer)));
145
+ pointer-events: none;
146
+ }
147
+
148
+ /* 贴边写在 content 自己身上,而不是交给 positioner:
149
+ positioner 在抽屉里不是必需部件,最小合规结构只有 root + content,
150
+ 贴边若挂在 positioner 上,那种结构下面板会直接塌回文档流。
151
+ 非 contained 时 content 是 fixed,包住它的 positioner 没有 transform / filter,
152
+ 不构成固定定位的包含块,两种结构下参照的都是视口,位置一致;
153
+ contained 时上面那条把它一并换成 absolute,参照的就是作者那个容器。 */
154
+ .xh-scope-drawer[data-part='content'] {
155
+ /* 位移方向的私有槽位:默认按 LTR,RTL 在下面整体翻符号。幅度取整幅位移令牌,减弱动效下归零 */
156
+ --xh-_drawer-shift-inline: var(--xh-motion-travel);
157
+ --xh-_drawer-shift-block: var(--xh-motion-travel);
158
+ /* 尺寸档只换这一个私有槽:左右放置时它是面板宽度、上下放置时是面板高度,
159
+ 两种取法都在下面「四条边」那两条规则里。声明在 content 而不是 root:
160
+ content 会被 portal 到 body,root 上的槽位继承不过来(data-side 也是同一个道理) */
161
+ --xh-_drawer-size: var(--xh-overlay-drawer-w-md);
162
+ /* 系统占着的那几段:分三段时面板一层只让出它们,设计内衬交给三段各自给。
163
+ 安全区只有物理方向的四个名字,行内轴上两侧同取较宽的那一段,RTL 下不会翻错边 */
164
+ --xh-_drawer-safe-top: env(safe-area-inset-top, 0px);
165
+ --xh-_drawer-safe-bottom: env(safe-area-inset-bottom, 0px);
166
+ --xh-_drawer-safe-inline: max(env(safe-area-inset-left, 0px), env(safe-area-inset-right, 0px));
167
+ /* 头部带:标题首行与角上的关闭钮都落在这条带的中线上,与对话框同一组槽 */
168
+ --xh-_drawer-header-h: var(--xh-overlay-header-h);
169
+ /* 标题首行在带里居中要让出的上内衬:带高减标题行高再对半 */
170
+ --xh-_drawer-header-pt: calc((var(--xh-_drawer-header-h) - var(--xh-text-heading-3-size) * var(--xh-leading-normal)) / 2);
171
+ /* 分三段时头的下内衬扣掉分隔线那 1px,只有标题时整条带恰好是带高 */
172
+ --xh-_drawer-header-pb: calc(var(--xh-_drawer-header-pt) - var(--xh-stroke-thin));
173
+ /* 带的上沿:不分三段时上内衬与安全区取大的一头,安全区更深时整条带往下让出差值 */
174
+ --xh-_drawer-header-top: calc(max(var(--xh-_drawer-header-pt), var(--xh-_drawer-safe-top)) - var(--xh-_drawer-header-pt));
175
+
176
+ position: fixed;
177
+ z-index: var(--xh-drawer-layer, var(--xh-_layer, var(--xh-layer-drawer)));
178
+ display: flex;
179
+ flex-direction: column;
180
+ gap: var(--xh-drawer-gap, var(--xh-stack-gap-md));
181
+ /* 不分三段时内衬由面板一层给:上沿让标题行落在头部带中线,横向 16px。
182
+ 面板贴死视口的某一条边、另一向满铺,内衬与安全区取大的一头:
183
+ 刘海、圆角与底部横条压住的那一段由系统给出,内衬比它窄时首尾两行会被切掉。
184
+ 桌面上 env() 恒为 0,取值与内衬槽完全一致。 */
185
+ padding-block-start: max(var(--xh-drawer-py, var(--xh-_drawer-header-pt)), env(safe-area-inset-top));
186
+ padding-block-end: max(var(--xh-drawer-py, var(--xh-overlay-sheet-footer-py)), env(safe-area-inset-bottom));
187
+ padding-inline: max(
188
+ var(--xh-drawer-px, var(--xh-surface-px-sm)),
189
+ env(safe-area-inset-left),
190
+ env(safe-area-inset-right)
191
+ );
192
+ /* sheet 三件套:任何浮层不得只靠 box-shadow 分层,亮色下面板与页面同色,
193
+ 1px 描边才是它的边界;影只是加成。面就是实体底,不叠渐变与顶光 */
194
+ border: var(--xh-stroke-thin) solid var(--xh-drawer-border, var(--xh-material-elevated-border));
195
+ background: var(--xh-drawer-bg, var(--xh-material-elevated-bg));
196
+ color: var(--xh-drawer-fg, var(--xh-material-elevated-fg));
197
+ box-shadow: var(--xh-drawer-shadow, var(--xh-material-elevated-shadow));
198
+ /* 作者不用 header / body / footer 三段时它是唯一的滚动层:模态面滚到头不把页面一起带走 */
199
+ overflow: auto;
200
+ overscroll-behavior: contain;
201
+ /* 尺寸是照视口那条边算出来的,padding 再往外顶就会把面板挤出屏幕、
202
+ 逼出一条横向滚动条。reset 层已有同款兜底,这里显式写一遍表明尺寸算法依赖它 */
203
+ box-sizing: border-box;
204
+ /* positioner 整层不吃指针,面板得自己收回来 */
205
+ pointer-events: auto;
206
+ }
207
+
208
+ .xh-scope-drawer[data-part='content']:dir(rtl) {
209
+ --xh-_drawer-shift-inline: calc(-1 * var(--xh-motion-travel));
210
+ }
211
+
212
+ /* 这里刻意没有 [data-part='content'][hidden] { display: none },与 dialog 一致。
213
+ 收起态连接层会给 content 打 hidden,而上面这条 display: flex 正是要盖掉
214
+ UA 的 [hidden]{display:none}——退场动画得先能播:
215
+ presence 读的是 content 的 animationName,读到就申领租约、等 animationend 才卸载;
216
+ 一旦 display: none,元素不生成盒子、动画根本不启动,退场探测器会直接放弃申领
217
+ (否则就要等一个永不到来的 animationend),面板不播动画就地卸载。
218
+ 真正的收起两个适配器各自兜住了:Vue 卸载整棵,WC 写内联 style.display。
219
+ 其余声明了 display 的角色节点仍补了 [hidden],那几处没有退场动画,作者手写 hidden 要生效。 */
220
+
221
+ /* 面板是焦点陷阱的兜底落点(tabindex="-1"),落焦不画环:环长在里面的可聚焦控件上 */
222
+ .xh-scope-drawer[data-part='content']:focus-visible {
223
+ outline: none;
224
+ }
225
+
226
+ /* —— 尺寸 —— */
227
+ /* 只有面板厚度分档;中间档不写规则,缺省即中档。
228
+ data-size 与 data-side 一样同时打在 root 与 content 上,这里只认 content 自己那一份。 */
229
+ .xh-scope-drawer[data-part='content'][data-size='sm'] {
230
+ --xh-_drawer-size: var(--xh-overlay-drawer-w-sm);
231
+ }
232
+
233
+ .xh-scope-drawer[data-part='content'][data-size='lg'] {
234
+ --xh-_drawer-size: var(--xh-overlay-drawer-w-lg);
235
+ }
236
+
237
+ /* —— 四条边 ——
238
+ data-side 同时打在 root 与 content 上;content 会被 portal 到 body,
239
+ 选择器只认得 content 自己身上这一份。 */
240
+
241
+ /* 左右:满高、定宽 */
242
+ .xh-scope-drawer[data-part='content'][data-side='left'],
243
+ .xh-scope-drawer[data-part='content'][data-side='right'] {
244
+ inset-block: 0;
245
+ /* 调过厚度就按连接层写进私有槽的像素走,压过 size 档与使用者槽 */
246
+ inline-size: var(--xh-_drawer-panel-size, var(--xh-drawer-size, var(--xh-_drawer-size)));
247
+ /* 视口比抽屉还窄时让位,否则面板会顶出一条横向滚动条 */
248
+ max-inline-size: 100%;
249
+ }
250
+
251
+ /* 贴住视口(或容器)的那条边不取圆角:圆了反而露出底下的页面。朝向页面那两个角与别的浮层同一把尺,
252
+ 取 overlay 圆角:使用者把圆角调大时抽屉不会单独方着;要另定经 --xh-drawer-radius */
253
+ .xh-scope-drawer[data-part='content'][data-side='left'] {
254
+ inset-inline-start: 0;
255
+ border-start-end-radius: var(--xh-drawer-radius, var(--xh-shape-overlay));
256
+ border-end-end-radius: var(--xh-drawer-radius, var(--xh-shape-overlay));
257
+ }
258
+
259
+ .xh-scope-drawer[data-part='content'][data-side='right'] {
260
+ inset-inline-end: 0;
261
+ border-start-start-radius: var(--xh-drawer-radius, var(--xh-shape-overlay));
262
+ border-end-start-radius: var(--xh-drawer-radius, var(--xh-shape-overlay));
263
+ }
264
+
265
+ /* 上下:满宽、定高 */
266
+ .xh-scope-drawer[data-part='content'][data-side='top'],
267
+ .xh-scope-drawer[data-part='content'][data-side='bottom'] {
268
+ inset-inline: 0;
269
+ block-size: var(--xh-_drawer-panel-size, var(--xh-drawer-size, var(--xh-_drawer-size)));
270
+ max-block-size: 100%;
271
+ }
272
+
273
+ .xh-scope-drawer[data-part='content'][data-side='top'] {
274
+ inset-block-start: 0;
275
+ border-end-start-radius: var(--xh-drawer-radius, var(--xh-shape-overlay));
276
+ border-end-end-radius: var(--xh-drawer-radius, var(--xh-shape-overlay));
277
+ }
278
+
279
+ .xh-scope-drawer[data-part='content'][data-side='bottom'] {
280
+ inset-block-end: 0;
281
+ border-start-start-radius: var(--xh-drawer-radius, var(--xh-shape-overlay));
282
+ border-start-end-radius: var(--xh-drawer-radius, var(--xh-shape-overlay));
283
+ }
284
+
285
+ /* 滑入/滑出共用整幅滑入关键帧,四条边只在两个方向槽里写起点。位移取整幅位移令牌,
286
+ translate 的百分比参照面板自己的边框盒,所以不管 --xh-drawer-size 被改成多少,
287
+ "正好推到视口外"这件事都成立。
288
+
289
+ 方向槽由上面的 --xh-_drawer-shift-* 换算而不是写死物理方向:贴边用的是逻辑 inset
290
+ (inset-inline-start 等),RTL 下 inline-end 落在物理左边;translate 没有逻辑等价物,
291
+ 若这里写死物理方向,就会出现"面板贴在左边、却从右边滑进来"。shift 槽在 RTL 下翻符号,
292
+ 两者才始终同向。竖排书写模式下 block 轴不再是 Y 轴,位移会退化为纵向,但贴边本身仍由逻辑 inset 保证。 */
293
+ .xh-scope-drawer[data-part='content'][data-side='right'] {
294
+ --xh-_slide-from-x: var(--xh-_drawer-shift-inline);
295
+ }
296
+
297
+ .xh-scope-drawer[data-part='content'][data-side='left'] {
298
+ --xh-_slide-from-x: calc(-1 * var(--xh-_drawer-shift-inline));
299
+ }
300
+
301
+ .xh-scope-drawer[data-part='content'][data-side='top'] {
302
+ --xh-_slide-from-y: calc(-1 * var(--xh-_drawer-shift-block));
303
+ }
304
+
305
+ .xh-scope-drawer[data-part='content'][data-side='bottom'] {
306
+ --xh-_slide-from-y: var(--xh-_drawer-shift-block);
307
+ }
308
+
309
+ /* 入场是整面板从画外推入的大尺度位移:走 --xh-motion-duration-slide 与 --xh-motion-ease-slide;
310
+ 退场仍走 exit 档。并列的一段淡变取淡变档:缺省起止都是不透明、看不出来,减弱动效下
311
+ 整幅位移归零、进出场由它表达。退场一律 forwards:presence 要等 animationend 才卸载,
312
+ 不定住终态,面板会在最后一帧弹回原位再消失。 */
313
+ .xh-scope-drawer[data-part='content'][data-state='open']:not([data-instant]) {
314
+ animation:
315
+ xh-slide-in var(--xh-motion-duration-slide) var(--xh-motion-ease-slide),
316
+ xh-slide-fade-in var(--xh-motion-duration-enter) var(--xh-motion-ease-enter);
317
+ }
318
+
319
+ .xh-scope-drawer[data-part='content'][data-state='closed'] {
320
+ animation:
321
+ xh-slide-out var(--xh-motion-duration-exit) var(--xh-motion-ease-exit) forwards,
322
+ xh-slide-fade-out var(--xh-motion-duration-exit) var(--xh-motion-ease-exit) forwards;
323
+ }
324
+
325
+ /* —— 面板三段 —— */
326
+ /* header / body / footer 把面板切成「头尾定在原处、正文自己滚」三段,
327
+ 与弹窗、浮动面板同一套角色划分:头尾不参与压缩,正文吃掉剩下的高度并自己滚。
328
+ 分三段时面板一层只让出安全区,设计内衬由三段各自给:头下、尾上的分隔线才能贴着面板两侧的边;
329
+ 整块的滚动交还给正文段——两层都能滚时滚轮落在哪一层要看指针停在哪,
330
+ 贴边的头尾会跟着一起走。 */
331
+ .xh-scope-drawer[data-part='content']:has(.xh-scope-drawer[data-part='body']) {
332
+ --xh-_drawer-header-top: var(--xh-_drawer-safe-top);
333
+
334
+ gap: 0;
335
+ padding-block-start: var(--xh-_drawer-safe-top);
336
+ padding-block-end: var(--xh-_drawer-safe-bottom);
337
+ padding-inline: var(--xh-_drawer-safe-inline);
338
+ overflow: hidden;
339
+ }
340
+
341
+ /* 头段:标题与说明纵向堆叠;不参与压缩,正文再长也压不扁它 */
342
+ .xh-scope-drawer[data-part='header'] {
343
+ flex: none;
344
+ display: flex;
345
+ flex-direction: column;
346
+ gap: var(--xh-drawer-header-gap, var(--xh-stack-gap-sm));
347
+ padding-block-end: var(--xh-drawer-header-pb, var(--xh-space-2));
348
+ }
349
+
350
+ /* 三段结构的头:一条 48px 的头部带,标题首行落在带的中线上(说明在下面接着排,带随之长高),
351
+ 横向内衬 16px;下沿一条 1px 的内部分隔线走 sheet 分隔令牌,贴着面板两侧的边。
352
+ 下内衬扣掉分隔线那 1px,只有标题时整条带恰好是带高 */
353
+ .xh-scope-drawer[data-part='content']:has(.xh-scope-drawer[data-part='body'])
354
+ .xh-scope-drawer[data-part='header'] {
355
+ justify-content: center;
356
+ min-block-size: var(--xh-_drawer-header-h);
357
+ padding-block-start: var(--xh-drawer-header-pt, var(--xh-_drawer-header-pt));
358
+ padding-block-end: var(--xh-drawer-header-pb, var(--xh-_drawer-header-pb));
359
+ padding-inline: var(--xh-drawer-header-px, var(--xh-surface-px-sm));
360
+ border-block-end: var(--xh-stroke-thin) solid var(--xh-drawer-separator, var(--xh-material-elevated-separator));
361
+ }
362
+
363
+ /* 正文段:面板里唯一会滚的一段。最小高度归零,
364
+ 否则弹性项按内容撑高,容器再矮也不产生溢出,滚动条永远出不来。
365
+ 模态 body 是原生细条滚动面:细条由 reset 层统一给,滚到头不把页面一起带走。
366
+ 内衬纵 12 横 16 */
367
+ .xh-scope-drawer[data-part='body'] {
368
+ flex: 1 1 auto;
369
+ min-block-size: 0;
370
+ overflow: auto;
371
+ overscroll-behavior: contain;
372
+ padding-block: var(--xh-drawer-body-py, var(--xh-surface-py-sm));
373
+ padding-inline: var(--xh-drawer-body-px, var(--xh-surface-px-sm));
374
+ }
375
+
376
+ /* 正文高度随交互变化(表单校验、展开段落):还在用原生滚动条的正文留一条稳定空道,
377
+ 滚动条出现与消失时不推动文字。带 data-xh-scrollbar 的容器已经把原生条藏成零宽,排除掉 */
378
+ .xh-scope-drawer[data-part='body']:not([data-xh-scrollbar]) {
379
+ scrollbar-gutter: stable;
380
+ }
381
+
382
+ /* 尾段:动作按钮排一行靠尾;同样不参与压缩 */
383
+ .xh-scope-drawer[data-part='footer'] {
384
+ flex: none;
385
+ display: flex;
386
+ align-items: center;
387
+ justify-content: flex-end;
388
+ gap: var(--xh-drawer-footer-gap, var(--xh-control-gap-md));
389
+ padding-block-start: var(--xh-drawer-footer-pt, var(--xh-space-2));
390
+ }
391
+
392
+ /* 三段结构的尾:纵 16 横 16,上沿一条贴边的 1px 内部分隔线 */
393
+ .xh-scope-drawer[data-part='content']:has(.xh-scope-drawer[data-part='body'])
394
+ .xh-scope-drawer[data-part='footer'] {
395
+ padding-block: var(--xh-drawer-footer-py, var(--xh-overlay-sheet-footer-py));
396
+ padding-inline: var(--xh-drawer-footer-px, var(--xh-surface-px-sm));
397
+ border-block-start: var(--xh-stroke-thin) solid var(--xh-drawer-separator, var(--xh-material-elevated-separator));
398
+ }
399
+
400
+ /* 声明过 display 就盖掉了 UA 的 [hidden]{display:none},收起态得自己还回去 */
401
+ .xh-scope-drawer[data-part='header'][hidden],
402
+ .xh-scope-drawer[data-part='body'][hidden],
403
+ .xh-scope-drawer[data-part='footer'][hidden] {
404
+ display: none;
405
+ }
406
+
407
+ /* 面板标题:页面级面板标题档、正文色;行高钉在 normal,头部带按它算标题行居中 */
408
+ .xh-scope-drawer[data-part='title'] {
409
+ margin: 0;
410
+ font-size: var(--xh-drawer-title-font-size, var(--xh-text-heading-3-size));
411
+ font-weight: var(--xh-drawer-title-font-weight, var(--xh-text-heading-3-weight));
412
+ line-height: var(--xh-leading-normal);
413
+ color: var(--xh-drawer-title-fg, var(--xh-fg-default));
414
+ }
415
+
416
+ /* 说明文字走说明档:13px + fg-muted */
417
+ .xh-scope-drawer[data-part='description'] {
418
+ margin: 0;
419
+ font-size: var(--xh-drawer-description-font-size, var(--xh-text-secondary-size));
420
+ color: var(--xh-drawer-description-fg, var(--xh-fg-muted));
421
+ }
422
+
423
+ /* 关闭按钮是绝对定位的,不占流内宽度:标题得自己让出那块角,
424
+ 否则长标题会直接钻到按钮底下。只在真有关闭按钮时让位。 */
425
+ .xh-scope-drawer[data-part='content']:has(.xh-scope-drawer[data-part='close-trigger'])
426
+ .xh-scope-drawer[data-part='title'] {
427
+ padding-inline-end: calc(var(--xh-drawer-close-size, var(--xh-control-h-sm)) + var(--xh-space-4));
428
+ }
429
+
430
+ /*
431
+ * 关闭钮是面板角落的单图标钮:正方盒、sm 档几何、ghost 四态面、按压换底与粗指针命中区
432
+ * 由家族配方给出——白面上走画布承载阶梯悬停 --xh-bg-subtle(100)→ 按下 --xh-bg-subtle-hover(200),
433
+ * 焦点面透明吃库环。这里只把公开槽桥接到矩阵之前(使用者槽 → 形态矩阵 → 家族缺省)与摆放,
434
+ * 聚焦档的 -bg-focus / -fg-focus 两槽同样桥到配方的 focus-visible 面(与 dialog 一致),缺省仍是透明底与悬停字色;
435
+ * 静息前景取 muted 字色,悬停 / 按下回到 fg-default。
436
+ * 叉取 12px(--xh-glyph-size-xs),比钮的随档字形低一档;钮距右 16px,竖向落在头部带的中线上。
437
+ */
438
+ .xh-scope-drawer[data-part='close-trigger'] {
439
+ --xh-action-visual-size: var(--xh-drawer-close-size, var(--xh-_action-profile-visual-size));
440
+ --xh-action-radius: var(--xh-drawer-close-radius, var(--xh-shape-control));
441
+ --xh-action-bg-hover: var(--xh-drawer-close-bg-hover, var(--xh-_action-variant-bg-hover));
442
+ --xh-action-bg-pressed: var(--xh-drawer-close-bg-active, var(--xh-_action-variant-bg-pressed));
443
+ --xh-action-bg-focus-visible: var(--xh-drawer-close-bg-focus, var(--xh-_action-variant-bg-focus-visible));
444
+ --xh-action-fg-rest: var(--xh-drawer-close-fg, var(--xh-fg-muted));
445
+ --xh-action-fg-hover: var(--xh-drawer-close-fg-hover, var(--xh-_action-variant-fg-hover));
446
+ --xh-action-fg-pressed: var(--xh-drawer-close-fg-hover, var(--xh-_action-variant-fg-pressed));
447
+ --xh-action-fg-focus-visible: var(--xh-drawer-close-fg-focus, var(--xh-drawer-close-fg-hover, var(--xh-_action-variant-fg-focus-visible)));
448
+ /* 作者塞进按钮的图标与皮肤画的兜底叉同一把尺 */
449
+ --xh-icon-size: var(--xh-drawer-icon-size, var(--xh-glyph-size-xs));
450
+
451
+ position: absolute;
452
+ /* 钮的视觉盒在头部带里竖向居中:按钮自己的边长从带高里扣掉再对半 */
453
+ inset-block-start: calc(var(--xh-_drawer-header-top) + (var(--xh-_drawer-header-h) - var(--xh-drawer-close-size, var(--xh-_action-profile-visual-size))) / 2);
454
+ /* 行向先让出安全区再距边 16px:绝对定位从面板的内边距盒量起,横屏刘海压住的那一段不让,叉就落进去;
455
+ 局部容器里的抽屉安全区槽归零,仍是 16px */
456
+ inset-inline-end: calc(var(--xh-_drawer-safe-inline) + var(--xh-space-4));
457
+ }
458
+
459
+ .xh-scope-drawer[data-part='close-trigger'][hidden] {
460
+ display: none;
461
+ }
462
+
463
+ /* 没写内容就由皮肤画兜底字形;作者往部件里塞了自己的图形,这几条即不命中 */
464
+ .xh-scope-drawer[data-part='close-trigger']:empty::before {
465
+ content: '';
466
+ display: inline-block;
467
+ inline-size: var(--xh-icon-size, var(--xh-glyph-size-text));
468
+ block-size: var(--xh-icon-size, var(--xh-glyph-size-text));
469
+ vertical-align: var(--xh-glyph-baseline-shift);
470
+ background-color: currentColor;
471
+ -webkit-mask: var(--xh-glyph-mark-close) center / contain no-repeat;
472
+ mask: var(--xh-glyph-mark-close) center / contain no-repeat;
473
+ }
474
+
475
+ /* —— 改尺 ——
476
+ 把手是一条透明的命中区,贴在朝向页面的那条边上,中间一段指示条标出这里能推:
477
+ 左右放置时是竖条、上下放置时是横条。贴边用逻辑属性:right 贴的是行尾侧,把手落在行首那条边,
478
+ 与机器按书写方向翻转推动方向同源。厚度跟手,不挂过渡 */
479
+ .xh-scope-drawer[data-part='content'][data-resizing] {
480
+ user-select: none;
481
+ }
482
+
483
+ .xh-scope-drawer[data-part='resize-trigger'] {
484
+ --xh-_drawer-resize-indicator: var(--xh-drawer-resize-trigger-bg, var(--xh-border-control));
485
+
486
+ position: absolute;
487
+ display: block;
488
+ border: 0;
489
+ padding: 0;
490
+ background: transparent;
491
+ touch-action: none;
492
+ }
493
+
494
+ .xh-scope-drawer[data-part='resize-trigger']::after {
495
+ content: '';
496
+ position: absolute;
497
+ inset-block-start: 50%;
498
+ inset-inline-start: 50%;
499
+ border-radius: var(--xh-drawer-resize-trigger-radius, var(--xh-shape-pill));
500
+ background: var(--xh-_drawer-resize-indicator);
501
+ pointer-events: none;
502
+ /* 起点是逻辑属性、平移是物理通道:行内分量乘方向符号,RTL 下指示条才落回把手正中 */
503
+ translate: calc(-50% * var(--xh-direction-sign)) -50%;
504
+ transition: background-color var(--xh-motion-duration-micro) var(--xh-motion-ease-enter);
505
+ }
506
+
507
+ .xh-scope-drawer[data-part='resize-trigger']:hover {
508
+ --xh-_drawer-resize-indicator: var(--xh-drawer-resize-trigger-bg-hover, var(--xh-border-control-hover));
509
+ }
510
+
511
+ .xh-scope-drawer[data-part='resize-trigger'][data-resizing] {
512
+ --xh-_drawer-resize-indicator: var(--xh-drawer-resize-trigger-bg-active, var(--xh-bg-brand));
513
+ }
514
+
515
+ /* 键盘落在把手上时指示条换成焦点色:命中区贴着面板边,外扩的环会压到页面上 */
516
+ .xh-scope-drawer[data-part='resize-trigger']:focus-visible {
517
+ --xh-_drawer-resize-indicator: var(--xh-ring-focus);
518
+
519
+ outline: none;
520
+ }
521
+
522
+ .xh-scope-drawer[data-part='resize-trigger'][data-side='left'],
523
+ .xh-scope-drawer[data-part='resize-trigger'][data-side='right'] {
524
+ inset-block: 0;
525
+ inline-size: var(--xh-drawer-resize-trigger-size, var(--xh-space-2));
526
+ cursor: ew-resize;
527
+ }
528
+
529
+ .xh-scope-drawer[data-part='resize-trigger'][data-side='right'] {
530
+ inset-inline-start: 0;
531
+ }
532
+
533
+ .xh-scope-drawer[data-part='resize-trigger'][data-side='left'] {
534
+ inset-inline-end: 0;
535
+ }
536
+
537
+ .xh-scope-drawer[data-part='resize-trigger'][data-side='top'],
538
+ .xh-scope-drawer[data-part='resize-trigger'][data-side='bottom'] {
539
+ inset-inline: 0;
540
+ block-size: var(--xh-drawer-resize-trigger-size, var(--xh-space-2));
541
+ cursor: ns-resize;
542
+ }
543
+
544
+ .xh-scope-drawer[data-part='resize-trigger'][data-side='top'] {
545
+ inset-block-end: 0;
546
+ }
547
+
548
+ .xh-scope-drawer[data-part='resize-trigger'][data-side='bottom'] {
549
+ inset-block-start: 0;
550
+ }
551
+
552
+ .xh-scope-drawer[data-part='resize-trigger']:is([data-side='left'], [data-side='right'])::after {
553
+ inline-size: var(--xh-drawer-resize-indicator-thickness, var(--xh-stroke-strong));
554
+ block-size: var(--xh-drawer-resize-indicator-length, var(--xh-space-8));
555
+ }
556
+
557
+ .xh-scope-drawer[data-part='resize-trigger']:is([data-side='top'], [data-side='bottom'])::after {
558
+ inline-size: var(--xh-drawer-resize-indicator-length, var(--xh-space-8));
559
+ block-size: var(--xh-drawer-resize-indicator-thickness, var(--xh-stroke-strong));
560
+ }
561
+
562
+ .xh-scope-drawer[data-part='resize-trigger'][hidden] {
563
+ display: none;
564
+ }
565
+
566
+ /* 强制色下指示条的底色会被系统色吃掉:改画成正文色,调整中与聚焦时取高亮色 */
567
+ @media (forced-colors: active) {
568
+ .xh-scope-drawer[data-part='resize-trigger']::after {
569
+ forced-color-adjust: none;
570
+ background: CanvasText;
571
+ }
572
+
573
+ .xh-scope-drawer[data-part='resize-trigger']:is([data-resizing], :focus-visible)::after {
574
+ background: Highlight;
575
+ }
576
+ }
577
+
578
+ @media print {
579
+ /* 打印:定位层与遮罩是交互期才存在的东西,落到纸上只会盖住底下的正文。
580
+ 收起写在这份皮肤里而不是 reset:reset 层排在组件层之前,组件层里任何一条 display 都压得住它。 */
581
+ .xh-scope-drawer[data-part='backdrop'],
582
+ .xh-scope-drawer[data-part='positioner'],
583
+ .xh-scope-drawer[data-part='resize-trigger'] {
584
+ display: none;
585
+ }
586
+ }
587
+
588
+ @media (forced-colors: active) {
589
+ /* 兜底字形是 mask 挖出来的一块底色,这一档里底色被系统换成 Canvas,字形跟着消失。
590
+ 字形退出强制换色、直接写系统色(不能取 currentColor:退出强制换色的伪元素读到的是被系统换掉之前的作者色):
591
+ 按钮面上取 ButtonText,悬停与按下时家族把按钮涂成 Highlight、字形换 HighlightText;
592
+ 禁用取 GrayText */
593
+ .xh-scope-drawer[data-part='close-trigger']:empty::before {
594
+ forced-color-adjust: none;
595
+ background-color: ButtonText;
596
+ }
597
+
598
+ .xh-scope-drawer[data-part='close-trigger']:not([data-disabled]):not([data-loading]):is(:hover, :active, [data-pressed]):empty::before {
599
+ background-color: HighlightText;
600
+ }
601
+
602
+ .xh-scope-drawer[data-part='close-trigger'][data-disabled]:empty::before {
603
+ background-color: GrayText;
604
+ }
605
+ }
606
+ }