@xihan-ui/styles 2.1.0 → 3.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 (152) hide show
  1. package/CHANGELOG.md +1227 -0
  2. package/README.md +6 -1
  3. package/component-tokens.d.ts +505 -96
  4. package/components.tokens.json +34636 -25846
  5. package/css/accordion.css +34 -8
  6. package/css/alert.css +59 -1
  7. package/css/anchor.css +46 -8
  8. package/css/approval.css +116 -76
  9. package/css/avatar-group.css +1 -1
  10. package/css/avatar.css +13 -5
  11. package/css/back-top.css +61 -42
  12. package/css/badge.css +62 -12
  13. package/css/bar-code.css +1 -1
  14. package/css/breadcrumb.css +62 -3
  15. package/css/button-group.css +4 -4
  16. package/css/button.css +67 -19
  17. package/css/calendar-picker.css +19 -0
  18. package/css/calendar-range-picker.css +39 -2
  19. package/css/card.css +115 -1
  20. package/css/carousel.css +148 -43
  21. package/css/cartesian-chart.css +830 -0
  22. package/css/cascader.css +181 -65
  23. package/css/checkbox-group.css +59 -89
  24. package/css/checkbox.css +16 -49
  25. package/css/citation.css +470 -0
  26. package/css/clipboard.css +20 -63
  27. package/css/code-view.css +101 -6
  28. package/css/collapsible.css +34 -8
  29. package/css/color-field.css +18 -0
  30. package/css/color-picker.css +55 -58
  31. package/css/color-slider.css +22 -15
  32. package/css/color-swatch-picker.css +3 -1
  33. package/css/combobox.css +80 -33
  34. package/css/command.css +45 -43
  35. package/css/context-menu.css +39 -22
  36. package/css/date-field.css +23 -0
  37. package/css/date-picker.css +57 -22
  38. package/css/date-range-picker.css +301 -12
  39. package/css/description.css +17 -1
  40. package/css/descriptions.css +42 -0
  41. package/css/dialog.css +94 -36
  42. package/css/diff-view.css +97 -12
  43. package/css/download-trigger.css +44 -78
  44. package/css/drawer.css +160 -119
  45. package/css/editable.css +19 -0
  46. package/css/empty-state.css +7 -6
  47. package/css/field-array.css +36 -0
  48. package/css/field.css +16 -18
  49. package/css/file-upload.css +125 -135
  50. package/css/flex.css +324 -8
  51. package/css/float-button.css +165 -38
  52. package/css/floating-panel.css +53 -19
  53. package/css/form.css +23 -17
  54. package/css/funnel-chart.css +106 -0
  55. package/css/graph-chart.css +205 -0
  56. package/css/grid-list.css +235 -0
  57. package/css/grid.css +252 -1
  58. package/css/heatmap.css +119 -36
  59. package/css/hierarchy-chart.css +298 -0
  60. package/css/hover-card.css +31 -14
  61. package/css/icon.css +100 -0
  62. package/css/image-cropper.css +33 -7
  63. package/css/image-viewer.css +167 -22
  64. package/css/image.css +23 -4
  65. package/css/input-group.css +11 -13
  66. package/css/json-viewer.css +50 -2
  67. package/css/layout.css +68 -18
  68. package/css/liquid.css +106 -0
  69. package/css/list.css +1 -1
  70. package/css/listbox.css +46 -6
  71. package/css/loading-bar.css +27 -13
  72. package/css/log.css +129 -33
  73. package/css/markdown-stream.css +1 -1
  74. package/css/marquee.css +163 -7
  75. package/css/matrix-code.css +1 -1
  76. package/css/mention.css +35 -19
  77. package/css/menu.css +35 -21
  78. package/css/menubar.css +36 -20
  79. package/css/message-feed.css +172 -51
  80. package/css/navigation-menu.css +172 -11
  81. package/css/notification.css +429 -108
  82. package/css/number-field.css +22 -0
  83. package/css/page-header.css +3 -1
  84. package/css/pagination.css +126 -24
  85. package/css/password-input.css +40 -8
  86. package/css/pie-chart.css +247 -0
  87. package/css/popconfirm.css +44 -50
  88. package/css/popover.css +50 -14
  89. package/css/progress.css +308 -10
  90. package/css/prompt-input.css +36 -0
  91. package/css/question-flow.css +97 -57
  92. package/css/radar-chart.css +233 -0
  93. package/css/radio-group.css +363 -5
  94. package/css/rating.css +21 -23
  95. package/css/reasoning.css +61 -54
  96. package/css/resizable.css +6 -1
  97. package/css/sankey-chart.css +174 -0
  98. package/css/scroll-area.css +32 -0
  99. package/css/scrollbar.css +1 -1
  100. package/css/select.css +74 -55
  101. package/css/side-nav.css +173 -24
  102. package/css/signature-pad.css +16 -1
  103. package/css/skeleton.css +13 -14
  104. package/css/slider.css +35 -13
  105. package/css/sortable.css +37 -7
  106. package/css/sparkline.css +164 -0
  107. package/css/spinner.css +50 -22
  108. package/css/splitter.css +7 -1
  109. package/css/statistic.css +10 -0
  110. package/css/steps.css +248 -29
  111. package/css/switch.css +23 -48
  112. package/css/table.css +158 -118
  113. package/css/tabs.css +231 -19
  114. package/css/tag-group.css +27 -3
  115. package/css/tag.css +53 -12
  116. package/css/tags-input.css +40 -3
  117. package/css/text-field.css +19 -0
  118. package/css/time-field.css +20 -1
  119. package/css/time-picker.css +44 -15
  120. package/css/time-range-picker.css +45 -16
  121. package/css/timeline.css +1 -1
  122. package/css/toggle-group.css +4 -4
  123. package/css/toggle.css +4 -3
  124. package/css/tool-call.css +59 -51
  125. package/css/toolbar.css +101 -3
  126. package/css/tooltip.css +15 -2
  127. package/css/tour.css +42 -12
  128. package/css/transfer.css +98 -75
  129. package/css/tree-select.css +232 -53
  130. package/css/tree.css +201 -55
  131. package/css/truncate.css +55 -12
  132. package/css/typography.css +93 -0
  133. package/css/virtualizer.css +56 -0
  134. package/css/watermark.css +23 -0
  135. package/family/action-control.css +14 -5
  136. package/family/chart.css +480 -0
  137. package/family/check-mark.css +94 -0
  138. package/family/choice-card.css +97 -0
  139. package/family/collection-item.css +9 -15
  140. package/family/field-chrome.css +1 -12
  141. package/family/loading-ring.css +95 -0
  142. package/family/material.css +72 -0
  143. package/family/menu-choice.css +56 -0
  144. package/family/motion.css +207 -10
  145. package/family/tag-list.css +59 -0
  146. package/index.css +22997 -13678
  147. package/index.unlayered.css +12928 -3605
  148. package/package.json +20 -8
  149. package/css/gradient-text.css +0 -91
  150. package/css/icon-wrapper.css +0 -81
  151. package/css/segmented.css +0 -280
  152. package/css/toast.css +0 -499
