@xihan-ui/styles 3.1.0 → 3.2.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 (216) hide show
  1. package/CHANGELOG.md +29 -0
  2. package/component-tokens.d.ts +1 -0
  3. package/components.tokens.json +32 -2
  4. package/css/alert.css +2 -2
  5. package/css/approval.css +4 -4
  6. package/css/button.css +9 -5
  7. package/css/calendar-picker.css +3 -3
  8. package/css/calendar-range-picker.css +7 -7
  9. package/css/carousel.css +45 -13
  10. package/css/cartesian-chart.css +11 -11
  11. package/css/cascader.css +10 -10
  12. package/css/citation.css +2 -2
  13. package/css/code-view.css +6 -6
  14. package/css/color-swatch-picker.css +9 -4
  15. package/css/combobox.css +12 -4
  16. package/css/command.css +1 -1
  17. package/css/date-field.css +8 -2
  18. package/css/date-picker.css +13 -7
  19. package/css/date-range-picker.css +13 -7
  20. package/css/diff-view.css +8 -8
  21. package/css/field-array.css +1 -1
  22. package/css/file-upload.css +1 -1
  23. package/css/float-button.css +42 -27
  24. package/css/form.css +6 -6
  25. package/css/graph-chart.css +2 -2
  26. package/css/highlight.css +1 -1
  27. package/css/image.css +1 -1
  28. package/css/mention.css +1 -1
  29. package/css/message-feed.css +1 -1
  30. package/css/notification.css +18 -18
  31. package/css/number-field.css +18 -18
  32. package/css/page-header.css +2 -2
  33. package/css/password-input.css +2 -2
  34. package/css/popconfirm.css +3 -3
  35. package/css/question-flow.css +8 -8
  36. package/css/radar-chart.css +6 -6
  37. package/css/rating.css +1 -1
  38. package/css/select.css +2 -2
  39. package/css/separator.css +2 -2
  40. package/css/side-nav.css +13 -13
  41. package/css/skeleton.css +5 -5
  42. package/css/slider.css +6 -6
  43. package/css/sortable.css +2 -2
  44. package/css/table.css +2 -2
  45. package/css/tags-input.css +1 -1
  46. package/css/tool-call.css +7 -7
  47. package/css/tooltip.css +1 -1
  48. package/css/tree-select.css +2 -2
  49. package/dist/css/accordion.css +269 -0
  50. package/dist/css/affix.css +47 -0
  51. package/dist/css/alert.css +247 -0
  52. package/dist/css/anchor.css +252 -0
  53. package/dist/css/approval.css +501 -0
  54. package/dist/css/avatar-group.css +99 -0
  55. package/dist/css/avatar.css +98 -0
  56. package/dist/css/back-top.css +161 -0
  57. package/dist/css/badge.css +205 -0
  58. package/dist/css/bar-code.css +62 -0
  59. package/dist/css/breadcrumb.css +230 -0
  60. package/dist/css/button-group.css +263 -0
  61. package/dist/css/button.css +219 -0
  62. package/dist/css/calendar-picker.css +467 -0
  63. package/dist/css/calendar-range-picker.css +554 -0
  64. package/dist/css/card.css +221 -0
  65. package/dist/css/carousel.css +710 -0
  66. package/dist/css/cartesian-chart.css +830 -0
  67. package/dist/css/cascader.css +961 -0
  68. package/dist/css/checkbox-group.css +358 -0
  69. package/dist/css/checkbox.css +257 -0
  70. package/dist/css/citation.css +470 -0
  71. package/dist/css/clipboard.css +315 -0
  72. package/dist/css/code-view.css +374 -0
  73. package/dist/css/collapsible.css +185 -0
  74. package/dist/css/color-field.css +176 -0
  75. package/dist/css/color-picker.css +595 -0
  76. package/dist/css/color-slider.css +281 -0
  77. package/dist/css/color-swatch-picker.css +250 -0
  78. package/dist/css/color-swatch.css +35 -0
  79. package/dist/css/combobox.css +574 -0
  80. package/dist/css/command.css +399 -0
  81. package/dist/css/context-menu.css +420 -0
  82. package/dist/css/date-field.css +317 -0
  83. package/dist/css/date-picker.css +868 -0
  84. package/dist/css/date-range-picker.css +886 -0
  85. package/dist/css/description.css +67 -0
  86. package/dist/css/descriptions.css +299 -0
  87. package/dist/css/dialog.css +455 -0
  88. package/dist/css/diff-view.css +513 -0
  89. package/dist/css/download-trigger.css +151 -0
  90. package/dist/css/drawer.css +552 -0
  91. package/dist/css/editable.css +295 -0
  92. package/dist/css/empty-state.css +163 -0
  93. package/dist/css/field-array.css +226 -0
  94. package/dist/css/field.css +166 -0
  95. package/dist/css/fieldset.css +102 -0
  96. package/dist/css/file-upload.css +429 -0
  97. package/dist/css/flex.css +441 -0
  98. package/dist/css/float-button.css +569 -0
  99. package/dist/css/floating-panel.css +429 -0
  100. package/dist/css/focus.css +46 -0
  101. package/dist/css/forced-colors.css +93 -0
  102. package/dist/css/form.css +393 -0
  103. package/dist/css/funnel-chart.css +106 -0
  104. package/dist/css/graph-chart.css +205 -0
  105. package/dist/css/grid-list.css +235 -0
  106. package/dist/css/grid.css +1201 -0
  107. package/dist/css/heatmap.css +552 -0
  108. package/dist/css/hierarchy-chart.css +298 -0
  109. package/dist/css/highlight.css +41 -0
  110. package/dist/css/hover-card.css +226 -0
  111. package/dist/css/icon.css +225 -0
  112. package/dist/css/image-cropper.css +373 -0
  113. package/dist/css/image-viewer.css +538 -0
  114. package/dist/css/image.css +98 -0
  115. package/dist/css/infinite-scroll.css +77 -0
  116. package/dist/css/input-group.css +275 -0
  117. package/dist/css/json-viewer.css +379 -0
  118. package/dist/css/kbd.css +72 -0
  119. package/dist/css/label.css +78 -0
  120. package/dist/css/layers.css +7 -0
  121. package/dist/css/layout.css +372 -0
  122. package/dist/css/liquid.css +106 -0
  123. package/dist/css/list.css +152 -0
  124. package/dist/css/listbox.css +390 -0
  125. package/dist/css/loading-bar.css +141 -0
  126. package/dist/css/log.css +306 -0
  127. package/dist/css/markdown-stream.css +149 -0
  128. package/dist/css/marquee.css +378 -0
  129. package/dist/css/masonry.css +70 -0
  130. package/dist/css/matrix-code.css +67 -0
  131. package/dist/css/mention.css +393 -0
  132. package/dist/css/menu.css +364 -0
  133. package/dist/css/menubar.css +456 -0
  134. package/dist/css/message-feed.css +318 -0
  135. package/dist/css/navigation-menu.css +513 -0
  136. package/dist/css/notification.css +782 -0
  137. package/dist/css/number-animation.css +44 -0
  138. package/dist/css/number-field.css +252 -0
  139. package/dist/css/overlay-arrow.css +56 -0
  140. package/dist/css/page-header.css +184 -0
  141. package/dist/css/pagination.css +450 -0
  142. package/dist/css/password-input.css +391 -0
  143. package/dist/css/pie-chart.css +247 -0
  144. package/dist/css/pin-input.css +199 -0
  145. package/dist/css/pointer.css +36 -0
  146. package/dist/css/popconfirm.css +320 -0
  147. package/dist/css/popover.css +279 -0
  148. package/dist/css/progress.css +501 -0
  149. package/dist/css/prompt-input.css +260 -0
  150. package/dist/css/question-flow.css +553 -0
  151. package/dist/css/radar-chart.css +233 -0
  152. package/dist/css/radio-group.css +598 -0
  153. package/dist/css/rating.css +294 -0
  154. package/dist/css/reasoning.css +343 -0
  155. package/dist/css/reset.css +117 -0
  156. package/dist/css/resizable.css +242 -0
  157. package/dist/css/sankey-chart.css +174 -0
  158. package/dist/css/scroll-area.css +240 -0
  159. package/dist/css/scrollbar.css +204 -0
  160. package/dist/css/select.css +612 -0
  161. package/dist/css/separator.css +122 -0
  162. package/dist/css/side-nav.css +476 -0
  163. package/dist/css/signature-pad.css +179 -0
  164. package/dist/css/skeleton.css +161 -0
  165. package/dist/css/slider.css +374 -0
  166. package/dist/css/sortable.css +228 -0
  167. package/dist/css/sparkline.css +164 -0
  168. package/dist/css/spinner.css +236 -0
  169. package/dist/css/splitter.css +159 -0
  170. package/dist/css/statistic.css +137 -0
  171. package/dist/css/steps.css +627 -0
  172. package/dist/css/switch.css +351 -0
  173. package/dist/css/table.css +1145 -0
  174. package/dist/css/tabs.css +944 -0
  175. package/dist/css/tag-group.css +247 -0
  176. package/dist/css/tag.css +310 -0
  177. package/dist/css/tags-input.css +322 -0
  178. package/dist/css/text-field.css +197 -0
  179. package/dist/css/time-field.css +277 -0
  180. package/dist/css/time-picker.css +707 -0
  181. package/dist/css/time-range-picker.css +746 -0
  182. package/dist/css/timeline.css +423 -0
  183. package/dist/css/timer.css +123 -0
  184. package/dist/css/timestamp.css +34 -0
  185. package/dist/css/toggle-group.css +424 -0
  186. package/dist/css/toggle.css +146 -0
  187. package/dist/css/tone.css +189 -0
  188. package/dist/css/tool-call.css +429 -0
  189. package/dist/css/toolbar.css +365 -0
  190. package/dist/css/tooltip.css +218 -0
  191. package/dist/css/tour.css +439 -0
  192. package/dist/css/transfer.css +638 -0
  193. package/dist/css/tree-select.css +878 -0
  194. package/dist/css/tree.css +733 -0
  195. package/dist/css/truncate.css +108 -0
  196. package/dist/css/typography.css +472 -0
  197. package/dist/css/undefined.css +58 -0
  198. package/dist/css/virtualizer.css +166 -0
  199. package/dist/css/visually-hidden.css +20 -0
  200. package/dist/css/watermark.css +82 -0
  201. package/dist/family/action-control.css +487 -0
  202. package/dist/family/chart.css +480 -0
  203. package/dist/family/check-mark.css +94 -0
  204. package/dist/family/choice-card.css +97 -0
  205. package/dist/family/collection-item.css +764 -0
  206. package/dist/family/field-chrome.css +287 -0
  207. package/dist/family/loading-ring.css +95 -0
  208. package/dist/family/material.css +72 -0
  209. package/dist/family/menu-choice.css +56 -0
  210. package/dist/family/motion.css +363 -0
  211. package/dist/family/swatch.css +59 -0
  212. package/dist/family/tag-list.css +59 -0
  213. package/family/action-control.css +3 -12
  214. package/index.css +6882 -6809
  215. package/index.unlayered.css +6884 -6811
  216. package/package.json +165 -164
