@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
@@ -186,10 +186,12 @@
186
186
  }
187
187
 
188
188
  /* 作者塞进来的图形跟着勾同一套显隐 */
189
+ /* 显隐写在 indicator 自己的私有槽上、图形只读槽:作者的图形没有可认的特征,
190
+ 规则主体不能挂在 data-state 后面(翻转时会让全页同名属性的变化整棵子树重算) */
189
191
  [data-scope='color-swatch-picker'][data-part='indicator'] > * {
190
192
  position: relative;
191
193
  color: var(--xh-color-swatch-picker-indicator-fg, var(--xh-_tone-on, var(--xh-fg-on-brand)));
192
- opacity: 0;
194
+ opacity: var(--xh-_color-swatch-picker-glyph-opacity, 0);
193
195
  transition: opacity var(--xh-motion-duration-micro) var(--xh-motion-ease-enter);
194
196
  }
195
197
 
@@ -199,8 +201,11 @@
199
201
  scale: 1;
200
202
  }
201
203
 
202
- [data-scope='color-swatch-picker'][data-part='indicator'][data-state='checked']:empty::after,
203
- [data-scope='color-swatch-picker'][data-part='indicator'][data-state='checked'] > * {
204
+ [data-scope='color-swatch-picker'][data-part='indicator'][data-state='checked'] {
205
+ --xh-_color-swatch-picker-glyph-opacity: 1;
206
+ }
207
+
208
+ [data-scope='color-swatch-picker'][data-part='indicator'][data-state='checked']:empty::after {
204
209
  opacity: 1;
205
210
  }
206
211
 
@@ -227,7 +232,7 @@
227
232
  */
228
233
  @media (forced-colors: active) {
229
234
  /* 家族在这一档把色块描边统一钉成 CanvasText,选中的那一格要在它之上换成高亮色 */
230
- [data-scope='color-swatch-picker'][data-part='item'][data-state='checked'] > [data-part='swatch'] {
235
+ [data-scope='color-swatch-picker'][data-part='item'][data-state='checked'] > [data-part='swatch']:where([data-scope='color-swatch-picker']) {
231
236
  border-color: Highlight;
232
237
  }
233
238
 
package/css/combobox.css CHANGED
@@ -236,14 +236,19 @@
236
236
  /* 有值时清空钮顶上来,展开钮让位:两颗并排堆着用户分不清点哪个,换来换去还会让盒的宽度跳一下。
237
237
  判据是盒里此刻有一颗没收起的清空钮——没写清空钮的结构里展开钮照常留着;
238
238
  输入框仍是展开的入口(打字、方向键、openOnClick) */
239
- [data-scope='combobox'][data-part='control']:has([data-part='clear-trigger']:not([hidden])) [data-part='trigger'] {
239
+ [data-scope='combobox'][data-part='control']:has([data-part='clear-trigger']:not([hidden])) [data-part='trigger']:where([data-scope='combobox']) {
240
240
  display: none;
241
241
  }
242
242
 
243
243
  /* 展开时箭头翻个面,指向与列表的去向一致。转的是字形或作者塞的图形,不转按钮本体:
244
244
  按钮自带悬停底色,整个按钮转会带着底色一起转;家族按压缩放的是整钮,不影响这里的转向 */
245
- [data-scope='combobox'][data-part='trigger']:empty::before,
245
+ [data-scope='combobox'][data-part='trigger']:empty::before {
246
+ transition: rotate var(--xh-motion-duration-nudge) var(--xh-motion-ease-enter-strong);
247
+ }
248
+
249
+ /* 作者的箭头是任意节点:转向写在 trigger 自己的私有槽上,箭头只读槽(规则主体无特征时不挂在 data-state 后面) */
246
250
  [data-scope='combobox'][data-part='trigger'] > * {
251
+ rotate: var(--xh-_combobox-trigger-turn, none);
247
252
  transition: rotate var(--xh-motion-duration-nudge) var(--xh-motion-ease-enter-strong);
248
253
  }
249
254
 
@@ -272,11 +277,14 @@
272
277
  }
273
278
 
274
279
  /* 打开中与悬停同档:展开钮不另上底,方向由箭头转向承担 */
275
- [data-scope='combobox'][data-part='trigger'][data-state='open']:empty::before,
276
- [data-scope='combobox'][data-part='trigger'][data-state='open'] > * {
280
+ [data-scope='combobox'][data-part='trigger'][data-state='open']:empty::before {
277
281
  rotate: 180deg;
278
282
  }
279
283
 
284
+ [data-scope='combobox'][data-part='trigger'][data-state='open'] {
285
+ --xh-_combobox-trigger-turn: 180deg;
286
+ }
287
+
280
288
  [data-scope='combobox'][data-part='content'] {
281
289
  /* 材质由家族配方画(family/material.css 的 frosted 面:描边、底、1px 顶光、前景、投影与背景滤镜),
282
290
  这里只把使用者槽接进来 */
package/css/command.css CHANGED
@@ -298,7 +298,7 @@
298
298
  不会拖出一条越来越慢的尾巴)。打开时已有的结果直接呈现:自己或本列表带 data-instant。
299
299
  检索过滤筛掉的条目带 hidden 不生成盒子,重新露面只是换一批已有结果,机器给它打上 data-instant 直接呈现。
300
300
  backwards 让每条在自己那份延迟里保持起始帧 */
301
- [data-scope='command'][data-part='list'] [data-part='item']:not([data-instant], [data-scope='command'][data-part='list'][data-instant] *) {
301
+ [data-scope='command'][data-part='list'] [data-part='item']:where([data-scope='command']):not([data-instant], [data-scope='command'][data-part='list'][data-instant] :where([data-scope='command'])) {
302
302
  animation: xh-rise-in var(--xh-motion-duration-enter) var(--xh-motion-ease-enter-strong) backwards;
303
303
  animation-delay: calc(var(--xh-_stagger-index, 0) * var(--xh-motion-stagger-step));
304
304
  }
@@ -130,8 +130,14 @@
130
130
  color: transparent;
131
131
  }
132
132
 
133
- [data-scope='date-field'][data-part='segment-group'][data-placeholder-shown] > * {
134
- opacity: 0;
133
+ /* 段位与分隔符(后者是不带解剖的文字节点)一起淡出:显隐写在 segment-group 自己的私有槽上,
134
+ 子节点只读槽——主体无特征的规则不挂在 data-placeholder-shown 后面,输入时翻转只让这一组失效 */
135
+ [data-scope='date-field'][data-part='segment-group'][data-placeholder-shown] {
136
+ --xh-_date-field-segment-opacity: 0;
137
+ }
138
+
139
+ [data-scope='date-field'][data-part='segment-group'] > * {
140
+ opacity: var(--xh-_date-field-segment-opacity, 1);
135
141
  }
136
142
 
137
143
  [data-scope='date-field'][data-part='segment-group'][data-placeholder-shown]::before {
@@ -211,8 +211,14 @@
211
211
  color: transparent;
212
212
  }
213
213
 
214
- [data-scope='date-picker'][data-part='segment-group'][data-placeholder-shown] > * {
215
- opacity: 0;
214
+ /* 段位与分隔符(后者是不带解剖的文字节点)一起淡出:显隐写在 segment-group 自己的私有槽上,
215
+ 子节点只读槽——主体无特征的规则不挂在 data-placeholder-shown 后面,输入时翻转只让这一组失效 */
216
+ [data-scope='date-picker'][data-part='segment-group'][data-placeholder-shown] {
217
+ --xh-_date-picker-segment-opacity: 0;
218
+ }
219
+
220
+ [data-scope='date-picker'][data-part='segment-group'] > * {
221
+ opacity: var(--xh-_date-picker-segment-opacity, 1);
216
222
  }
217
223
 
218
224
  [data-scope='date-picker'][data-part='segment-group'][data-placeholder-shown]::before {
@@ -401,7 +407,7 @@
401
407
  }
402
408
 
403
409
  /* 确认按钮沉到所在那一行的底边:它是整块面板的出口,不跟日历顶边对齐 */
404
- [data-scope='date-picker'][data-part='content']:has(> [data-part='time-column']) > [data-part='confirm-trigger'] {
410
+ [data-scope='date-picker'][data-part='content']:has(> [data-part='time-column']) > [data-part='confirm-trigger']:where([data-scope='date-picker']) {
405
411
  align-self: flex-end;
406
412
  }
407
413
 
@@ -721,7 +727,7 @@
721
727
 
722
728
  /* 列整体禁用时格没有自己的 aria-disabled,禁用面按列的 aria-disabled 映射到家族槽:
723
729
  字色降级、悬停 / 高亮 / 按下不换面、光标 not-allowed */
724
- [data-scope='date-picker'][data-part='time-column'][aria-disabled='true'] [data-part='time-item'] {
730
+ [data-scope='date-picker'][data-part='time-column'][aria-disabled='true'] [data-part='time-item']:where([data-scope='date-picker']) {
725
731
  --xh-collection-fg-rest: var(--xh-fg-disabled);
726
732
  --xh-collection-fg-hover: var(--xh-fg-disabled);
727
733
  --xh-collection-fg-keyboard-highlight: var(--xh-fg-disabled);
@@ -740,7 +746,7 @@
740
746
  --xh-collection-cursor-selected: not-allowed;
741
747
  }
742
748
 
743
- [data-scope='date-picker'][data-part='time-column'][aria-disabled='true'] [data-part='time-item']::after {
749
+ [data-scope='date-picker'][data-part='time-column'][aria-disabled='true'] [data-part='time-item']:where([data-scope='date-picker'])::after {
744
750
  background-color: var(--xh-fg-disabled);
745
751
  }
746
752
 
@@ -820,13 +826,13 @@
820
826
 
821
827
  [data-scope='date-picker'][data-part='preset'][data-disabled]::after,
822
828
  [data-scope='date-picker'][data-part='time-item'][data-disabled]::after,
823
- [data-scope='date-picker'][data-part='time-column'][aria-disabled='true'] [data-part='time-item']::after {
829
+ [data-scope='date-picker'][data-part='time-column'][aria-disabled='true'] [data-part='time-item']:where([data-scope='date-picker'])::after {
824
830
  background-color: GrayText;
825
831
  }
826
832
 
827
833
  [data-scope='date-picker'][data-part='preset'][data-disabled],
828
834
  [data-scope='date-picker'][data-part='time-item'][data-disabled],
829
- [data-scope='date-picker'][data-part='time-column'][aria-disabled='true'] [data-part='time-item'] {
835
+ [data-scope='date-picker'][data-part='time-column'][aria-disabled='true'] [data-part='time-item']:where([data-scope='date-picker']) {
830
836
  color: GrayText;
831
837
  }
832
838
  }
@@ -239,8 +239,14 @@
239
239
  color: transparent;
240
240
  }
241
241
 
242
- [data-scope='date-range-picker'][data-part='segment-group'][data-placeholder-shown] > * {
243
- opacity: 0;
242
+ /* 段位与分隔符(后者是不带解剖的文字节点)一起淡出:显隐写在 segment-group 自己的私有槽上,
243
+ 子节点只读槽——主体无特征的规则不挂在 data-placeholder-shown 后面,输入时翻转只让这一组失效 */
244
+ [data-scope='date-range-picker'][data-part='segment-group'][data-placeholder-shown] {
245
+ --xh-_date-range-picker-segment-opacity: 0;
246
+ }
247
+
248
+ [data-scope='date-range-picker'][data-part='segment-group'] > * {
249
+ opacity: var(--xh-_date-range-picker-segment-opacity, 1);
244
250
  }
245
251
 
246
252
  [data-scope='date-range-picker'][data-part='segment-group'][data-placeholder-shown]::before {
@@ -553,7 +559,7 @@
553
559
  }
554
560
 
555
561
  /* 确认按钮沉到所在那一行的底边:它是整块面板的出口,不跟日历顶边对齐 */
556
- [data-scope='date-range-picker'][data-part='content']:has(> [data-part='column-group']) > [data-part='confirm-trigger'] {
562
+ [data-scope='date-range-picker'][data-part='content']:has(> [data-part='column-group']) > [data-part='confirm-trigger']:where([data-scope='date-range-picker']) {
557
563
  align-self: flex-end;
558
564
  }
559
565
 
@@ -735,7 +741,7 @@
735
741
 
736
742
  /* 列整体禁用时格没有自己的 aria-disabled,禁用面按列的 aria-disabled 映射到家族槽:
737
743
  字色降级、悬停 / 高亮 / 按下不换面、光标 not-allowed */
738
- [data-scope='date-range-picker'][data-part='time-column'][aria-disabled='true'] [data-part='time-item'] {
744
+ [data-scope='date-range-picker'][data-part='time-column'][aria-disabled='true'] [data-part='time-item']:where([data-scope='date-range-picker']) {
739
745
  --xh-collection-fg-rest: var(--xh-fg-disabled);
740
746
  --xh-collection-fg-hover: var(--xh-fg-disabled);
741
747
  --xh-collection-fg-keyboard-highlight: var(--xh-fg-disabled);
@@ -754,7 +760,7 @@
754
760
  --xh-collection-cursor-selected: not-allowed;
755
761
  }
756
762
 
757
- [data-scope='date-range-picker'][data-part='time-column'][aria-disabled='true'] [data-part='time-item']::after {
763
+ [data-scope='date-range-picker'][data-part='time-column'][aria-disabled='true'] [data-part='time-item']:where([data-scope='date-range-picker'])::after {
758
764
  background-color: var(--xh-fg-disabled);
759
765
  }
760
766
 
@@ -833,13 +839,13 @@
833
839
 
834
840
  [data-scope='date-range-picker'][data-part='preset'][data-disabled]::after,
835
841
  [data-scope='date-range-picker'][data-part='time-item'][data-disabled]::after,
836
- [data-scope='date-range-picker'][data-part='time-column'][aria-disabled='true'] [data-part='time-item']::after {
842
+ [data-scope='date-range-picker'][data-part='time-column'][aria-disabled='true'] [data-part='time-item']:where([data-scope='date-range-picker'])::after {
837
843
  background-color: GrayText;
838
844
  }
839
845
 
840
846
  [data-scope='date-range-picker'][data-part='preset'][data-disabled],
841
847
  [data-scope='date-range-picker'][data-part='time-item'][data-disabled],
842
- [data-scope='date-range-picker'][data-part='time-column'][aria-disabled='true'] [data-part='time-item'] {
848
+ [data-scope='date-range-picker'][data-part='time-column'][aria-disabled='true'] [data-part='time-item']:where([data-scope='date-range-picker']) {
843
849
  color: GrayText;
844
850
  }
845
851
 
package/css/diff-view.css CHANGED
@@ -164,7 +164,7 @@
164
164
  /* 窄档的并排视图:一行的两侧改成上下两段,旧行在上、新行在下。
165
165
  行由横排 flex 换成两列栅格——行号一列、正文一列,一行里的四个格按 DOM 次序
166
166
  自然落成两行,正文列因此只按单侧的最长行撑宽,不再是两侧之和 */
167
- [data-scope='diff-view'][data-part='root'][data-view='split'] [data-part='row']:not([hidden]) {
167
+ [data-scope='diff-view'][data-part='root'][data-view='split'] [data-part='row']:where([data-scope='diff-view']):not([hidden]) {
168
168
  display: grid;
169
169
  grid-template-columns: auto minmax(0, 1fr);
170
170
  }
@@ -197,13 +197,13 @@
197
197
 
198
198
  /* 开了换行:pre-wrap 仍保留缩进与连续空白,只是允许行尾折下来;
199
199
  anywhere 让没有空格的长串(url、base64)也能断 */
200
- [data-scope='diff-view'][data-part='root'][data-wrap] [data-part='line-content'] {
200
+ [data-scope='diff-view'][data-part='root'][data-wrap] [data-part='line-content']:where([data-scope='diff-view']) {
201
201
  white-space: pre-wrap;
202
202
  overflow-wrap: anywhere;
203
203
  }
204
204
 
205
205
  /* 正文原本按最长行撑宽,不解除就折不下来 */
206
- [data-scope='diff-view'][data-part='root'][data-wrap] [data-part='body'] {
206
+ [data-scope='diff-view'][data-part='root'][data-wrap] [data-part='body']:where([data-scope='diff-view']) {
207
207
  min-inline-size: 0;
208
208
  }
209
209
 
@@ -348,7 +348,7 @@
348
348
  --xh-_diff-view-comment-col: var(--xh-diff-view-comment-col, var(--xh-diff-view-line-height, var(--xh-text-code-leading)));
349
349
  }
350
350
 
351
- [data-scope='diff-view'][data-part='root'][data-commentable] [data-part='line-content'] {
351
+ [data-scope='diff-view'][data-part='root'][data-commentable] [data-part='line-content']:where([data-scope='diff-view']) {
352
352
  position: relative;
353
353
  padding-inline-start: var(--xh-_diff-view-comment-col);
354
354
  }
@@ -387,8 +387,8 @@
387
387
  --xh-action-opacity-rest: 0;
388
388
  }
389
389
 
390
- [data-scope='diff-view'][data-part='row']:hover [data-part='comment-trigger'],
391
- [data-scope='diff-view'][data-part='viewport']:focus-within [data-part='comment-trigger'] {
390
+ [data-scope='diff-view'][data-part='row']:hover [data-part='comment-trigger']:where([data-scope='diff-view']),
391
+ [data-scope='diff-view'][data-part='viewport']:focus-within [data-part='comment-trigger']:where([data-scope='diff-view']) {
392
392
  --xh-action-opacity-rest: 1;
393
393
  }
394
394
  }
@@ -434,13 +434,13 @@
434
434
 
435
435
  /* 宽档:视口放得下两列,并排视图回到一行两侧 */
436
436
  @media (min-width: 1024px) {
437
- [data-scope='diff-view'][data-part='root'][data-view='split'] [data-part='row']:not([hidden]) {
437
+ [data-scope='diff-view'][data-part='root'][data-view='split'] [data-part='row']:where([data-scope='diff-view']):not([hidden]) {
438
438
  display: flex;
439
439
  }
440
440
 
441
441
  /* 两列之间的接缝:新侧的行号槽再补一条左边线。只在并排时是接缝,
442
442
  堆叠时它落在段首,成了一条与任何东西都不相接的竖线 */
443
- [data-scope='diff-view'][data-part='root'][data-view='split'] [data-part='line-number'][data-side='new'] {
443
+ [data-scope='diff-view'][data-part='root'][data-view='split'] [data-part='line-number'][data-side='new']:where([data-scope='diff-view']) {
444
444
  border-inline-start: var(--xh-stroke-thin) solid var(--xh-diff-view-divider, var(--xh-border-subtle));
445
445
  }
446
446
  }
@@ -42,7 +42,7 @@
42
42
  }
43
43
 
44
44
  /* 新增的行进场,同一批按到达顺序错开;首帧就在的直接呈现(自己或根节点带 data-instant) */
45
- [data-scope='field-array'][data-part='item']:not([data-instant], [data-instant] > *) {
45
+ [data-scope='field-array'][data-part='item']:not([data-instant], [data-instant] > :where([data-scope='field-array'])) {
46
46
  animation: xh-item-in var(--xh-motion-duration-enter) var(--xh-motion-ease-enter-strong) backwards;
47
47
  animation-delay: calc(var(--xh-_stagger-index, 0) * var(--xh-motion-stagger-step));
48
48
  }
@@ -184,7 +184,7 @@
184
184
  transition: translate var(--xh-motion-duration-move) var(--xh-motion-ease-continuous);
185
185
  }
186
186
 
187
- [data-scope='file-upload'][data-part='item']:not([data-instant], [data-instant] > *) {
187
+ [data-scope='file-upload'][data-part='item']:not([data-instant], [data-instant] > :where([data-scope='file-upload'])) {
188
188
  animation: xh-item-in var(--xh-motion-duration-enter) var(--xh-motion-ease-enter-strong) backwards;
189
189
  animation-delay: calc(var(--xh-_stagger-index, 0) * var(--xh-motion-stagger-step));
190
190
  }
@@ -25,10 +25,10 @@
25
25
  [data-scope='float-button'][data-part='root'] {
26
26
  --xh-_float-button-offset: var(--xh-space-6);
27
27
  /* 展开列表里原生动作项的身量与字形尺:触发器自己走 Action Control floating 档
28
- (sm = box-md / md = box-lg / lg = box-lg + space-2,字形 md / lg / xl),
28
+ (sm = box-sm / md = box-md / lg = box-lg,字形 sm / md / lg),
29
29
  原生动作项不是 Headless 部件、配方打不到它,这两支私有槽按同一张表镜像,换档只改这里 */
30
- --xh-_float-button-size: var(--xh-control-box-lg);
31
- --xh-_float-button-glyph-size: var(--xh-glyph-size-lg);
30
+ --xh-_float-button-size: var(--xh-control-box-md);
31
+ --xh-_float-button-glyph-size: var(--xh-glyph-size-md);
32
32
  /* 作者塞进指示符槽的图标跟着尺寸档走,与皮肤画的兜底字形同一把尺 */
33
33
  --xh-icon-size: var(--xh-float-button-icon-size, var(--xh-_float-button-glyph-size));
34
34
 
@@ -166,18 +166,18 @@
166
166
 
167
167
  /* —— 尺寸:原生动作项与触发器的 floating 档逐档同表 —— */
168
168
  [data-scope='float-button'][data-part='root'][data-size='sm'] {
169
- --xh-_float-button-size: var(--xh-control-box-md);
170
- --xh-_float-button-glyph-size: var(--xh-glyph-size-md);
169
+ --xh-_float-button-size: var(--xh-control-box-sm);
170
+ --xh-_float-button-glyph-size: var(--xh-glyph-size-sm);
171
171
  }
172
172
 
173
173
  [data-scope='float-button'][data-part='root'][data-size='md'] {
174
- --xh-_float-button-size: var(--xh-control-box-lg);
175
- --xh-_float-button-glyph-size: var(--xh-glyph-size-lg);
174
+ --xh-_float-button-size: var(--xh-control-box-md);
175
+ --xh-_float-button-glyph-size: var(--xh-glyph-size-md);
176
176
  }
177
177
 
178
178
  [data-scope='float-button'][data-part='root'][data-size='lg'] {
179
- --xh-_float-button-size: calc(var(--xh-control-box-lg) + var(--xh-space-2));
180
- --xh-_float-button-glyph-size: var(--xh-glyph-size-xl);
179
+ --xh-_float-button-size: var(--xh-control-box-lg);
180
+ --xh-_float-button-glyph-size: var(--xh-glyph-size-lg);
181
181
  }
182
182
 
183
183
  /* —— 形态:给展开列表里原生动作项用的面 ——
@@ -402,10 +402,12 @@
402
402
  }
403
403
 
404
404
  /* 逐条依次冒出来,离触发器最近的那条先到。backwards 让每条在自己那份延迟里保持起始帧。
405
- 挂载时就展开着的那一段(data-instant)属于首帧,直接呈现。守卫包在 :where 里不加特异性:
406
- 后面的交错延迟、液态分离块与收起那几条要照旧压得过这一条 */
407
- [data-scope='float-button'][data-part='list']:where(:not([data-instant])) > * {
408
- animation: xh-pop-in var(--xh-motion-duration-enter) var(--xh-motion-ease-enter-strong) backwards;
405
+ 挂载时就展开着的那一段(data-instant)属于首帧,直接呈现。
406
+ 动作项是作者放进来的任意节点,规则主体没有可认的特征:冒出、缩回与交错写成 list 自己的私有槽,
407
+ 动作项只读槽。主体无特征的规则挂在 data-instant / data-state 后面,页面上任何元素翻转这两个属性
408
+ 都会让它整棵子树重算 */
409
+ [data-scope='float-button'][data-part='list']:where(:not([data-instant])) {
410
+ --xh-_float-button-item-enter: xh-pop-in var(--xh-motion-duration-enter) var(--xh-motion-ease-enter-strong) backwards;
409
411
  }
410
412
 
411
413
  /* 原生按钮直接作为动作项时,沿用触发器的视觉面(同一组公开槽、同一张形态表);XhButton 保留自己的皮肤。 */
@@ -462,42 +464,55 @@
462
464
  /* 交错的间隔:第二条起逐级往后推,第五条起统一钉在第四级——与收起、与列表动效同一个封顶,
463
465
  动作再多也不会拖出一条越来越慢的尾巴 */
464
466
  [data-scope='float-button'][data-part='list'] > *:nth-child(2) {
465
- animation-delay: var(--xh-motion-stagger-step);
467
+ --xh-_float-button-item-rank: 1;
466
468
  }
467
469
 
468
470
  [data-scope='float-button'][data-part='list'] > *:nth-child(3) {
469
- animation-delay: calc(2 * var(--xh-motion-stagger-step));
471
+ --xh-_float-button-item-rank: 2;
470
472
  }
471
473
 
472
474
  [data-scope='float-button'][data-part='list'] > *:nth-child(4) {
473
- animation-delay: calc(3 * var(--xh-motion-stagger-step));
475
+ --xh-_float-button-item-rank: 3;
474
476
  }
475
477
 
476
478
  [data-scope='float-button'][data-part='list'] > *:nth-child(n + 5) {
477
- animation-delay: calc(4 * var(--xh-motion-stagger-step));
479
+ --xh-_float-button-item-rank: 4;
478
480
  }
479
481
 
480
482
  /* 收起:逆着冒出的次序逐条缩回,离触发器最远的先走、最近的最后收,连接层等它们播完才藏起展开组。
481
483
  液态档里从触发器拆出来的那几块由液态组融回,不挂这段 */
482
- [data-scope='float-button'][data-part='list'][data-state='closed'] > :not([data-xh-liquid-goo-split]) {
484
+ [data-scope='float-button'][data-part='list'][data-state='closed'] {
485
+ --xh-_float-button-item-exit: xh-pop-out var(--xh-motion-duration-exit) var(--xh-motion-ease-exit) forwards;
486
+ --xh-_float-button-item-exiting: 1;
483
487
  pointer-events: none;
484
- animation: xh-pop-out var(--xh-motion-duration-exit) var(--xh-motion-ease-exit) forwards;
485
488
  }
486
489
 
487
- [data-scope='float-button'][data-part='list'][data-state='closed'] > :not([data-xh-liquid-goo-split]):nth-last-child(2) {
488
- animation-delay: var(--xh-motion-stagger-step);
490
+ /* 动作项只读槽:收起档压过进场档;延迟展开按正序名次、收起按倒序名次(收起标记为 1 时取后者) */
491
+ [data-scope='float-button'][data-part='list'] > :not([data-xh-liquid-goo-split]) {
492
+ animation: var(--xh-_float-button-item-exit, var(--xh-_float-button-item-enter, none));
493
+ animation-delay: calc(
494
+ var(--xh-motion-stagger-step) *
495
+ (
496
+ var(--xh-_float-button-item-rank, 0) * (1 - var(--xh-_float-button-item-exiting, 0)) +
497
+ var(--xh-_float-button-item-rank-back, 0) * var(--xh-_float-button-item-exiting, 0)
498
+ )
499
+ );
500
+ }
501
+
502
+ [data-scope='float-button'][data-part='list'] > :not([data-xh-liquid-goo-split]):nth-last-child(2) {
503
+ --xh-_float-button-item-rank-back: 1;
489
504
  }
490
505
 
491
- [data-scope='float-button'][data-part='list'][data-state='closed'] > :not([data-xh-liquid-goo-split]):nth-last-child(3) {
492
- animation-delay: calc(2 * var(--xh-motion-stagger-step));
506
+ [data-scope='float-button'][data-part='list'] > :not([data-xh-liquid-goo-split]):nth-last-child(3) {
507
+ --xh-_float-button-item-rank-back: 2;
493
508
  }
494
509
 
495
- [data-scope='float-button'][data-part='list'][data-state='closed'] > :not([data-xh-liquid-goo-split]):nth-last-child(4) {
496
- animation-delay: calc(3 * var(--xh-motion-stagger-step));
510
+ [data-scope='float-button'][data-part='list'] > :not([data-xh-liquid-goo-split]):nth-last-child(4) {
511
+ --xh-_float-button-item-rank-back: 3;
497
512
  }
498
513
 
499
- [data-scope='float-button'][data-part='list'][data-state='closed'] > :not([data-xh-liquid-goo-split]):nth-last-child(n + 5) {
500
- animation-delay: calc(4 * var(--xh-motion-stagger-step));
514
+ [data-scope='float-button'][data-part='list'] > :not([data-xh-liquid-goo-split]):nth-last-child(n + 5) {
515
+ --xh-_float-button-item-rank-back: 4;
501
516
  }
502
517
 
503
518
  /* 没写内容就由皮肤画兜底字形;作者往部件里塞了自己的图形,这几条即不命中。
package/css/form.css CHANGED
@@ -247,7 +247,7 @@
247
247
 
248
248
  /* 摘要显出时条目逐条入场,越靠后起步越晚。
249
249
  backwards 让还没轮到的条目停在首帧,不是先显出再重播 */
250
- [data-scope='form'][data-part='error-summary'][data-state='invalid'] [data-part='error-summary-item'] {
250
+ [data-scope='form'][data-part='error-summary'][data-state='invalid'] [data-part='error-summary-item']:where([data-scope='form']) {
251
251
  animation: xh-drop-in var(--xh-motion-duration-enter) var(--xh-motion-ease-enter-strong) backwards;
252
252
  }
253
253
 
@@ -256,14 +256,14 @@
256
256
  每多一节 ~ 就多要求前面多一条露面的条目,链越长的规则排得越后、赢过短链 */
257
257
  [data-scope='form'][data-part='error-summary'][data-state='invalid']
258
258
  [data-part='error-summary-item']:not([hidden])
259
- ~ [data-part='error-summary-item']:not([hidden]) {
259
+ ~ [data-part='error-summary-item']:where([data-scope='form']):not([hidden]) {
260
260
  animation-delay: var(--xh-motion-stagger-step);
261
261
  }
262
262
 
263
263
  [data-scope='form'][data-part='error-summary'][data-state='invalid']
264
264
  [data-part='error-summary-item']:not([hidden])
265
265
  ~ [data-part='error-summary-item']:not([hidden])
266
- ~ [data-part='error-summary-item']:not([hidden]) {
266
+ ~ [data-part='error-summary-item']:where([data-scope='form']):not([hidden]) {
267
267
  animation-delay: calc(var(--xh-motion-stagger-step) * 2);
268
268
  }
269
269
 
@@ -271,7 +271,7 @@
271
271
  [data-part='error-summary-item']:not([hidden])
272
272
  ~ [data-part='error-summary-item']:not([hidden])
273
273
  ~ [data-part='error-summary-item']:not([hidden])
274
- ~ [data-part='error-summary-item']:not([hidden]) {
274
+ ~ [data-part='error-summary-item']:where([data-scope='form']):not([hidden]) {
275
275
  animation-delay: calc(var(--xh-motion-stagger-step) * 3);
276
276
  }
277
277
 
@@ -280,7 +280,7 @@
280
280
  ~ [data-part='error-summary-item']:not([hidden])
281
281
  ~ [data-part='error-summary-item']:not([hidden])
282
282
  ~ [data-part='error-summary-item']:not([hidden])
283
- ~ [data-part='error-summary-item']:not([hidden]) {
283
+ ~ [data-part='error-summary-item']:where([data-scope='form']):not([hidden]) {
284
284
  animation-delay: calc(var(--xh-motion-stagger-step) * 4);
285
285
  }
286
286
 
@@ -292,7 +292,7 @@
292
292
  ~ [data-part='error-summary-item']:not([hidden])
293
293
  ~ [data-part='error-summary-item']:not([hidden])
294
294
  ~ [data-part='error-summary-item']:not([hidden])
295
- ~ [data-part='error-summary-item']:not([hidden]) {
295
+ ~ [data-part='error-summary-item']:where([data-scope='form']):not([hidden]) {
296
296
  animation-delay: calc(var(--xh-motion-stagger-step) * 5);
297
297
  }
298
298
 
@@ -162,7 +162,7 @@
162
162
 
163
163
  /* —— 直接操纵:能拖的节点给抓手,拖着时整张图是抓紧的手;放大后空白处也能拖着平移。
164
164
  触屏在节点上的拖动归图,其余地方照常滚动页面 —— */
165
- [data-scope='graph-chart'][data-part='plot'][data-draggable] [data-part='node'] {
165
+ [data-scope='graph-chart'][data-part='plot'][data-draggable] [data-part='node']:where([data-scope='graph-chart']) {
166
166
  cursor: grab;
167
167
  touch-action: none;
168
168
  }
@@ -173,7 +173,7 @@
173
173
  }
174
174
 
175
175
  [data-scope='graph-chart'][data-part='plot'][data-dragging],
176
- [data-scope='graph-chart'][data-part='plot'][data-dragging] [data-part='node'] {
176
+ [data-scope='graph-chart'][data-part='plot'][data-dragging] [data-part='node']:where([data-scope='graph-chart']) {
177
177
  cursor: grabbing;
178
178
  }
179
179
 
package/css/highlight.css CHANGED
@@ -34,7 +34,7 @@
34
34
 
35
35
  /* 语气落在根上而不是每个 mark 上:命中片段有好几个,用哪族颜色是整段的属性。
36
36
  使用者槽排在语气之前:写死了 mark 的底与字色,六族语气一并让位 */
37
- [data-scope='highlight'][data-part='root'][data-tone] [data-part='mark'] {
37
+ [data-scope='highlight'][data-part='root'][data-tone] [data-part='mark']:where([data-scope='highlight']) {
38
38
  background: var(--xh-highlight-mark-bg, var(--xh-_tone-subtle));
39
39
  color: var(--xh-highlight-mark-fg, var(--xh-_tone-fg));
40
40
  }
package/css/image.css CHANGED
@@ -44,7 +44,7 @@
44
44
 
45
45
  /* 占位层还在(正淡出)时图片不再自己淡入:它在占位层底下直接落位,由占位层的淡出揭开,
46
46
  模糊小图与图片交叉,不先透出一拍底色 */
47
- [data-scope='image'][data-part='root']:has(> [data-part='placeholder']:not([hidden])) > [data-part='image'] {
47
+ [data-scope='image'][data-part='root']:has(> [data-part='placeholder']:not([hidden])) > [data-part='image']:where([data-scope='image']) {
48
48
  animation: none;
49
49
  }
50
50
 
package/css/mention.css CHANGED
@@ -294,7 +294,7 @@
294
294
  标记读定位层那一份:候选被搬到 portal 落点,根上的只读标记够不着它们。
295
295
  排掉禁用条目是因为这条选择器权重高过上面那条,不排就会把 not-allowed 覆盖回 default */
296
296
  [data-scope='mention'][data-part='positioner'][data-readonly]
297
- [data-part='item']:not([data-disabled]) {
297
+ [data-part='item']:where([data-scope='mention']):not([data-disabled]) {
298
298
  cursor: default;
299
299
  }
300
300
 
@@ -112,7 +112,7 @@
112
112
 
113
113
  /* 新到的消息进场,同一批按到达顺序错开;首帧就在的历史消息直接呈现(自己或 list 带 data-instant)。
114
114
  进场只动 opacity 与 translate:改高度会扰动粘底补偿量到的 scrollHeight */
115
- [data-scope='message-feed'][data-part='item']:not([data-instant], [data-instant] > *) {
115
+ [data-scope='message-feed'][data-part='item']:not([data-instant], [data-instant] > :where([data-scope='message-feed'])) {
116
116
  animation: xh-item-in var(--xh-motion-duration-enter) var(--xh-motion-ease-enter-strong) backwards;
117
117
  animation-delay: calc(var(--xh-_stagger-index, 0) * var(--xh-motion-stagger-step));
118
118
  }