package/css/clipboard.css CHANGED
@@ -5,27 +5,10 @@
5
5
 
6
6
  /* 定义 clipboard 样式。 */
7
7
 
8
+ /* 共享关键帧由 family/motion.css 提供,本皮肤 @import 它,单独引入仍成立。 */
9
+ @import '../family/motion.css';
8
10
  @import '../family/action-control.css';
9
-
10
- @layer xihan.motion {
11
- @keyframes xh-clipboard-rotate {
12
- to {
13
- rotate: 360deg;
14
- }
15
- }
16
-
17
- @keyframes xh-clipboard-loading-reveal {
18
- to {
19
- opacity: 1;
20
- }
21
- }
22
-
23
- @keyframes xh-clipboard-loading-hide {
24
- to {
25
- opacity: 0;
26
- }
27
- }
28
- }
11
+ @import '../family/loading-ring.css';
29
12
 
30
13
  @layer xihan.components {
31
14
  /* 皮肤在场的标记:开发模式下按 scope 探一次,取不到就说明这份皮肤没被引入。 */
@@ -148,14 +131,15 @@
148
131
  字改用 -webkit-text-fill-color 接回来,那是这个态下唯一还听样式表的前景通道。
149
132
  不去拉长 transition 把系统底推迟显现:那只是把它藏起来,减弱动效通道一关过渡就当场露出。
150
133
  两个选择器名分写两条:一条选择器列表里只要有一个名字不被认识,整条规则就被丢弃。
151
- 铺的底跟着这个框自己那档压低的底走,不然填过之后它会比没填时亮一块。 */
134
+ 铺的底跟着这个框自己那档压低的底走,不然填过之后它会比没填时亮一块。
135
+ 压低的底是墨色按比例透明,盖不住平台底:铺它叠在缺省面上的不透明档。 */
152
136
  [data-scope='clipboard'][data-part='input']:autofill {
153
- box-shadow: inset 0 0 0 100vmax var(--xh-clipboard-input-autofill-bg, var(--xh-bg-subtle));
137
+ box-shadow: inset 0 0 0 100vmax var(--xh-clipboard-input-autofill-bg, var(--xh-bg-subtle-opaque));
154
138
  -webkit-text-fill-color: var(--xh-clipboard-input-autofill-fg, var(--xh-fg-default));
155
139
  }
156
140
 
157
141
  [data-scope='clipboard'][data-part='input']:-webkit-autofill {
158
- box-shadow: inset 0 0 0 100vmax var(--xh-clipboard-input-autofill-bg, var(--xh-bg-subtle));
142
+ box-shadow: inset 0 0 0 100vmax var(--xh-clipboard-input-autofill-bg, var(--xh-bg-subtle-opaque));
159
143
  -webkit-text-fill-color: var(--xh-clipboard-input-autofill-fg, var(--xh-fg-default));
160
144
  }
161
145
 
@@ -203,9 +187,10 @@
203
187
  --xh-action-border-focus-visible: var(--xh-clipboard-copy-trigger-border, var(--xh-border-control));
204
188
  }
205
189
 