package/css/sortable.css CHANGED
@@ -50,7 +50,7 @@
50
50
  其余项反过来要过渡:它们是被让开的,瞬移会看不出发生了什么。
51
51
  键盘拖动时被拖那一项不跟手、逐格挪,与让位的邻项同一段一起滑;抓起时的抬升照常淡变。
52
52
  同组别的列表的一项悬在这里(data-drop='inside')时,插入点及其后的项同样是被让开的 */
53
- [data-scope='sortable'][data-part='root']:is([data-dragging], [data-drop='inside']) [data-part='item']:not([data-dragging]) {
53
+ [data-scope='sortable'][data-part='root']:is([data-dragging], [data-drop='inside']) [data-part='item']:where([data-scope='sortable']):not([data-dragging]) {
54
54
  transition: translate var(--xh-motion-duration-nudge) var(--xh-motion-ease-continuous);
55
55
  }
56
56
 
@@ -62,7 +62,7 @@
62
62
  flex: 0 0 var(--xh-_sortable-incoming-size);
63
63
  }
64
64
 
65
- [data-scope='sortable'][data-part='root'][data-drag-mode='keyboard'] [data-part='item'][data-dragging] {
65
+ [data-scope='sortable'][data-part='root'][data-drag-mode='keyboard'] [data-part='item'][data-dragging]:where([data-scope='sortable']) {
66
66
  transition:
67
67
  translate var(--xh-motion-duration-nudge) var(--xh-motion-ease-continuous),
68
68
  box-shadow var(--xh-motion-duration-micro) var(--xh-motion-ease-enter),
package/css/table.css CHANGED
@@ -419,8 +419,8 @@
419
419
  }
420
420
 
421
421
  /* root 恒报两端(没有冻结列时两端都算贴着);虚拟滚动的行隔着视口,按后代认 */
422
- [data-scope='table'][data-part='root']:not([data-at-min-horizontal]) :is([data-part='column-header'], [data-part='cell'])[data-frozen-edge][data-frozen='start']::after,
423
- [data-scope='table'][data-part='root']:not([data-at-max-horizontal]) :is([data-part='column-header'], [data-part='cell'])[data-frozen-edge][data-frozen='end']::after {
422
+ [data-scope='table'][data-part='root']:not([data-at-min-horizontal]) :is([data-part='column-header'], [data-part='cell']):where([data-scope='table'])[data-frozen-edge][data-frozen='start']::after,
423
+ [data-scope='table'][data-part='root']:not([data-at-max-horizontal]) :is([data-part='column-header'], [data-part='cell']):where([data-scope='table'])[data-frozen-edge][data-frozen='end']::after {
424
424
  opacity: 1;
425
425
  }
426
426
 
@@ -161,7 +161,7 @@
161
161
 
162
162
  /* 新落下的标签原地弹出,同一批按到达顺序错开;首帧就在的直接呈现(自己或 control 带 data-instant)。
163
163
  横排胶囊不用竖向上浮:与来源方向不符,还会探出字段外壳的底边 */
164
- [data-scope='tags-input'][data-part='item']:not([data-instant], [data-instant] > *) {
164
+ [data-scope='tags-input'][data-part='item']:not([data-instant], [data-instant] > :where([data-scope='tags-input'])) {
165
165
  animation: xh-pop-in var(--xh-motion-duration-enter) var(--xh-motion-ease-enter-strong) backwards;
166
166
  animation-delay: calc(var(--xh-_stagger-index, 0) * var(--xh-motion-stagger-step));
167
167
  }
package/css/tool-call.css CHANGED
@@ -41,7 +41,7 @@
41
41
  }
42
42
 
43
43
  /* 卡片出现时滑入;落在首帧就在的列表条目里(历史消息)时直接呈现,不跟着整屏一起入场 */
44
- [data-scope='tool-call'][data-part='root']:not([data-scope][data-part='item'][data-instant] *) {
44
+ [data-scope='tool-call'][data-part='root']:not([data-scope][data-part='item'][data-instant] :where([data-scope='tool-call'])) {
45
45
  animation: xh-item-in var(--xh-motion-duration-enter) var(--xh-motion-ease-enter-strong) both;
46
46
  }
47
47
 
@@ -174,7 +174,7 @@
174
174
  }
175
175
 
176
176
  /* 有摘要时把剩余宽度让给它:工具名只要放得下自己,摘要才是这一行里最想读到的东西 */
177
- [data-scope='tool-call'][data-part='trigger']:has([data-part='summary']) [data-part='label'] {
177
+ [data-scope='tool-call'][data-part='trigger']:has([data-part='summary']) [data-part='label']:where([data-scope='tool-call']) {
178
178
  flex: 0 1 auto;
179
179
  }
180
180
 
@@ -241,7 +241,7 @@
241
241
  /* 在跑的时候状态文字自己扫一道光:data-loading 此前在皮肤里没有任何表达,
242
242
  参数在传与参数齐了两档在屏幕上一模一样。
243
243
  渐变画在背景上再裁进字形,前景与 WebKit 的字形填充色都要透明才透得出底下那道光 */
244
- [data-scope='tool-call'][data-part='root'][data-loading] [data-part='status'] {
244
+ [data-scope='tool-call'][data-part='root'][data-loading] [data-part='status']:where([data-scope='tool-call']) {
245
245
  background-image: linear-gradient(
246
246
  90deg,
247
247
  var(--xh-tool-call-status-shimmer-base, var(--xh-fg-subtle)) 35%,
@@ -259,7 +259,7 @@
259
259
  /* 减少动效:整道光撤掉换回平色,"在跑"仍由状态文字本身表达——只停动画的话,
260
260
  字形里会留着一段冻住的渐变。两条规则是同一件事的两个触发条件:系统偏好与作者打的 data-motion */
261
261
  @media (prefers-reduced-motion: reduce) {
262
- [data-scope='tool-call'][data-part='root'][data-loading] [data-part='status'] {
262
+ [data-scope='tool-call'][data-part='root'][data-loading] [data-part='status']:where([data-scope='tool-call']) {
263
263
  background-image: none;
264
264
  color: var(--xh-tool-call-status-fg, var(--xh-fg-muted));
265
265
  -webkit-text-fill-color: currentColor;
@@ -267,7 +267,7 @@
267
267
  }
268
268
  }
269
269
 
270
- :where([data-motion='reduce']) [data-scope='tool-call'][data-part='root'][data-loading] [data-part='status'] {
270
+ :where([data-motion='reduce']) [data-scope='tool-call'][data-part='root'][data-loading] [data-part='status']:where([data-scope='tool-call']) {
271
271
  background-image: none;
272
272
  color: var(--xh-tool-call-status-fg, var(--xh-fg-muted));
273
273
  -webkit-text-fill-color: currentColor;
@@ -404,7 +404,7 @@
404
404
  取值与减弱动效那一档相同。两档各写一块、不并进一条媒体查询列表:减弱动效另有一份
405
405
  :where([data-motion='reduce']) 的钩子版本与它成对,打印没有对应的钩子可配,
406
406
  并成一条之后这层配对关系在文本上就断了。 */
407
- [data-scope='tool-call'][data-part='root'][data-loading] [data-part='status'] {
407
+ [data-scope='tool-call'][data-part='root'][data-loading] [data-part='status']:where([data-scope='tool-call']) {
408
408
  background-image: none;
409
409
  color: var(--xh-tool-call-status-fg, var(--xh-fg-muted));
410
410
  -webkit-text-fill-color: currentColor;
@@ -417,7 +417,7 @@
417
417
  * 把两处填充都还回去,在跑这件事仍由状态文字本身表出。
418
418
  */
419
419
  @media (forced-colors: active) {
420
- [data-scope='tool-call'][data-part='root'][data-loading] [data-part='status'] {
420
+ [data-scope='tool-call'][data-part='root'][data-loading] [data-part='status']:where([data-scope='tool-call']) {
421
421
  background-image: none;
422
422
  -webkit-background-clip: border-box;
423
423
  background-clip: border-box;
package/css/tooltip.css CHANGED
@@ -181,7 +181,7 @@
181
181
  }
182
182
 
183
183
  /* 高对比仍保持反白语义:compact 配方已把 tint / blur / shadow 换成实体档,此处只加强同色边界。 */
184
- :is([data-contrast='more'] *, [data-contrast='more'])[data-scope='tooltip'][data-part='content'] {
184
+ :is([data-contrast='more'] :where([data-scope='tooltip']), [data-contrast='more'])[data-scope='tooltip'][data-part='content'] {
185
185
  --xh-_tooltip-border: var(--xh-_tooltip-on);
186
186
  }
187
187
 
@@ -227,14 +227,14 @@
227
227
 
228
228
  /* 标签行露面时 value-text 让位:两者是触发器里的同一格,占位文字与标签不同屏。
229
229
  value-text 留在 DOM 里,trigger 的可及名仍从它取到完整的选中项文本 */
230
- [data-scope='tree-select'][data-part='trigger']:has([data-part='tag-list']:not([hidden])) [data-part='value-text'] {
230
+ [data-scope='tree-select'][data-part='trigger']:has([data-part='tag-list']:not([hidden])) [data-part='value-text']:where([data-scope='tree-select']) {
231
231
  display: none;
232
232
  }
233
233
 
234
234
  /* 有值时清空钮顶上来,箭头让位:两个图标并排堆着,用户分不清点哪个。
235
235
  判据查的是盒里此刻真有一颗没收起的清空钮,不是「有没有值」——
236
236
  作者没摆清空钮时箭头照常留着,不然让了位没人接,指示符整个消失 */
237
- [data-scope='tree-select'][data-part='control']:has([data-part='clear-trigger']:not([hidden])) [data-part='indicator'] {
237
+ [data-scope='tree-select'][data-part='control']:has([data-part='clear-trigger']:not([hidden])) [data-part='indicator']:where([data-scope='tree-select']) {
238
238
  display: none;
239
239
  }
240
240
 
@@ -0,0 +1,269 @@
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
+ /* 定义 accordion 样式。 */
7
+
8
+ /* 共享关键帧由 family/motion.css 提供,本皮肤 @import 它,单独引入仍成立;
9
+ 独立皮肤同时传递引入标题栏的动作控件配方,full bundle 递归去重。 */
10
+ @import '../family/motion.css';
11
+ @import '../family/action-control.css';
12
+
13
+ @layer xihan.components {
14
+ /* 皮肤在场的标记:开发模式下按 scope 探一次,取不到就说明这份皮肤没被引入。 */
15
+ .xh-scope-accordion {
16
+ --xh-accordion-skin: 1;
17
+ }
18
+
19
+ .xh-scope-accordion[data-part='root'] {
20
+ /* 作者塞进正文里的图标与皮肤画的兜底字形同一把尺:md 档,标题栏上另按家族档取值 */
21
+ --xh-icon-size: var(--xh-accordion-icon-size, var(--xh-glyph-size-md));
22
+
23
+ /* 尺寸档只换正文这两个私有槽,正文从 root 继承它们;标题栏的三档几何由家族 disclosure-trigger 档给 */
24
+ --xh-_accordion-content-px: var(--xh-space-4);
25
+ --xh-_accordion-content-pb: var(--xh-space-4);
26
+
27
+ /* 语气落在展开着的标题上,指示器写在标题里、跟着继承这个色,不另立规则。
28
+ 没写 data-tone 时 --xh-_tone-fg 没被声明,退回原来的前景色。
29
+ 聚焦环不在其列,它恒是 --xh-ring-focus */
30
+ --xh-_accordion-open-fg: var(--xh-_tone-fg, var(--xh-fg-default));
31
+
32
+ display: flex;
33
+ flex-direction: column;
34
+ inline-size: 100%;
35
+ contain: layout style;
36
+ }
37
+
38
+ .xh-scope-accordion[data-part='root'][data-orientation='horizontal'] {
39
+ flex-direction: row;
40
+ }
41
+
42
+ /* —— 尺寸 —— */
43
+ /* 缺省档写在上面的基础规则里 */
44
+ .xh-scope-accordion[data-part='root'][data-size='sm'] {
45
+ --xh-_accordion-content-px: var(--xh-space-3);
46
+ --xh-_accordion-content-pb: var(--xh-space-3);
47
+ }
48
+
49
+ .xh-scope-accordion[data-part='root'][data-size='lg'] {
50
+ --xh-_accordion-content-px: var(--xh-space-5);
51
+ --xh-_accordion-content-pb: var(--xh-space-5);
52
+ }
53
+
54
+ .xh-scope-accordion[data-part='item'] {
55
+ position: relative;
56
+ min-inline-size: 0;
57
+ }
58
+
59
+ /* 分隔线画在后一条的起始边,条与条之间才只有一条,末条也不会留一条悬空线
60
+ (根没有外框接住它)。只认自己的直接子条目:套在条目里的另一份手风琴由它自己的根管。
61
+ 横排时换成行内轴那一侧 */
62
+ .xh-scope-accordion[data-part='root']
63
+ > .xh-scope-accordion[data-part='item']
64
+ + .xh-scope-accordion[data-part='item'] {
65
+ border-block-start: var(--xh-stroke-thin) solid var(--xh-accordion-item-border, var(--xh-border-subtle));
66
+ }
67
+
68
+ .xh-scope-accordion[data-part='root'][data-orientation='horizontal']
69
+ > .xh-scope-accordion[data-part='item']
70
+ + .xh-scope-accordion[data-part='item'] {
71
+ border-block-start: 0;
72
+ border-inline-start: var(--xh-stroke-thin) solid var(--xh-accordion-item-border, var(--xh-border-subtle));
73
+ }
74
+
75
+ /* 作者显式渲染的分隔线。渲染了它,上面那条 item + item 的相邻规则就不再命中,
76
+ 两条线不会同时出现 */
77
+ .xh-scope-accordion[data-part='item-separator'] {
78
+ flex: none;
79
+ block-size: var(--xh-stroke-thin);
80
+ border: 0;
81
+ margin: 0;
82
+ background: var(--xh-accordion-item-border, var(--xh-border-subtle));
83
+ }
84
+
85
+ .xh-scope-accordion[data-part='item-separator'][hidden] {
86
+ display: none;
87
+ }
88
+
89
+ .xh-scope-accordion[data-part='root'][data-orientation='horizontal']
90
+ > .xh-scope-accordion[data-part='item-separator'] {
91
+ block-size: auto;
92
+ inline-size: var(--xh-stroke-thin);
93
+ }
94
+
95
+ /* —— 形态 —— */
96
+ /* ghost 档不在这儿:它就是上面那套基础取值,写不写 data-variant 都长一个样 */
97
+ /* 整份有了一块面,条与条之间就不再靠那条相邻边分开 */
98
+ .xh-scope-accordion[data-part='root']:is([data-variant='outline'], [data-variant='subtle'])
99
+ > .xh-scope-accordion[data-part='item']
100
+ + .xh-scope-accordion[data-part='item'] {
101
+ border-block-start: 0;
102
+ border-inline-start: 0;
103
+ }
104
+
105
+ /* outline:一张静态内容面,--xh-border-default 描边 + surface 底 + 无影(边界只由描边承担);
106
+ 根的外边走 --xh-accordion-border,与条与条之间的分隔线槽 --xh-accordion-item-border 各管各的 */
107
+ .xh-scope-accordion[data-part='root'][data-variant='outline'] {
108
+ border: var(--xh-stroke-thin) solid var(--xh-accordion-border, var(--xh-border-default));
109
+ border-radius: var(--xh-accordion-item-radius, var(--xh-shape-surface));
110
+ background: var(--xh-accordion-item-bg, var(--xh-bg-surface));
111
+ box-shadow: var(--xh-accordion-item-shadow, none);
112
+ overflow: clip;
113
+ }
114
+
115
+ /* subtle:同一块连续表面,底换成淡底,描边让位给底色但留住 1px 边位(三档几何一致);
116
+ 淡底承载面向标题栏下发 hover 200 → pressed 300 */
117
+ .xh-scope-accordion[data-part='root'][data-variant='subtle'] {
118
+ --xh-action-host-bg-hover: var(--xh-bg-subtle-hover);
119
+ --xh-action-host-bg-pressed: var(--xh-bg-subtle-active);
120
+
121
+ border: var(--xh-stroke-thin) solid transparent;
122
+ border-radius: var(--xh-accordion-item-radius, var(--xh-shape-surface));
123
+ background: var(--xh-accordion-item-bg, var(--xh-bg-subtle));
124
+ box-shadow: var(--xh-accordion-item-shadow, none);
125
+ overflow: clip;
126
+ }
127
+
128
+ .xh-scope-accordion[data-part='root']:is([data-variant='outline'], [data-variant='subtle'])
129
+ > .xh-scope-accordion[data-part='item']:not(:last-child)::after {
130
+ content: '';
131
+ position: absolute;
132
+ inset-inline: 3%;
133
+ inset-block-end: 0;
134
+ block-size: var(--xh-stroke-thin);
135
+ background: var(--xh-accordion-item-border, var(--xh-border-subtle));
136
+ pointer-events: none;
137
+ }
138
+
139
+ .xh-scope-accordion[data-part='header'] {
140
+ margin: 0;
141
+ font: inherit;
142
+ }
143
+
144
+ /* 标题栏铺满一行,盒型、三档几何、悬停 / 按下 / 禁用面由 Action Control 的 disclosure-trigger 档给
145
+ (ghost 形态:白底承载 hover 100 → pressed 200,淡底容器由根下发 host 槽;按下只换面不缩放);
146
+ 这里只把使用者槽映射到桥接槽:字色三态同值(家族的 hover / pressed 字色规则比皮肤更特定,不映射会被换回
147
+ 缺省字色),字形按标题栏自己的档位取 --xh-_action-profile-glyph-size;边归零贴住条目,几何与迁移前一致 */
148
+ .xh-scope-accordion[data-part='trigger'] {
149
+ --xh-action-gap: var(--xh-accordion-trigger-gap, var(--xh-_action-profile-gap));
150
+ --xh-action-visual-size: var(--xh-accordion-trigger-h, var(--xh-_action-profile-visual-size));
151
+ --xh-action-padding-block: var(--xh-accordion-trigger-py, var(--xh-_action-profile-padding-block));
152
+ --xh-action-padding-inline: var(--xh-accordion-trigger-px, var(--xh-_action-profile-padding-inline));
153
+ --xh-action-radius: var(--xh-accordion-trigger-radius, var(--xh-_action-profile-radius));
154
+ --xh-action-bg-rest: var(--xh-accordion-trigger-bg, var(--xh-_action-variant-bg-rest));
155
+ --xh-action-bg-hover: var(--xh-accordion-trigger-bg-hover, var(--xh-_action-variant-bg-hover));
156
+ --xh-action-fg-rest: var(--xh-accordion-trigger-fg, var(--xh-_action-variant-fg-rest));
157
+ --xh-action-fg-hover: var(--xh-accordion-trigger-fg, var(--xh-_action-variant-fg-hover));
158
+ --xh-action-fg-pressed: var(--xh-accordion-trigger-fg, var(--xh-_action-variant-fg-pressed));
159
+ --xh-action-font-size: var(--xh-accordion-trigger-font-size, var(--xh-_action-profile-font-size));
160
+ --xh-icon-size: var(--xh-accordion-icon-size, var(--xh-_action-profile-glyph-size));
161
+
162
+ border-width: 0;
163
+ font-weight: var(--xh-accordion-trigger-font-weight, var(--xh-text-label-weight));
164
+ }
165
+
166
+ /* 展开态自带一个槽:与常态共用一个的话,作者一改常态字色,
167
+ 展开那一档的语气高亮就跟着被抹平,再也分不开。悬停 / 按下的面与收起态同档(open 与家族 hover 同档中性) */
168
+ .xh-scope-accordion[data-part='trigger'][data-state='open'] {
169
+ --xh-action-fg-rest: var(--xh-accordion-trigger-fg-open, var(--xh-_accordion-open-fg));
170
+ --xh-action-fg-hover: var(--xh-accordion-trigger-fg-open, var(--xh-_accordion-open-fg));
171
+ --xh-action-fg-pressed: var(--xh-accordion-trigger-fg-open, var(--xh-_accordion-open-fg));
172
+ }
173
+
174
+ /* 禁用条目走 aria-disabled,仍留在 Tab 序里,只是不可操作;前景换成禁用色,不靠 opacity 压暗
175
+ (家族按 data-disabled 给禁用面与指针,字色槽在这里保留优先) */
176
+ .xh-scope-accordion[data-part='trigger'][data-disabled] {
177
+ --xh-action-fg-disabled: var(--xh-accordion-trigger-fg-disabled, var(--xh-_action-variant-fg-disabled));
178
+ }
179
+
180
+ .xh-scope-accordion[data-part='indicator'] {
181
+ display: inline-flex;
182
+ align-items: center;
183
+ justify-content: center;
184
+ flex: none;
185
+ color: var(--xh-accordion-indicator-fg, var(--xh-fg-muted));
186
+ line-height: var(--xh-leading-none);
187
+ }
188
+
189
+ /* 指示器与正文同档转向:收起时取 collapse 档,展开时(下面的打开态)取 expand 档。
190
+ 首帧就在的朝向直接呈现(data-instant),第一次开合起才转 */
191
+ .xh-scope-accordion[data-part='indicator']:not([data-instant]) {
192
+ transition: rotate var(--xh-motion-duration-collapse) var(--xh-motion-ease-enter-strong);
193
+ }
194
+
195
+ /* 没写内容就由皮肤画;作者往部件里塞了自己的图形,这条规则即不命中 */
196
+ .xh-scope-accordion[data-part='indicator']:empty::before {
197
+ content: '';
198
+ display: inline-block;
199
+ inline-size: var(--xh-icon-size, var(--xh-glyph-size-md));
200
+ block-size: var(--xh-icon-size, var(--xh-glyph-size-md));
201
+ vertical-align: var(--xh-glyph-baseline-shift);
202
+ background-color: currentColor;
203
+ -webkit-mask: var(--xh-glyph-mark-chevron-down) center / contain no-repeat;
204
+ mask: var(--xh-glyph-mark-chevron-down) center / contain no-repeat;
205
+ }
206
+
207
+ .xh-scope-accordion[data-part='indicator'][data-state='open'] {
208
+ rotate: 180deg;
209
+ }
210
+
211
+ .xh-scope-accordion[data-part='indicator'][data-state='open']:not([data-instant]) {
212
+ transition: rotate var(--xh-motion-duration-expand) var(--xh-motion-ease-enter-strong);
213
+ }
214
+
215
+ /* 这里刻意没有 [data-part='content'][hidden] { display: none }:补了动画一帧都播不出来。
216
+ 收起由适配器在退场结束后写内联 display 落成,退场窗口内靠 connect 发的 inert 挡住焦点 */
217
+ .xh-scope-accordion[data-part='content'] {
218
+ /* 行高与内缩同帧动的共享关键帧读这条槽:只有末端有内缩,起端不写、按 0 动 */
219
+ --xh-_disclosure-pb: var(--xh-accordion-content-pb, var(--xh-_accordion-content-pb));
220
+
221
+ display: grid;
222
+ grid-template-rows: 1fr;
223
+ overflow: clip;
224
+ padding-block-start: 0;
225
+ padding-block-end: var(--xh-accordion-content-pb, var(--xh-_accordion-content-pb));
226
+ padding-inline: var(--xh-accordion-content-px, var(--xh-_accordion-content-px));
227
+ color: var(--xh-accordion-content-fg, var(--xh-fg-muted));
228
+ font-size: var(--xh-accordion-content-font-size, var(--xh-text-secondary-size));
229
+ line-height: var(--xh-leading-normal);
230
+ }
231
+
232
+ /* 展开与收起只在开合时播:首帧就在的展开 / 收起直接呈现(data-instant) */
233
+ .xh-scope-accordion[data-part='content'][data-state='open']:not([data-instant]) {
234
+ animation: xh-disclosure-expand var(--xh-motion-duration-expand) var(--xh-motion-ease-enter-strong);
235
+ }
236
+
237
+ .xh-scope-accordion[data-part='content'][data-state='closed']:not([data-instant]) {
238
+ animation: xh-disclosure-collapse var(--xh-motion-duration-collapse) var(--xh-motion-ease-exit) forwards;
239
+ }
240
+
241
+ @media (forced-colors: active) {
242
+ /* 兜底字形是 mask 挖出来的一块底色,这一档里底色被系统换成 Canvas,字形跟着消失。
243
+ 字形退出强制换色、直接写系统色(不能取 currentColor:退出强制换色的伪元素读到的是被系统换掉之前的作者色):
244
+ 按钮面上取 ButtonText,悬停与按下时家族把按钮涂成 Highlight、字形换 HighlightText;
245
+ 禁用取 GrayText */
246
+ .xh-scope-accordion[data-part='indicator']:empty::before {
247
+ forced-color-adjust: none;
248
+ background-color: ButtonText;
249
+ }
250
+
251
+ .xh-scope-accordion[data-part='trigger']:not([data-disabled]):not([data-loading]):is(:hover, :active, [data-pressed]) .xh-scope-accordion[data-part='indicator']:empty::before {
252
+ background-color: HighlightText;
253
+ }
254
+
255
+ .xh-scope-accordion[data-part='trigger'][data-disabled] .xh-scope-accordion[data-part='indicator']:empty::before {
256
+ background-color: GrayText;
257
+ }
258
+ }
259
+ }
260
+
261
+ @layer xihan.motion {
262
+ /* 声明过任何 display 就盖掉了 UA 的 [hidden]{display:none},收起态得自己还回去。
263
+ 写在文件末尾:兜底必须排在该部件所有 display 声明之后 */
264
+ .xh-scope-accordion[data-part='root'][hidden],
265
+ .xh-scope-accordion[data-part='trigger'][hidden],
266
+ .xh-scope-accordion[data-part='indicator'][hidden] {
267
+ display: none;
268
+ }
269
+ }
@@ -0,0 +1,47 @@
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
+ /* 定义 affix 样式。 */
7
+
8
+ @layer xihan.components {
9
+ /* 皮肤在场的标记:开发模式下按 scope 探一次,取不到就说明这份皮肤没被引入。 */
10
+ .xh-scope-affix {
11
+ --xh-affix-skin: 1;
12
+ }
13
+
14
+ /* 占位盒就是 content 在常规流里占的那块地方。
15
+ 这里不声明 display,也不写高度:吸住时冻结的高度由连接层量好写进内联样式(它量得到,样式表量不到),
16
+ 没吸住时高度就该跟着内容走。不给 display,UA 的 [hidden]{display:none} 也仍然压得住 */
17
+ .xh-scope-affix[data-part='root'] {
18
+ /* 脱流后 content 不再撑开占位盒,宽度改从父级取 */
19
+ inline-size: 100%;
20
+ }
21
+
22
+ /* 没吸住时是常规流里普通的一块,不做任何定位 */
23
+ .xh-scope-affix[data-part='content'] {
24
+ inline-size: 100%;
25
+ }
26
+
27
+ /*
28
+ * 吸住:脱离常规流钉在视口上。
29
+ * 四个落位数(top / bottom / left / width)由连接层写成内联样式——它们是照占位盒的矩形实测出来的
30
+ * 物理量,换成逻辑属性会在 RTL 下贴反。这里只管「用哪种定位、压在第几层」。
31
+ * 另一件必须提防的事:fixed 认的是视口,祖先上一旦出现
32
+ * transform / filter / backdrop-filter / contain,包含块就被抢走,钉住的内容立刻贴错位置——
33
+ * 所以别往覆盖钩子里加这几个属性。
34
+ */
35
+ .xh-scope-affix[data-part='content'][data-fixed] {
36
+ position: fixed;
37
+ z-index: var(--xh-affix-layer, var(--xh-layer-sticky));
38
+ }
39
+
40
+ @media print {
41
+ /* 打印:钉住的是作者自己的内容,不能收起;但保持 fixed 会让部分打印引擎每页重复一次,
42
+ 所以只把它放回正常流。 */
43
+ .xh-scope-affix[data-part='content'][data-fixed] {
44
+ position: static;
45
+ }
46
+ }
47
+ }