190
+ /* 与输入框共用的那条边只画一次:墨色描边半透明,两条叠在一起会加深。输入框的末端边就是这条共边 */
206
191
  [data-scope='clipboard'][data-part='control'] > [data-scope='clipboard'][data-part='copy-trigger']:not(:first-child) {
207
192
  position: relative;
208
- margin-inline-start: calc(-1 * var(--xh-stroke-thin));
193
+ border-inline-start-width: 0;
209
194
  border-start-start-radius: 0;
210
195
  border-end-start-radius: 0;
211
196
  border-start-end-radius: var(
@@ -230,50 +215,22 @@
230
215
  display: none;
231
216
  }
232
217
 
233
- /* 快速写入不显示瞬时圆环;超过一个 micro 周期后才平滑换成加载状态。 */
234
- [data-scope='clipboard'][data-part='root'][data-state='copying']
235
- [data-scope='clipboard'][data-part='copy-trigger'][aria-busy='true'] {
236
- cursor: progress;
237
- }
238
-
239
- [data-scope='clipboard'][data-part='copy-trigger'][aria-busy='true']::before {
240
- content: '';
241
- position: absolute;
242
- inset: 0;
243
- inline-size: 1em;
244
- block-size: 1em;
245
- margin: auto;
246
- border: var(--xh-stroke-thin) solid transparent;
247
- border-block-start-color: currentColor;
248
- /* 正圆的加载环:正方盒取 circle */
249
- border-radius: var(--xh-shape-circle);
250
- opacity: 0;
251
- animation:
252
- xh-clipboard-rotate var(--xh-clipboard-loading-duration, var(--xh-spin-duration)) var(--xh-motion-ease-loop) infinite,
253
- xh-clipboard-loading-reveal var(--xh-motion-duration-micro) var(--xh-motion-ease-enter) var(--xh-motion-duration-micro) forwards;
218
+ /* 写入在途:环由加载环配方压在钮正中(连接层投影 data-xh-loading-ring="overlay"),直径取钮的图标档,
219
+ 起始边取钮的真实前景、转速认使用者槽。进入在途等一个 micro 才起淡,快速写入什么都不闪;
220
+ 钮里原有的文字与字形随前景淡到透明留位,同样等这一个 micro,退出在途不等、按 micro 淡回 */
221
+ [data-scope='clipboard'][data-part='copy-trigger'] {
222
+ --xh-_loading-ring-fg: var(--xh-clipboard-copy-trigger-fg, var(--xh-_action-variant-fg-loading));
223
+ --xh-_loading-ring-duration: var(--xh-clipboard-loading-duration, var(--xh-motion-loop-spin));
254
224
  }
255
225
 
256
- [data-scope='clipboard'][data-part='copy-trigger'][aria-busy='true']
257
- > [data-scope='clipboard'][data-part='indicator']:not([data-copied]) {
258
- animation: xh-clipboard-loading-hide var(--xh-motion-duration-micro) var(--xh-motion-ease-enter)
259
- var(--xh-motion-duration-micro) forwards;
226
+ [data-scope='clipboard'][data-part='copy-trigger']::before {
227
+ --xh-icon-size: var(--xh-_action-profile-glyph-size);
260
228
  }
261
229
 
262
- @media (prefers-reduced-motion: reduce) {
263
- [data-scope='clipboard'][data-part='copy-trigger'][aria-busy='true']::before {
264
- animation: none;
265
- }
266
-
267
- [data-scope='clipboard'][data-part='copy-trigger'][aria-busy='true']
268
- > [data-scope='clipboard'][data-part='indicator']:not([data-copied]) {
269
- animation: none;
270
- }
271
- }
230
+ [data-scope='clipboard'][data-part='copy-trigger'][data-loading] {
231
+ --xh-action-fg-loading: transparent;
272
232
 
273
- :where([data-motion='reduce']) [data-scope='clipboard'][data-part='copy-trigger'][aria-busy='true']::before,
274
- :where([data-motion='reduce']) [data-scope='clipboard'][data-part='copy-trigger'][aria-busy='true']
275
- > [data-scope='clipboard'][data-part='indicator']:not([data-copied]) {
276
- animation: none;
233
+ transition-delay: var(--xh-motion-duration-micro);
277
234
  }
278
235
 
279
236
  /* 复制成功只换前景与内容,轮廓和尺寸保持稳定;各态前景经桥接槽换,悬停与按下不退回平时的字色 */
package/css/code-view.css CHANGED
@@ -16,11 +16,11 @@
16
16
 
17
17
  /* 一张静态内容面:--xh-border-default 描边 + surface 底 + 无影(边界只由描边承担),
18
18
  overflow: hidden 让内部 <pre> 的滚动内容沿圆角收边;不设 display,排布由作者决定。
19
- color 给整段未着色的代码定基线,字号在这里消费一次,缺省即 sm 档。 */
19
+ color 给整段未着色的代码定基线,字号在这里消费一次,缺省即 md 档(与面内按钮同档)。 */
20
20
  [data-scope='code-view'][data-part='root'] {
21
21
  /* 尺寸缺省档:不写 data-size 时的取值。三档都只写这个私有槽,
22
22
  公开槽留在读处当首选,作者在祖先上设的覆盖才赢得过档位声明 */
23
- --xh-_code-view-font-size: var(--xh-control-font-sm);
23
+ --xh-_code-view-font-size: var(--xh-control-font-md);
24
24
 
25
25
  overflow: hidden;
26
26
  border: var(--xh-stroke-thin) solid var(--xh-code-view-border, var(--xh-border-default));
@@ -111,7 +111,7 @@
111
111
  padding-inline-end: var(--xh-code-view-px, var(--xh-space-3));
112
112
  /* 标出来的那几行换的是底色与那条内阴影色条,两样一起过渡才是同一个动作 */
113
113
  transition:
114
- background var(--xh-motion-duration-micro) var(--xh-motion-ease-enter),
114
+ background-color var(--xh-motion-duration-micro) var(--xh-motion-ease-enter),
115
115
  box-shadow var(--xh-motion-duration-micro) var(--xh-motion-ease-enter);
116
116
  }
117
117
 
@@ -119,9 +119,10 @@
119
119
  display: none;
120
120
  }
121
121
 
122
+ /* 高亮行是强调不是选中:中性淡底 + 行首强调条,不用品牌淡底(品牌淡底只表达选中 / 当前) */
122
123
  [data-scope='code-view'][data-part='line'][data-highlighted] {
123
- background: var(--xh-code-view-highlight-bg, var(--xh-bg-brand-subtle));
124
- box-shadow: inset var(--xh-code-view-highlight-bar, var(--xh-stroke-thick)) 0 0 0 var(--xh-code-view-highlight-fg, var(--xh-bg-brand));
124
+ background: var(--xh-code-view-highlight-bg, var(--xh-bg-subtle));
125
+ box-shadow: inset var(--xh-code-view-highlight-bar, var(--xh-stroke-thick)) 0 0 0 var(--xh-code-view-highlight-fg, var(--xh-border-strong));
125
126
  }
126
127
 
127
128
  /* 行号是画上去的不是写上去的:复制代码不带它,读屏也不逐行念数字。
@@ -133,7 +134,7 @@
133
134
  flex: 0 0 auto;
134
135
  padding-inline-start: var(--xh-code-view-px, var(--xh-space-3));
135
136
  padding-inline-end: var(--xh-code-view-gutter-gap, var(--xh-space-1));
136
- border-inline-end: var(--xh-stroke-thin) solid var(--xh-code-view-gutter-border, var(--xh-border-default));
137
+ border-inline-end: var(--xh-stroke-thin) solid var(--xh-code-view-gutter-border, var(--xh-border-subtle));
137
138
  color: var(--xh-code-view-number-fg, var(--xh-fg-subtle));
138
139
  font-size: var(--xh-code-view-number-font-size, var(--xh-text-caption-size));
139
140
  inline-size: var(--xh-_code-view-gutter);
@@ -226,6 +227,75 @@
226
227
  display: none;
227
228
  }
228
229
 
230
+ /* 按块折叠:每行正文都让出一列(一行高的正方格),块头的折叠钮定位在这一列里;
231
+ 没有钮的行也让,缩进才对得齐 */
232
+ [data-scope='code-view'][data-part='root'][data-block-folding] {
233
+ --xh-_code-view-fold-col: var(--xh-code-view-fold-col, var(--xh-code-view-line-height, var(--xh-text-code-leading)));
234
+ }
235
+
236
+ [data-scope='code-view'][data-part='root'][data-block-folding] [data-part='line-content'] {
237
+ position: relative;
238
+ padding-inline-start: var(--xh-_code-view-fold-col);
239
+ }
240
+
241
+ [data-scope='code-view'][data-part='root'][data-block-folding]:not([data-line-numbers]) [data-part='line-content'] {
242
+ padding-inline-start: calc(var(--xh-code-view-px, var(--xh-space-3)) + var(--xh-_code-view-fold-col));
243
+ }
244
+
245
+ /* 行首折叠钮是 disclosure trigger:接 Action Control icon 档、ghost 形态,边长压到一行高,
246
+ 按下只换面不缩放;静息取次级字色,不和正文抢 */
247
+ [data-scope='code-view'][data-part='line-fold-trigger'] {
248
+ --xh-action-visual-size: var(--xh-_code-view-fold-col);
249
+ --xh-action-min-inline-size: var(--xh-_code-view-fold-col);
250
+ --xh-action-radius: var(--xh-code-view-line-fold-trigger-radius, var(--xh-shape-control));
251
+ --xh-action-fg-rest: var(--xh-code-view-line-fold-trigger-fg, var(--xh-fg-subtle));
252
+ --xh-action-scale-pressed: none;
253
+ --xh-icon-size: var(--xh-code-view-icon-size, var(--xh-glyph-size-sm));
254
+
255
+ position: absolute;
256
+ inset-block-start: 0;
257
+ inset-inline-start: 0;
258
+ block-size: var(--xh-_code-view-fold-col);
259
+ }
260
+
261
+ [data-scope='code-view'][data-part='root'][data-block-folding]:not([data-line-numbers]) [data-part='line-fold-trigger'] {
262
+ inset-inline-start: var(--xh-code-view-px, var(--xh-space-3));
263
+ }
264
+
265
+ [data-scope='code-view'][data-part='line-fold-trigger'][hidden] {
266
+ display: none;
267
+ }
268
+
269
+ /* 展开时朝下;收起时转向行尾那一侧(RTL 跟着换向) */
270
+ [data-scope='code-view'][data-part='line-fold-trigger']::before {
271
+ content: '';
272
+ display: block;
273
+ inline-size: var(--xh-icon-size, var(--xh-glyph-size-sm));
274
+ block-size: var(--xh-icon-size, var(--xh-glyph-size-sm));
275
+ background-color: currentColor;
276
+ -webkit-mask: var(--xh-glyph-mark-chevron-down) center / contain no-repeat;
277
+ mask: var(--xh-glyph-mark-chevron-down) center / contain no-repeat;
278
+ transition: rotate var(--xh-motion-duration-expand) var(--xh-motion-ease-enter-strong);
279
+ }
280
+
281
+ [data-scope='code-view'][data-part='line-fold-trigger'][data-state='closed']::before {
282
+ rotate: calc(-90deg * var(--xh-direction-sign));
283
+ transition-duration: var(--xh-motion-duration-collapse);
284
+ }
285
+
286
+ /* 折叠着的块头:正文后面一枚省略号,示意下面收起了几行;画上去的,复制不带它 */
287
+ [data-scope='code-view'][data-part='line-content'][data-folded]::after {
288
+ content: '';
289
+ display: inline-block;
290
+ inline-size: var(--xh-icon-size, var(--xh-glyph-size-sm));
291
+ block-size: var(--xh-icon-size, var(--xh-glyph-size-sm));
292
+ margin-inline-start: var(--xh-code-view-folded-gap, var(--xh-space-1));
293
+ vertical-align: var(--xh-glyph-baseline-shift);
294
+ background-color: var(--xh-code-view-folded-fg, var(--xh-fg-subtle));
295
+ -webkit-mask: var(--xh-glyph-mark-ellipsis) center / contain no-repeat;
296
+ mask: var(--xh-glyph-mark-ellipsis) center / contain no-repeat;
297
+ }
298
+
229
299
  /* 尺寸档写私有槽、由 root 基础规则消费一次:缺省与阶梯是同一个口子,
230
300
  作者设的 --xh-code-view-font-size 排在读处首选,不会被这三条盖掉。
231
301
  行号槽宽以 ch 计,随字号一起走 */
@@ -276,4 +346,29 @@
276
346
  outline-offset: calc(-1 * var(--xh-code-view-highlight-bar, var(--xh-stroke-thick)));
277
347
  }
278
348
  }
349
+
350
+ @media (forced-colors: active) {
351
+ /* 兜底字形是 mask 挖出来的一块底色,这一档里底色被系统换成 Canvas,字形跟着消失。
352
+ 字形退出强制换色、直接写系统色(不能取 currentColor:退出强制换色的伪元素读到的是被系统换掉之前的作者色):
353
+ 按钮面上取 ButtonText,悬停与按下时家族把按钮涂成 Highlight、字形换 HighlightText;
354
+ 落在 Canvas 面上的取 CanvasText;
355
+ 禁用取 GrayText */
356
+ [data-scope='code-view'][data-part='line-fold-trigger']::before {
357
+ forced-color-adjust: none;
358
+ background-color: ButtonText;
359
+ }
360
+
361
+ [data-scope='code-view'][data-part='line-content'][data-folded]::after {
362
+ forced-color-adjust: none;
363
+ background-color: CanvasText;
364
+ }
365
+
366
+ [data-scope='code-view'][data-part='line-fold-trigger']:not([data-disabled]):not([data-loading]):is(:hover, :active, [data-pressed])::before {
367
+ background-color: HighlightText;
368
+ }
369
+
370
+ [data-scope='code-view'][data-part='line-fold-trigger'][data-disabled]::before {
371
+ background-color: GrayText;
372
+ }
373
+ }
279
374
  }
@@ -101,8 +101,12 @@
101
101
  justify-content: center;
102
102
  color: var(--xh-collapsible-indicator-fg, var(--xh-fg-muted));
103
103
  line-height: var(--xh-leading-none);
104
- /* 指示器与正文同档转向:正文 enter 档展开,箭头也用同一段时长翻过去 */
105
- transition: rotate var(--xh-motion-duration-enter) var(--xh-motion-ease-enter-strong);
104
+ }
105
+
106
+ /* 指示器与正文同档转向:收起时取 collapse 档,展开时(下面的打开态)取 expand 档。
107
+ 首帧就在的朝向直接呈现(data-instant),第一次开合起才转 */
108
+ [data-scope='collapsible'][data-part='indicator']:not([data-instant]) {
109
+ transition: rotate var(--xh-motion-duration-collapse) var(--xh-motion-ease-enter-strong);
106
110
  }
107
111
 
108
112
  /* 没写内容就由皮肤画;作者往部件里塞了自己的图形,这条规则即不命中 */
@@ -121,6 +125,10 @@
121
125
  rotate: 180deg;
122
126
  }
123
127
 
128
+ [data-scope='collapsible'][data-part='indicator'][data-state='open']:not([data-instant]) {
129
+ transition: rotate var(--xh-motion-duration-expand) var(--xh-motion-ease-enter-strong);
130
+ }
131
+
124
132
  /* 这里刻意没有 [data-part='content'][hidden] { display: none }:补了动画一帧都播不出来。
125
133
  收起由适配器在退场结束后写内联 display 落成,退场窗口内靠 connect 发的 inert 挡住焦点 */
126
134
  [data-scope='collapsible'][data-part='content'] {
@@ -138,14 +146,32 @@
138
146
  line-height: var(--xh-leading-normal);
139
147
  }
140
148
 
141
- /* 展开那一档才提前备好行高这条通道:属性随 data-state 一起消失,收起后不长期占着 */
142
- [data-scope='collapsible'][data-part='content'][data-state='open'] {
143
- will-change: grid-template-rows;
144
- animation: xh-disclosure-expand var(--xh-motion-duration-enter) var(--xh-motion-ease-enter-strong);
149
+ /* 展开与收起只在开合时播:首帧就在的展开 / 收起直接呈现(data-instant) */
150
+ [data-scope='collapsible'][data-part='content'][data-state='open']:not([data-instant]) {
151
+ animation: xh-disclosure-expand var(--xh-motion-duration-expand) var(--xh-motion-ease-enter-strong);
145
152
  }
146
153
 
147
- [data-scope='collapsible'][data-part='content'][data-state='closed'] {
148
- animation: xh-disclosure-collapse var(--xh-motion-duration-exit) var(--xh-motion-ease-exit) forwards;
154
+ [data-scope='collapsible'][data-part='content'][data-state='closed']:not([data-instant]) {
155
+ animation: xh-disclosure-collapse var(--xh-motion-duration-collapse) var(--xh-motion-ease-exit) forwards;
156
+ }
157
+
158
+ @media (forced-colors: active) {
159
+ /* 兜底字形是 mask 挖出来的一块底色,这一档里底色被系统换成 Canvas,字形跟着消失。
160
+ 字形退出强制换色、直接写系统色(不能取 currentColor:退出强制换色的伪元素读到的是被系统换掉之前的作者色):
161
+ 按钮面上取 ButtonText,悬停与按下时家族把按钮涂成 Highlight、字形换 HighlightText;
162
+ 禁用取 GrayText */
163
+ [data-scope='collapsible'][data-part='indicator']:empty::before {
164
+ forced-color-adjust: none;
165
+ background-color: ButtonText;
166
+ }
167
+
168
+ [data-scope='collapsible'][data-part='trigger']:not([data-disabled]):not([data-loading]):is(:hover, :active, [data-pressed]) [data-scope='collapsible'][data-part='indicator']:empty::before {
169
+ background-color: HighlightText;
170
+ }
171
+
172
+ [data-scope='collapsible'][data-part='trigger'][data-disabled] [data-scope='collapsible'][data-part='indicator']:empty::before {
173
+ background-color: GrayText;
174
+ }
149
175
  }
150
176
  }
151
177
 
@@ -155,4 +155,22 @@
155
155
  mask: var(--xh-glyph-mark-close) center / contain no-repeat;
156
156
  }
157
157
 
158
+ @media (forced-colors: active) {
159
+ /* 兜底字形是 mask 挖出来的一块底色,这一档里底色被系统换成 Canvas,字形跟着消失。
160
+ 字形退出强制换色、直接写系统色(不能取 currentColor:退出强制换色的伪元素读到的是被系统换掉之前的作者色):
161
+ 按钮面上取 ButtonText,悬停与按下时家族把按钮涂成 Highlight、字形换 HighlightText;
162
+ 禁用取 GrayText */
163
+ [data-scope='color-field'][data-part='clear-trigger']:empty::before {
164
+ forced-color-adjust: none;
165
+ background-color: ButtonText;
166
+ }
167
+
168
+ [data-scope='color-field'][data-part='clear-trigger']:not([data-disabled]):not([data-loading]):is(:hover, :active, [data-pressed]):empty::before {
169
+ background-color: HighlightText;
170
+ }
171
+
172
+ [data-scope='color-field'][data-part='clear-trigger'][data-disabled]:empty::before {
173
+ background-color: GrayText;
174
+ }
175
+ }
158
176
  }
@@ -5,10 +5,10 @@
5
5
 
6
6
  /* 定义 color picker 样式。 */
7
7
 
8
+ @import '../family/field-chrome.css';
8
9
  @import '../family/swatch.css';
9
10
  @import '../family/motion.css';
10
11
 
11
-
12
12
  @layer xihan.components {
13
13
  /* 皮肤在场的标记:开发模式下按 scope 探一次,取不到就说明这份皮肤没被引入。 */
14
14
  [data-scope='color-picker'] {
@@ -23,11 +23,10 @@
23
23
 
24
24
  /* 标签一行、盒一行的两行堆叠 */
25
25
  [data-scope='color-picker'][data-part='root'] {
26
- /* 盒的度量与标签字号走私有槽中转,与同族的下拉选择一处对一处 */
26
+ /* 盒的度量走私有槽中转,与同族的下拉选择一处对一处 */
27
27
  --xh-_color-picker-h: var(--xh-control-h-md);
28
28
  --xh-_color-picker-px: var(--xh-control-px-md);
29
29
  --xh-_color-picker-gap: var(--xh-control-gap-md);
30
- --xh-_color-picker-label-font-size: var(--xh-control-font-md);
31
30
 
32
31
  /* 聚焦环恒用固定环色 */
33
32
  --xh-_color-picker-ring: var(--xh-ring-focus);
@@ -50,70 +49,47 @@
50
49
  --xh-_color-picker-h: var(--xh-control-h-sm);
51
50
  --xh-_color-picker-px: var(--xh-control-px-sm);
52
51
  --xh-_color-picker-gap: var(--xh-control-gap-sm);
53
- --xh-_color-picker-label-font-size: var(--xh-control-font-sm);
54
52
  }
55
53
 
56
54
  [data-scope='color-picker']:is([data-part='root'], [data-part='positioner'])[data-size='lg'] {
57
55
  --xh-_color-picker-h: var(--xh-control-h-lg);
58
56
  --xh-_color-picker-px: var(--xh-control-px-lg);
59
57
  --xh-_color-picker-gap: var(--xh-control-gap-lg);
60
- --xh-_color-picker-label-font-size: var(--xh-control-font-lg);
61
58
  }
62
59
 
63
60
  [data-scope='color-picker'][data-part='label'] {
64
61
  color: var(--xh-color-picker-label-fg, var(--xh-fg-default));
65
- font-size: var(--xh-color-picker-label-font-size, var(--xh-_color-picker-label-font-size));
62
+ /* 字段标签不随档:与同族字段同一档标签字号 */
63
+ font-size: var(--xh-color-picker-label-font-size, var(--xh-text-label-size));
66
64
  font-weight: var(--xh-color-picker-label-font-weight, var(--xh-text-label-weight));
67
65
  }
68
66
 
69
- /* 盒:描边、底色、控件高度与行内内衬都落在这一层,
70
- 另加一档静态落影把它从页面里抬起一层 */
67
+ /* 盒:接字段外壳家族(data-xh-field-chrome),描边、底色、控件高度、行内内衬、悬停与聚焦面
68
+ 都由家族按 data-variant 与状态画,与同族的下拉选择一处对一处;这里只把组件自己的覆盖槽桥接进去。
69
+ 静息无影、悬停取家族的 45% 淡底、聚焦边一律 --xh-border-control-focus(不随语气) */
71
70
  [data-scope='color-picker'][data-part='control'] {
72
- display: inline-flex;
73
- align-items: center;
74
- gap: var(--xh-color-picker-control-gap, var(--xh-_color-picker-gap));
75
- min-inline-size: min(var(--xh-color-picker-control-min-w, var(--xh-control-min-w)), 100%);
76
- block-size: var(--xh-color-picker-control-h, var(--xh-_color-picker-h));
77
- padding-inline: var(--xh-color-picker-control-px, var(--xh-_color-picker-px));
78
- border: var(--xh-stroke-thin) solid var(--xh-color-picker-control-border, var(--xh-border-control));
79
- border-radius: var(--xh-color-picker-control-radius, var(--xh-shape-control));
80
- background: var(--xh-color-picker-control-bg, transparent);
81
- box-shadow: var(--xh-color-picker-control-shadow, var(--xh-elevation-raised));
82
- color: var(--xh-color-picker-control-fg, var(--xh-fg-default));
83
- cursor: pointer;
84
- transition:
85
- background var(--xh-motion-duration-micro) var(--xh-motion-ease-enter),
86
- border-color var(--xh-motion-duration-micro) var(--xh-motion-ease-enter);
71
+ --xh-field-control-height: var(--xh-color-picker-control-h, var(--xh-_color-picker-h));
72
+ --xh-field-control-padding-inline: var(--xh-color-picker-control-px, var(--xh-_color-picker-px));
73
+ --xh-field-control-gap: var(--xh-color-picker-control-gap, var(--xh-_color-picker-gap));
74
+ --xh-field-control-min-inline-size: var(--xh-color-picker-control-min-w, var(--xh-control-min-w));
75
+ --xh-field-control-radius: var(--xh-color-picker-control-radius, var(--xh-shape-control));
76
+ --xh-field-bg-rest: var(--xh-color-picker-control-bg, var(--xh-_field-variant-bg-rest));
77
+ --xh-field-bg-hover: var(--xh-color-picker-control-bg-hover, var(--xh-_field-variant-bg-hover));
78
+ --xh-field-bg-read-only: var(--xh-color-picker-control-bg-readonly, var(--xh-_field-variant-bg-read-only));
79
+ --xh-field-bg-disabled: var(--xh-color-picker-control-bg-disabled, var(--xh-_field-variant-bg-disabled));
80
+ --xh-field-fg-rest: var(--xh-color-picker-control-fg, var(--xh-fg-default));
81
+ --xh-field-border-rest: var(--xh-color-picker-control-border, var(--xh-_field-variant-border-rest));
82
+ --xh-field-border-hover: var(--xh-color-picker-control-border-hover, var(--xh-_field-variant-border-hover));
83
+ --xh-field-border-focus: var(--xh-color-picker-control-border-focus, var(--xh-_field-variant-border-focus));
84
+ --xh-field-ring-focus: var(--xh-_color-picker-ring);
85
+ --xh-field-shadow-rest: var(--xh-color-picker-control-shadow, none);
86
+ --xh-field-cursor-rest: pointer;
87
87
  }
88
88
 
89
89
  [data-scope='color-picker'][data-part='control'][hidden] {
90
90
  display: none;
91
91
  }
92
92
 
93
- /* 悬停换描边的同时换填充:这个盒里大半面积是那块色样,只挪一圈 1px 的描边读不出来。
94
- 只读档摘掉:它正拿压低一档的底色说「改不动」,被悬停的填充盖掉那条信息就没了 */
95
- [data-scope='color-picker'][data-part='control']:hover:not([data-disabled], [data-readonly]) {
96
- border-color: var(--xh-color-picker-control-border-hover, var(--xh-border-control-hover));
97
- background: var(--xh-color-picker-control-bg-hover, var(--xh-bg-subtle));
98
- }
99
-
100
- /* Tab 停靠点是盒里的 trigger,环画在盒上 */
101
- [data-scope='color-picker'][data-part='control']:focus-within:not([data-disabled]) {
102
- border-color: var(--xh-color-picker-control-border-focus, var(--xh-_tone, var(--xh-border-control-focus)));
103
- outline: var(--xh-ring-width) solid var(--xh-_color-picker-ring);
104
- outline-offset: var(--xh-ring-offset);
105
- }
106
-
107
- [data-scope='color-picker'][data-part='control'][data-disabled] {
108
- background: var(--xh-color-picker-control-bg-disabled, var(--xh-bg-subtle));
109
- color: var(--xh-fg-disabled);
110
- }
111
-
112
- /* 只读仍可聚焦、浮层照开,只是改不动:不置灰,只把底色压下去 */
113
- [data-scope='color-picker'][data-part='control'][data-readonly] {
114
- background: var(--xh-color-picker-control-bg-readonly, var(--xh-bg-subtle));
115
- }
116
-
117
93
  /* 盒内那颗可聚焦的按钮:不画描边不铺底也不自带高度,只占满剩余宽度、排布色块与值文本 */
118
94
  [data-scope='color-picker'][data-part='trigger'] {
119
95
  display: inline-flex;
@@ -229,13 +205,14 @@
229
205
  pointer-events: auto;
230
206
  }
231
207
 
232
- [data-scope='color-picker'][data-part='content'][data-state='open'] {
208
+ /* 挂载时就开着的那一段(data-instant)属于首帧,直接呈现;常驻形态的取色面一直在,没有进退场 */
209
+ [data-scope='color-picker'][data-part='content'][data-state='open']:not([data-instant], [data-inline]) {
233
210
  animation: xh-overlay-slide-in var(--xh-motion-duration-enter) var(--xh-motion-ease-enter-strong);
234
211
  }
235
212
 
236
213
  /* 退场:收起那一帧 hidden 由退场闸门押后,这里才播得出来。forwards 把末态钉住,
237
214
  免得动画结束到真收起之间闪一下原样 */
238
- [data-scope='color-picker'][data-part='content'][data-state='closed'] {
215
+ [data-scope='color-picker'][data-part='content'][data-state='closed']:not([data-inline]) {
239
216
  animation: xh-overlay-slide-out var(--xh-motion-duration-exit) var(--xh-motion-ease-exit) forwards;
240
217
  }
241
218
 
@@ -244,6 +221,22 @@
244
221
  outline: none;
245
222
  }
246
223
 
224
+ /* 常驻形态:根不再取字段缺省宽,跟着取色面走 */
225
+ [data-scope='color-picker'][data-part='root'][data-inline] {
226
+ inline-size: auto;
227
+ min-inline-size: 0;
228
+ }
229
+
230
+ /* 常驻形态的取色面是页面里的静态内容面(solid):surface 圆角、border-default 描边、实体底、不落影。
231
+ 没有定位层给出可用宽高,不限高也不自己滚;它一直在,没有进退场 */
232
+ [data-scope='color-picker'][data-part='content'][data-inline] {
233
+ max-inline-size: 100%;
234
+ max-block-size: none;
235
+ overflow-y: visible;
236
+ border-radius: var(--xh-color-picker-content-radius, var(--xh-shape-surface));
237
+ box-shadow: var(--xh-color-picker-content-shadow, none);
238
+ }
239
+
247
240
  /* 二维取色区。底色是当前色相(连接层内联给),两层渐变盖在上面:
248
241
  横轴由白到透明 = 饱和度,纵轴由透明到黑 = 明度。
249
242
  两层都收在一个 ::before 里:它是盒树里的第一个子节点,作者写的拇指排在它后面,
@@ -301,7 +294,7 @@
301
294
  background: transparent;
302
295
  box-shadow: var(--xh-color-picker-thumb-shadow, var(--xh-elevation-raised));
303
296
  cursor: grab;
304
- transition: scale var(--xh-motion-duration-micro) var(--xh-motion-ease-enter-strong);
297
+ transition: scale var(--xh-motion-duration-nudge) var(--xh-motion-ease-enter-strong);
305
298
  }
306
299
 
307
300
  /* 取色区的纵轴也由连接层给(inset-block-start),回拉同样按 block-start 那侧 */
@@ -364,7 +357,8 @@
364
357
  }
365
358
 
366
359
  [data-scope='color-picker'][data-part='channel-input']:focus-visible {
367
- border-color: var(--xh-color-picker-input-border-focus, var(--xh-_tone, var(--xh-border-control-focus)));
360
+ /* 焦点边一律 --xh-border-control-focus,不随语气 */
361
+ border-color: var(--xh-color-picker-input-border-focus, var(--xh-border-control-focus));
368
362
  outline: var(--xh-ring-width) solid var(--xh-ring-focus);
369
363
  outline-offset: var(--xh-ring-offset);
370
364
  }
@@ -401,13 +395,14 @@
401
395
  cursor: pointer;
402
396
  user-select: none;
403
397
  transition:
404
- background var(--xh-motion-duration-micro) var(--xh-motion-ease-enter),
398
+ background-color var(--xh-motion-duration-micro) var(--xh-motion-ease-enter),
405
399
  border-color var(--xh-motion-duration-micro) var(--xh-motion-ease-enter),
406
400
  scale var(--xh-motion-duration-release) var(--xh-motion-ease-release);
407
401
  }
408
402
 
409
403
  [data-scope='color-picker'][data-part='eye-dropper-trigger']:hover:not(:disabled) {
410
- background: var(--xh-color-picker-action-bg-hover, var(--xh-bg-subtle-hover));
404
+ /* 坐在浮层白底上:白底承载阶梯 hover 100 → pressed 200 */
405
+ background: var(--xh-color-picker-action-bg-hover, var(--xh-bg-subtle));
411
406
  color: var(--xh-color-picker-action-fg-hover, var(--xh-fg-default));
412
407
  }
413
408
 
@@ -415,7 +410,7 @@
415
410
  松手那一刻浮层多半已经被系统的取色镜头盖住,按下的回执只有这一瞬看得见。
416
411
  指针 :active 与 Headless 投影的 data-pressed(Space / Enter 与触屏按住)看见同一副按压面 */
417
412
  [data-scope='color-picker'][data-part='eye-dropper-trigger']:not(:disabled):is(:active, [data-pressed]) {
418
- background: var(--xh-color-picker-action-bg-active, var(--xh-bg-subtle-active));
413
+ background: var(--xh-color-picker-action-bg-active, var(--xh-bg-subtle-hover));
419
414
  scale: var(--xh-motion-scale-press);
420
415
  transition-duration: var(--xh-motion-duration-press);
421
416
  transition-timing-function: var(--xh-motion-ease-press);
@@ -435,8 +430,9 @@
435
430
  /* 预设色板的挂载点,同时充当色板的根节点:color-swatch-picker 那份皮的 root 规则落在
436
431
  [data-scope='color-swatch-picker'][data-part='root'] 上,而这里没有那个节点,所以根上挂的那几个私有槽
437
432
  (格子边长、间距、徽标尺寸、语气色、图标尺)与排布得在这儿照抄一遍;格子的皮仍归色板那一份。
438
- 浮层里的色板走小号格子:与滑块的拇指、数值框一个量级,整块面板才不会被色板撑开 */
439
- [data-scope='color-picker'][data-part='swatch-picker'] {
433
+ 浮层里的色板走小号格子:与滑块的拇指、数值框一个量级,整块面板才不会被色板撑开。
434
+ 最近使用色是同一台色块选择器,挂载点同一套 */
435
+ [data-scope='color-picker']:is([data-part='swatch-picker'], [data-part='recent-swatch-picker']) {
440
436
  --xh-_color-swatch-picker-cell: var(--xh-color-picker-swatch-cell, var(--xh-control-h-sm));
441
437
  --xh-_color-swatch-picker-gap: var(--xh-color-picker-swatch-gap, var(--xh-control-gap-sm));
442
438
  --xh-_color-swatch-picker-indicator: var(--xh-control-indicator-sm);
@@ -450,7 +446,7 @@
450
446
  gap: var(--xh-color-picker-swatch-picker-gap, var(--xh-_color-swatch-picker-gap));
451
447
  }
452
448
 
453
- [data-scope='color-picker'][data-part='swatch-picker'][data-disabled] {
449
+ [data-scope='color-picker']:is([data-part='swatch-picker'], [data-part='recent-swatch-picker'])[data-disabled] {
454
450
  cursor: not-allowed;
455
451
  }
456
452
 
@@ -464,7 +460,8 @@
464
460
  [data-scope='color-picker'][data-part='hue-slider'][hidden],
465
461
  [data-scope='color-picker'][data-part='alpha-slider'][hidden],
466
462
  [data-scope='color-picker'][data-part='eye-dropper-trigger'][hidden],
467
- [data-scope='color-picker'][data-part='swatch-picker'][hidden] {
463
+ [data-scope='color-picker'][data-part='swatch-picker'][hidden],
464
+ [data-scope='color-picker'][data-part='recent-swatch-picker'][hidden] {
468
465
  display: none;
469
466
  }
470
467