@xihan-ui/styles 1.0.0 → 2.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 (171) hide show
  1. package/CHANGELOG.md +5146 -6
  2. package/README.md +22 -2
  3. package/component-tokens.d.ts +4212 -0
  4. package/component-tokens.js +2 -0
  5. package/components.tokens.json +80116 -0
  6. package/css/accordion.css +131 -75
  7. package/css/affix.css +16 -1
  8. package/css/alert.css +114 -67
  9. package/css/anchor.css +99 -27
  10. package/css/approval.css +461 -0
  11. package/css/avatar-group.css +14 -6
  12. package/css/avatar.css +33 -9
  13. package/css/back-top.css +103 -48
  14. package/css/badge.css +42 -14
  15. package/css/bar-code.css +62 -0
  16. package/css/breadcrumb.css +40 -21
  17. package/css/button-group.css +146 -24
  18. package/css/button.css +116 -99
  19. package/css/calendar-picker.css +448 -0
  20. package/css/calendar-range-picker.css +517 -0
  21. package/css/card.css +54 -77
  22. package/css/carousel.css +412 -68
  23. package/css/cascader.css +429 -246
  24. package/css/checkbox-group.css +225 -77
  25. package/css/checkbox.css +174 -37
  26. package/css/clipboard.css +266 -47
  27. package/css/code-view.css +279 -0
  28. package/css/collapsible.css +108 -63
  29. package/css/color-field.css +158 -0
  30. package/css/color-picker.css +172 -184
  31. package/css/color-slider.css +274 -0
  32. package/css/color-swatch-picker.css +243 -0
  33. package/css/color-swatch.css +35 -0
  34. package/css/combobox.css +267 -273
  35. package/css/command.css +399 -0
  36. package/css/context-menu.css +183 -108
  37. package/css/date-field.css +94 -121
  38. package/css/date-picker.css +486 -249
  39. package/css/date-range-picker.css +559 -0
  40. package/css/description.css +51 -0
  41. package/css/descriptions.css +133 -87
  42. package/css/dialog.css +247 -68
  43. package/css/diff-view.css +428 -0
  44. package/css/download-trigger.css +155 -46
  45. package/css/drawer.css +194 -111
  46. package/css/editable.css +172 -152
  47. package/css/empty-state.css +80 -11
  48. package/css/field-array.css +190 -0
  49. package/css/field.css +84 -31
  50. package/css/fieldset.css +51 -18
  51. package/css/file-upload.css +134 -36
  52. package/css/flex.css +20 -1
  53. package/css/float-button.css +238 -57
  54. package/css/floating-panel.css +173 -92
  55. package/css/focus.css +46 -0
  56. package/css/forced-colors.css +93 -0
  57. package/css/form.css +254 -77
  58. package/css/gradient-text.css +34 -10
  59. package/css/grid.css +516 -5
  60. package/css/heatmap.css +87 -29
  61. package/css/highlight.css +20 -5
  62. package/css/hover-card.css +97 -47
  63. package/css/icon-wrapper.css +15 -3
  64. package/css/icon.css +74 -8
  65. package/css/image-cropper.css +143 -29
  66. package/css/image-viewer.css +150 -89
  67. package/css/image.css +30 -1
  68. package/css/infinite-scroll.css +51 -1
  69. package/css/input-group.css +277 -0
  70. package/css/json-viewer.css +102 -45
  71. package/css/kbd.css +72 -0
  72. package/css/label.css +78 -0
  73. package/css/layers.css +5 -0
  74. package/css/layout.css +175 -31
  75. package/css/list.css +24 -3
  76. package/css/listbox.css +208 -67
  77. package/css/loading-bar.css +52 -3
  78. package/css/log.css +144 -9
  79. package/css/markdown-stream.css +149 -0
  80. package/css/marquee.css +27 -1
  81. package/css/masonry.css +7 -0
  82. package/css/matrix-code.css +67 -0
  83. package/css/mention.css +234 -152
  84. package/css/menu.css +180 -83
  85. package/css/menubar.css +204 -136
  86. package/css/message-feed.css +197 -0
  87. package/css/navigation-menu.css +144 -90
  88. package/css/notification.css +178 -100
  89. package/css/number-animation.css +7 -0
  90. package/css/number-field.css +120 -277
  91. package/css/overlay-arrow.css +12 -7
  92. package/css/page-header.css +99 -14
  93. package/css/pagination.css +175 -135
  94. package/css/password-input.css +222 -219
  95. package/css/pin-input.css +101 -67
  96. package/css/pointer.css +36 -0
  97. package/css/popconfirm.css +185 -94
  98. package/css/popover.css +121 -77
  99. package/css/progress.css +60 -12
  100. package/css/prompt-input.css +224 -0
  101. package/css/question-flow.css +513 -0
  102. package/css/radio-group.css +147 -30
  103. package/css/rating.css +193 -43
  104. package/css/reasoning.css +336 -0
  105. package/css/reset.css +84 -6
  106. package/css/resizable.css +237 -0
  107. package/css/scroll-area.css +68 -7
  108. package/css/scrollbar.css +47 -13
  109. package/css/segmented.css +94 -29
  110. package/css/select.css +288 -274
  111. package/css/separator.css +101 -1
  112. package/css/side-nav.css +133 -75
  113. package/css/signature-pad.css +74 -54
  114. package/css/skeleton.css +84 -11
  115. package/css/slider.css +132 -39
  116. package/css/sortable.css +198 -0
  117. package/css/spinner.css +126 -12
  118. package/css/splitter.css +29 -8
  119. package/css/statistic.css +55 -0
  120. package/css/steps.css +206 -72
  121. package/css/switch.css +268 -36
  122. package/css/table.css +695 -118
  123. package/css/tabs.css +604 -42
  124. package/css/tag-group.css +219 -0
  125. package/css/tag.css +118 -28
  126. package/css/tags-input.css +156 -274
  127. package/css/text-field.css +101 -249
  128. package/css/time-field.css +100 -128
  129. package/css/time-picker.css +323 -252
  130. package/css/time-range-picker.css +719 -0
  131. package/css/timeline.css +202 -68
  132. package/css/timer.css +56 -52
  133. package/css/timestamp.css +34 -0
  134. package/css/toast.css +373 -144
  135. package/css/toggle-group.css +309 -76
  136. package/css/toggle.css +116 -85
  137. package/css/tone.css +47 -0
  138. package/css/tool-call.css +421 -0
  139. package/css/toolbar.css +181 -33
  140. package/css/tooltip.css +107 -36
  141. package/css/tour.css +183 -152
  142. package/css/transfer.css +351 -138
  143. package/css/tree-select.css +323 -216
  144. package/css/tree.css +294 -62
  145. package/css/truncate.css +65 -0
  146. package/css/typography.css +228 -5
  147. package/css/undefined.css +10 -1
  148. package/css/virtualizer.css +9 -10
  149. package/css/visually-hidden.css +7 -0
  150. package/css/watermark.css +7 -0
  151. package/family/action-control.css +487 -0
  152. package/family/collection-item.css +721 -0
  153. package/family/field-chrome.css +298 -0
  154. package/family/motion.css +166 -0
  155. package/family/swatch.css +59 -0
  156. package/index.css +41705 -126
  157. package/index.unlayered.css +33692 -17339
  158. package/package.json +51 -17
  159. package/css/calendar.css +0 -367
  160. package/css/code-block.css +0 -91
  161. package/css/composer.css +0 -134
  162. package/css/countdown.css +0 -26
  163. package/css/dynamic-input.css +0 -220
  164. package/css/ellipsis.css +0 -52
  165. package/css/hotkeys.css +0 -90
  166. package/css/popselect.css +0 -391
  167. package/css/qr-code.css +0 -55
  168. package/css/result.css +0 -119
  169. package/css/space.css +0 -117
  170. package/css/thread.css +0 -120
  171. package/css/time.css +0 -25
@@ -1,27 +1,13 @@
1
- @layer xihan.motion {
2
- @keyframes xh-pop-in {
3
- from {
4
- opacity: 0;
5
- scale: var(--xh-motion-scale-enter);
6
- }
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
+ */
7
5
 
8
- to {
9
- opacity: 1;
10
- scale: 1;
11
- }
12
- }
13
- @keyframes xh-pop-out {
14
- from {
15
- opacity: 1;
16
- scale: 1;
17
- }
6
+ /* 定义 color picker 样式。 */
7
+
8
+ @import '../family/swatch.css';
9
+ @import '../family/motion.css';
18
10
 
19
- to {
20
- opacity: 0;
21
- scale: var(--xh-motion-scale-enter);
22
- }
23
- }
24
- }
25
11
 
26
12
  @layer xihan.components {
27
13
  /* 皮肤在场的标记:开发模式下按 scope 探一次,取不到就说明这份皮肤没被引入。 */
@@ -29,10 +15,11 @@
29
15
  --xh-color-picker-skin: 1;
30
16
  }
31
17
 
32
- /* 定位分工:取色区拇指的两条轴(inset-inline-start / inset-block-start)、
33
- 通道拇指的主轴(inset-inline-start)、浮层坐标、取色区底色、透明度轨道的渐变,
18
+ /* 定位分工:取色区拇指的两条轴(inset-inline-start / inset-block-start)、浮层坐标、取色区底色,
34
19
  全都由连接层每帧写进内联样式。这份皮肤一个都不碰:内联优先级高于样式表,
35
- 写了不但是死声明,还会跟连接层抢位置。皮肤只管尺寸、颜色、圆角与状态表现。 */
20
+ 写了不但是死声明,还会跟连接层抢位置。皮肤只管尺寸、颜色、圆角与状态表现。
21
+ 色相 / 透明度两条滑块与预设色板是内嵌组件,各自的皮归 color-slider.css 与 color-swatch-picker.css;
22
+ 这里只画三个挂载点——它们同时充当内嵌组件的根节点,根上那几条规则要在这儿照抄一遍。 */
36
23
 
37
24
  /* 标签一行、盒一行的两行堆叠 */
38
25
  [data-scope='color-picker'][data-part='root'] {
@@ -48,6 +35,12 @@
48
35
  display: inline-flex;
49
36
  flex-direction: column;
50
37
  gap: var(--xh-color-picker-gap, var(--xh-space-1));
38
+
39
+ /* 不传尺寸时一律这么宽,宽度不随内容走;父容器给不出这么宽时整件跟着收,地板同步让步,不越出父容器。
40
+ 地板不高过缺省宽:使用者把缺省宽钉到底线以下时不必再放开底线 */
41
+ inline-size: var(--xh-color-picker-control-w, var(--xh-control-w));
42
+ min-inline-size: min(var(--xh-color-picker-control-w, var(--xh-control-w)), var(--xh-color-picker-control-min-w, var(--xh-control-min-w)), 100%);
43
+ max-inline-size: 100%;
51
44
  }
52
45
 
53
46
  /* —— 尺寸 —— */
@@ -71,35 +64,37 @@
71
64
  color: var(--xh-color-picker-label-fg, var(--xh-fg-default));
72
65
  font-size: var(--xh-color-picker-label-font-size, var(--xh-_color-picker-label-font-size));
73
66
  font-weight: var(--xh-color-picker-label-font-weight, var(--xh-text-label-weight));
74
- line-height: var(--xh-leading-none);
75
67
  }
76
68
 
77
- [data-scope='color-picker'][data-part='label'][data-disabled] {
78
- color: var(--xh-fg-subtle);
79
- }
80
-
81
- /* 盒:描边、底色、控件高度与行内内衬都落在这一层 */
69
+ /* 盒:描边、底色、控件高度与行内内衬都落在这一层,
70
+ 另加一档静态落影把它从页面里抬起一层 */
82
71
  [data-scope='color-picker'][data-part='control'] {
83
72
  display: inline-flex;
84
73
  align-items: center;
85
74
  gap: var(--xh-color-picker-control-gap, var(--xh-_color-picker-gap));
86
- min-inline-size: var(--xh-color-picker-control-min-w, var(--xh-control-min-w));
75
+ min-inline-size: min(var(--xh-color-picker-control-min-w, var(--xh-control-min-w)), 100%);
87
76
  block-size: var(--xh-color-picker-control-h, var(--xh-_color-picker-h));
88
77
  padding-inline: var(--xh-color-picker-control-px, var(--xh-_color-picker-px));
89
78
  border: var(--xh-stroke-thin) solid var(--xh-color-picker-control-border, var(--xh-border-control));
90
79
  border-radius: var(--xh-color-picker-control-radius, var(--xh-shape-control));
91
- background: var(--xh-color-picker-control-bg, var(--xh-bg-canvas));
80
+ background: var(--xh-color-picker-control-bg, transparent);
81
+ box-shadow: var(--xh-color-picker-control-shadow, var(--xh-elevation-raised));
92
82
  color: var(--xh-color-picker-control-fg, var(--xh-fg-default));
93
83
  cursor: pointer;
94
- transition: border-color var(--xh-motion-duration-micro) var(--xh-motion-ease-enter);
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);
95
87
  }
96
88
 
97
89
  [data-scope='color-picker'][data-part='control'][hidden] {
98
90
  display: none;
99
91
  }
100
92
 
101
- [data-scope='color-picker'][data-part='control']:hover:not([data-disabled]) {
93
+ /* 悬停换描边的同时换填充:这个盒里大半面积是那块色样,只挪一圈 1px 的描边读不出来。
94
+ 只读档摘掉:它正拿压低一档的底色说「改不动」,被悬停的填充盖掉那条信息就没了 */
95
+ [data-scope='color-picker'][data-part='control']:hover:not([data-disabled], [data-readonly]) {
102
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));
103
98
  }
104
99
 
105
100
  /* Tab 停靠点是盒里的 trigger,环画在盒上 */
@@ -112,7 +107,6 @@
112
107
  [data-scope='color-picker'][data-part='control'][data-disabled] {
113
108
  background: var(--xh-color-picker-control-bg-disabled, var(--xh-bg-subtle));
114
109
  color: var(--xh-fg-disabled);
115
- cursor: not-allowed;
116
110
  }
117
111
 
118
112
  /* 只读仍可聚焦、浮层照开,只是改不动:不置灰,只把底色压下去 */
@@ -142,22 +136,17 @@
142
136
  display: none;
143
137
  }
144
138
 
145
- /* 单体控件用原生 disabled(预设色板那些格子也是原生按钮,同一条规矩) */
139
+ /* 单体控件用原生 disabled */
146
140
  [data-scope='color-picker'][data-part='trigger']:disabled {
147
141
  color: var(--xh-fg-disabled);
148
- cursor: not-allowed;
149
142
  }
150
143
 
151
- /* 当前颜色的色块。背景由连接层内联给(含透明度),这里只给形状与描边。
152
- 刻意不铺棋盘格底:连接层写的是 background 简写,会盖掉这里任何 background-image,
153
- 半透明色因此直接与页面底色混合——小色块上这么显示是准确的。 */
144
+ /* 当前颜色的色块:面、棋盘格、描边与尺寸档全由色块面家族画(带 data-xh-swatch),
145
+ 半透明色铺在棋盘格上;组件层只把自己的公开槽映射到家族合同 */
154
146
  [data-scope='color-picker'][data-part='swatch'] {
155
- display: inline-block;
156
- flex: none;
157
- inline-size: var(--xh-color-picker-swatch-size, 18px);
158
- block-size: var(--xh-color-picker-swatch-size, 18px);
159
- border: var(--xh-stroke-thin) solid var(--xh-color-picker-swatch-border, var(--xh-border-default));
160
- border-radius: var(--xh-color-picker-swatch-radius, var(--xh-shape-inset));
147
+ --xh-swatch-size: var(--xh-color-picker-swatch-size, var(--xh-_swatch-size));
148
+ --xh-swatch-radius: var(--xh-color-picker-swatch-radius, var(--xh-shape-inset));
149
+ --xh-swatch-border: var(--xh-color-picker-swatch-border, var(--xh-border-default));
161
150
  }
162
151
 
163
152
  /* 值串可能很长,必须能截断;框宽由盒定,这里得允许自己被压缩 */
@@ -177,46 +166,79 @@
177
166
  /* 落定那一侧的可用高度,由定位引擎经内联自定义属性写进来,内容层继承它限高;
178
167
  引擎没算(尚未落位 / 无引擎 / 贴边归零)时不额外限高 */
179
168
  --xh-_color-picker-available-h: 100vh;
169
+ /* 落定那一侧的可用宽度,同样由定位引擎经内联自定义属性写进来,内容层据此夹住行内轴;
170
+ 引擎没算(尚未落位 / 无引擎 / 贴边归零)时退到视口宽 */
171
+ --xh-_color-picker-available-w: 100vw;
172
+ /* 每个面板按自身落位方向进入,截断祖先浮层方向的继承。 */
173
+ --xh-_overlay-enter-up: 0;
174
+ --xh-_overlay-enter-down: 0;
175
+ --xh-_overlay-enter-left: 0;
176
+ --xh-_overlay-enter-right: 0;
180
177
 
181
178
  /* 面板的自绘条浮在内容之上:轨道不上底色,实色轨道会在面板右缘糊出一条竖灰带 */
182
179
  --xh-scrollbar-track-bg: transparent;
183
180
 
184
181
  position: fixed;
185
- z-index: var(--xh-color-picker-layer, var(--xh-layer-popover));
182
+ z-index: var(--xh-color-picker-layer, var(--xh-_layer, var(--xh-layer-popover)));
186
183
  /* 空壳不吃指针,交互只发生在 content 上 */
187
184
  pointer-events: none;
188
185
  }
189
186
 
187
+ [data-scope='color-picker'][data-part='positioner'][data-placement^='top'] {
188
+ --xh-_overlay-enter-down: 1;
189
+ }
190
+
191
+ [data-scope='color-picker'][data-part='positioner'][data-placement^='bottom'] {
192
+ --xh-_overlay-enter-up: 1;
193
+ }
194
+
195
+ [data-scope='color-picker'][data-part='positioner'][data-placement^='left'] {
196
+ --xh-_overlay-enter-right: 1;
197
+ }
198
+
199
+ [data-scope='color-picker'][data-part='positioner'][data-placement^='right'] {
200
+ --xh-_overlay-enter-left: 1;
201
+ }
202
+
190
203
  /* 锚点被滚出可视区:整个浮层随之收起 */
191
204
  [data-scope='color-picker'][data-part='positioner'][data-hidden] {
192
205
  visibility: hidden;
193
206
  }
194
207
 
195
208
  [data-scope='color-picker'][data-part='content'] {
209
+ position: relative;
196
210
  display: flex;
197
211
  flex-direction: column;
198
212
  gap: var(--xh-color-picker-content-gap, var(--xh-space-3));
199
213
  inline-size: var(--xh-color-picker-content-w, var(--xh-overlay-min-w));
214
+ /* 定宽的面板也要夹一道:窄视口下伸出去,右半边的取色区就点不到了 */
215
+ max-inline-size: var(--xh-_color-picker-available-w);
200
216
  padding-block: var(--xh-color-picker-content-py, var(--xh-space-3));
201
217
  padding-inline: var(--xh-color-picker-content-px, var(--xh-space-3));
202
218
  max-block-size: min(var(--xh-color-picker-max-h, var(--xh-viewport-h-md)), var(--xh-_color-picker-available-h));
203
219
  overflow-y: auto;
220
+ /* 浮层滚动面:滚到头不把页面一起带走(§6.6) */
221
+ overscroll-behavior: contain;
222
+ /* 面域 + 滑杆 + 通道输入的表单型多列面板,走 floating 材质(§8.4)——实体底 + --xh-border-default 描边 +
223
+ --xh-elevation-floating 落影,不透景、不画顶部边界光 */
204
224
  border: var(--xh-stroke-thin) solid var(--xh-color-picker-content-border, var(--xh-border-default));
205
- border-radius: var(--xh-color-picker-content-radius, var(--xh-shape-surface));
225
+ border-radius: var(--xh-color-picker-content-radius, var(--xh-shape-overlay));
206
226
  background: var(--xh-color-picker-content-bg, var(--xh-bg-surface));
207
227
  color: var(--xh-color-picker-content-fg, var(--xh-fg-default));
208
228
  box-shadow: var(--xh-color-picker-content-shadow, var(--xh-elevation-floating));
209
229
  pointer-events: auto;
210
230
  }
211
231
 
232
+ /* 在场那一档才提前备好合成层:属性随 data-state 一起消失,收起后不长期占着 */
212
233
  [data-scope='color-picker'][data-part='content'][data-state='open'] {
213
- animation: xh-pop-in var(--xh-motion-duration-enter) var(--xh-motion-ease-enter);
234
+ will-change: opacity, translate;
235
+ animation: xh-overlay-slide-in var(--xh-motion-duration-enter) var(--xh-motion-ease-enter-strong);
214
236
  }
215
237
 
216
238
  /* 退场:收起那一帧 hidden 由退场闸门押后,这里才播得出来。forwards 把末态钉住,
217
239
  免得动画结束到真收起之间闪一下原样 */
218
240
  [data-scope='color-picker'][data-part='content'][data-state='closed'] {
219
- animation: xh-pop-out var(--xh-motion-duration-exit) var(--xh-motion-ease-exit) forwards;
241
+ animation: xh-overlay-slide-out var(--xh-motion-duration-exit) var(--xh-motion-ease-exit) forwards;
220
242
  }
221
243
 
222
244
  /* 浮层本身只是个容器(tabindex=-1 是焦点域的兜底落点),落焦时不画环 */
@@ -229,16 +251,16 @@
229
251
  两层都收在一个 ::before 里:它是盒树里的第一个子节点,作者写的拇指排在它后面,
230
252
  绘制顺序上就压在渐变之上;拆成 ::before + ::after 的话 ::after 是最后一个子节点,
231
253
  会反过来盖住拇指。 */
232
- [data-scope='color-picker'][data-part='area'] {
254
+ [data-scope='color-picker'][data-part='saturation-area'] {
233
255
  position: relative;
234
256
  display: block;
235
- block-size: var(--xh-color-picker-area-h, 9rem);
236
- border-radius: var(--xh-color-picker-area-radius, var(--xh-shape-control));
257
+ block-size: var(--xh-color-picker-saturation-area-h, 9rem);
258
+ border-radius: var(--xh-color-picker-saturation-area-radius, var(--xh-shape-control));
237
259
  cursor: crosshair;
238
260
  }
239
261
 
240
262
  /* white / black 是 HSV 色彩空间自带的两个端点,不是主题色,因此不走令牌 */
241
- [data-scope='color-picker'][data-part='area']::before {
263
+ [data-scope='color-picker'][data-part='saturation-area']::before {
242
264
  position: absolute;
243
265
  border-radius: inherit;
244
266
  background-image:
@@ -250,39 +272,38 @@
250
272
 
251
273
  /* 渐变方向没有逻辑关键字可用,只能靠 :dir() 分流:
252
274
  拇指走的是 inset-inline-start,rtl 下自动换向,饱和度那层渐变不跟着换就反了 */
253
- [data-scope='color-picker'][data-part='area']:dir(rtl)::before {
275
+ [data-scope='color-picker'][data-part='saturation-area']:dir(rtl)::before {
254
276
  background-image:
255
277
  linear-gradient(to bottom, transparent, black),
256
278
  linear-gradient(to left, white, transparent);
257
279
  }
258
280
 
259
- [data-scope='color-picker'][data-part='area'][data-readonly] {
281
+ [data-scope='color-picker'][data-part='saturation-area'][data-readonly]:not([data-disabled]) {
260
282
  cursor: default;
261
283
  }
262
284
 
263
- [data-scope='color-picker'][data-part='area'][data-disabled] {
264
- cursor: not-allowed;
285
+ [data-scope='color-picker'][data-part='saturation-area'][data-disabled] {
265
286
  opacity: var(--xh-state-disabled-opacity);
266
287
  }
267
288
 
268
- /* 两处拇指同一副长相:镂空的小圆环,中心正好落在值所在的比例点上。
289
+ /* 取色区的拇指:镂空的小圆环,中心正好落在值所在的比例点上。
269
290
  内联样式把 inset-* 定在比例上,那是拇指的起始边不是圆心,用负的逻辑外边距回拉半径。
270
291
  刻意不用 translate(-50%):rtl 下 inset-inline-start 映射到 right,
271
292
  位移量是物理方向的,会把拇指推向错误的一侧;负的逻辑外边距自己就跟着换向。
272
- box-sizing 必须显式写:描边要吃进直径里,否则实际盒子比变量宽两条边,回拉就对不上圆心。 */
273
- [data-scope='color-picker'][data-part='area-thumb'],
274
- [data-scope='color-picker'][data-part='channel-slider-thumb'] {
293
+ box-sizing 必须显式写:描边要吃进直径里,否则实际盒子比变量宽两条边,回拉就对不上圆心。
294
+ 两条滑块的拇指归 color-slider 那份皮,与这一颗同一副长相。 */
295
+ [data-scope='color-picker'][data-part='area-thumb'] {
275
296
  position: absolute;
276
297
  box-sizing: border-box;
277
298
  inline-size: var(--xh-color-picker-thumb-size, 14px);
278
299
  block-size: var(--xh-color-picker-thumb-size, 14px);
279
300
  margin-inline-start: calc(var(--xh-color-picker-thumb-size, 14px) / -2);
280
301
  border: var(--xh-stroke-thick) solid var(--xh-color-picker-thumb-border, var(--xh-color-neutral-0));
281
- border-radius: var(--xh-color-picker-thumb-radius, var(--xh-shape-pill));
302
+ border-radius: var(--xh-color-picker-thumb-radius, var(--xh-shape-circle));
282
303
  background: transparent;
283
304
  box-shadow: var(--xh-color-picker-thumb-shadow, var(--xh-elevation-raised));
284
305
  cursor: grab;
285
- transition: scale var(--xh-motion-duration-micro) var(--xh-motion-ease-enter);
306
+ transition: scale var(--xh-motion-duration-micro) var(--xh-motion-ease-enter-strong);
286
307
  }
287
308
 
288
309
  /* 取色区的纵轴也由连接层给(inset-block-start),回拉同样按 block-start 那侧 */
@@ -290,101 +311,43 @@
290
311
  margin-block-start: calc(var(--xh-color-picker-thumb-size, 14px) / -2);
291
312
  }
292
313
 
293
- /* 通道拇指的纵轴归样式表:连接层只写主轴,交叉轴不写就得在这里钉死居中 */
294
- [data-scope='color-picker'][data-part='channel-slider-thumb'] {
295
- inset-block-start: 50%;
296
- margin-block-start: calc(var(--xh-color-picker-thumb-size, 14px) / -2);
297
- }
298
-
299
- [data-scope='color-picker'][data-part='area-thumb']:focus-visible,
300
- [data-scope='color-picker'][data-part='channel-slider-thumb']:focus-visible {
301
- outline: var(--xh-ring-width) solid var(--xh-ring-focus);
302
- outline-offset: var(--xh-ring-offset);
303
- }
304
-
305
- /* 只有手真正拖着的那一处带 data-dragging:放大与光标不会三处一起变。
314
+ /* 只有手真正拖着时带 data-dragging:放大与光标不会几处一起变。
306
315
  放大用 scale 而不是改尺寸:变换绕自身中心发生,圆心不动,负外边距的算式不用跟着改 */
307
- [data-scope='color-picker'][data-part='area-thumb'][data-dragging],
308
- [data-scope='color-picker'][data-part='channel-slider-thumb'][data-dragging] {
316
+ [data-scope='color-picker'][data-part='area-thumb'][data-dragging] {
309
317
  scale: var(--xh-color-picker-thumb-scale-dragging, var(--xh-motion-scale-drag));
310
318
  cursor: grabbing;
311
319
  }
312
320
 
313
- [data-scope='color-picker'][data-part='area-thumb'][data-readonly],
314
- [data-scope='color-picker'][data-part='channel-slider-thumb'][data-readonly] {
321
+ [data-scope='color-picker'][data-part='area-thumb'][data-readonly]:not([data-disabled]) {
315
322
  cursor: default;
316
323
  }
317
324
 
318
- [data-scope='color-picker'][data-part='area-thumb'][data-disabled],
319
- [data-scope='color-picker'][data-part='channel-slider-thumb'][data-disabled] {
320
- cursor: not-allowed;
321
- }
325
+ /* 两条颜色滑块的挂载点,同时充当各自的根节点:color-slider 那份皮的 root 规则落在
326
+ [data-scope='color-slider'][data-part='root'] 上,而这里没有那个节点,所以根上挂的两个私有槽
327
+ (拇指直径、轨道厚度,control / track / thumb 都读它们)与排布得在这儿照抄一遍;
328
+ 滑块内部的皮仍归 color-slider 那一份。尺寸档跟着浮层上的 data-size 走,不必再各写一遍 */
329
+ [data-scope='color-picker'][data-part='hue-slider'],
330
+ [data-scope='color-picker'][data-part='alpha-slider'] {
331
+ --xh-_thumb-size: var(--xh-color-picker-slider-thumb-size, var(--xh-track-thumb-size));
332
+ --xh-_track-thickness: var(--xh-color-picker-slider-track-thickness, var(--xh-space-3));
322
333
 
323
- /* 拇指以整条滑杆为定位上下文(拇指浮出轨道,挂在轨道上会被轨道的盒子束住)。
324
- 厚度取拇指直径:轨道只有几个像素,滑杆若按轨道高,浮出来的拇指会顶到上下相邻的元素。 */
325
- [data-scope='color-picker'][data-part='channel-slider'] {
326
- position: relative;
327
334
  display: flex;
328
- align-items: center;
329
- block-size: var(--xh-color-picker-thumb-size, 14px);
330
- border-radius: var(--xh-color-picker-track-radius, var(--xh-shape-pill));
331
- cursor: pointer;
332
- }
333
-
334
- /* 透明度那条的棋盘格铺在滑杆上、垫在轨道底下:
335
- 轨道自己的渐变从全透明走到实色,透明那半正好把棋盘格露出来。
336
- 铺在轨道上是做不到的——那儿的 background-image 归连接层。 */
337
- [data-scope='color-picker'][data-part='channel-slider'][data-channel='alpha'] {
338
- background-image:
339
- linear-gradient(45deg, var(--xh-color-picker-checker, var(--xh-color-neutral-300)) 25%, transparent 25%),
340
- linear-gradient(-45deg, var(--xh-color-picker-checker, var(--xh-color-neutral-300)) 25%, transparent 25%),
341
- linear-gradient(45deg, transparent 75%, var(--xh-color-picker-checker, var(--xh-color-neutral-300)) 75%),
342
- linear-gradient(-45deg, transparent 75%, var(--xh-color-picker-checker, var(--xh-color-neutral-300)) 75%);
343
- background-position: 0 0, 0 4px, 4px -4px, -4px 0;
344
- background-size: 8px 8px;
335
+ flex-direction: column;
345
336
  }
346
337
 
347
- [data-scope='color-picker'][data-part='channel-slider'][data-disabled] {
348
- cursor: not-allowed;
349
- opacity: var(--xh-state-disabled-opacity);
338
+ /* 标题与轨道之间的间隙 */
339
+ [data-scope='color-picker'][data-part='hue-slider'] {
340
+ gap: var(--xh-color-picker-hue-slider-gap, var(--xh-stack-gap-md));
350
341
  }
351
342
 
352
- [data-scope='color-picker'][data-part='channel-slider'][data-readonly] {
353
- cursor: default;
343
+ [data-scope='color-picker'][data-part='alpha-slider'] {
344
+ gap: var(--xh-color-picker-alpha-slider-gap, var(--xh-stack-gap-md));
354
345
  }
355
346
 
356
- [data-scope='color-picker'][data-part='channel-slider-track'] {
357
- inline-size: 100%;
358
- block-size: var(--xh-color-picker-track-thickness, 8px);
359
- border-radius: var(--xh-color-picker-track-radius, var(--xh-shape-pill));
360
- }
361
-
362
- /* 色相轨道是一条固定的彩虹:色相的六个锚点,与颜色主题无关,因此不走令牌。
363
- 透明度轨道的渐变归连接层(它要用到当前颜色),这里不碰。 */
364
- [data-scope='color-picker'][data-part='channel-slider-track'][data-channel='hue'] {
365
- background-image: linear-gradient(
366
- to right,
367
- hsl(0deg 100% 50%),
368
- hsl(60deg 100% 50%),
369
- hsl(120deg 100% 50%),
370
- hsl(180deg 100% 50%),
371
- hsl(240deg 100% 50%),
372
- hsl(300deg 100% 50%),
373
- hsl(360deg 100% 50%)
374
- );
375
- }
376
-
377
- [data-scope='color-picker'][data-part='channel-slider-track'][data-channel='hue']:dir(rtl) {
378
- background-image: linear-gradient(
379
- to left,
380
- hsl(0deg 100% 50%),
381
- hsl(60deg 100% 50%),
382
- hsl(120deg 100% 50%),
383
- hsl(180deg 100% 50%),
384
- hsl(240deg 100% 50%),
385
- hsl(300deg 100% 50%),
386
- hsl(360deg 100% 50%)
387
- );
347
+ /* 禁用的整体压暗只做一次,落在最外层;alpha 关掉时透明度那条整条压暗 */
348
+ [data-scope='color-picker'][data-part='hue-slider'][data-disabled],
349
+ [data-scope='color-picker'][data-part='alpha-slider'][data-disabled] {
350
+ opacity: var(--xh-state-disabled-opacity);
388
351
  }
389
352
 
390
353
  [data-scope='color-picker'][data-part='channel-input'] {
@@ -394,7 +357,7 @@
394
357
  padding-inline: var(--xh-color-picker-input-px, var(--xh-control-px-sm));
395
358
  border: var(--xh-stroke-thin) solid var(--xh-color-picker-input-border, var(--xh-border-control));
396
359
  border-radius: var(--xh-color-picker-input-radius, var(--xh-shape-control));
397
- background: var(--xh-color-picker-input-bg, var(--xh-bg-canvas));
360
+ background: var(--xh-color-picker-input-bg, transparent);
398
361
  color: inherit;
399
362
  /* 表单控件不继承页面字体,只给字号会让输入框用 UA 默认字族,与周围文本对不上 */
400
363
  font-family: inherit;
@@ -405,8 +368,7 @@
405
368
  [data-scope='color-picker'][data-part='channel-input']:focus-visible {
406
369
  border-color: var(--xh-color-picker-input-border-focus, var(--xh-_tone, var(--xh-border-control-focus)));
407
370
  outline: var(--xh-ring-width) solid var(--xh-ring-focus);
408
- /* 往内收一道发丝:输入框贴着面板边排,环画在外沿会压到相邻通道 */
409
- outline-offset: calc(-1 * var(--xh-stroke-thin));
371
+ outline-offset: var(--xh-ring-offset);
410
372
  }
411
373
 
412
374
  /* 打到一半的串:框里留着草稿,但值没动——描边提示"这串还没被收下" */
@@ -421,7 +383,6 @@
421
383
  [data-scope='color-picker'][data-part='channel-input']:disabled {
422
384
  background: var(--xh-color-picker-input-bg-disabled, var(--xh-bg-subtle));
423
385
  color: var(--xh-fg-disabled);
424
- cursor: not-allowed;
425
386
  }
426
387
 
427
388
  [data-scope='color-picker'][data-part='eye-dropper-trigger'] {
@@ -441,6 +402,10 @@
441
402
  line-height: var(--xh-leading-none);
442
403
  cursor: pointer;
443
404
  user-select: none;
405
+ transition:
406
+ background var(--xh-motion-duration-micro) var(--xh-motion-ease-enter),
407
+ border-color var(--xh-motion-duration-micro) var(--xh-motion-ease-enter),
408
+ scale var(--xh-motion-duration-release) var(--xh-motion-ease-release);
444
409
  }
445
410
 
446
411
  [data-scope='color-picker'][data-part='eye-dropper-trigger']:hover:not(:disabled) {
@@ -448,9 +413,14 @@
448
413
  color: var(--xh-color-picker-action-fg-hover, var(--xh-fg-default));
449
414
  }
450
415
 
451
- [data-scope='color-picker'][data-part='eye-dropper-trigger']:focus-visible {
452
- outline: var(--xh-ring-width) solid var(--xh-ring-focus);
453
- outline-offset: var(--xh-ring-offset);
416
+ /* 按下去要有回应:换底之外再压一档。取色是一次「点下去就交给系统」的操作,
417
+ 松手那一刻浮层多半已经被系统的取色镜头盖住,按下的回执只有这一瞬看得见。
418
+ 指针 :active 与 Headless 投影的 data-pressed(Space / Enter 与触屏按住)看见同一副按压面 */
419
+ [data-scope='color-picker'][data-part='eye-dropper-trigger']:not(:disabled):is(:active, [data-pressed]) {
420
+ background: var(--xh-color-picker-action-bg-active, var(--xh-bg-subtle-active));
421
+ scale: var(--xh-motion-scale-press);
422
+ transition-duration: var(--xh-motion-duration-press);
423
+ transition-timing-function: var(--xh-motion-ease-press);
454
424
  }
455
425
 
456
426
  /* 取色途中按钮保持按下的样子:屏幕取色期间浮层多半被系统的取色镜头盖着,
@@ -462,54 +432,41 @@
462
432
 
463
433
  [data-scope='color-picker'][data-part='eye-dropper-trigger']:disabled {
464
434
  color: var(--xh-fg-disabled);
465
- cursor: not-allowed;
466
435
  }
467
436
 
468
- [data-scope='color-picker'][data-part='swatch-group'] {
437
+ /* 预设色板的挂载点,同时充当色板的根节点:color-swatch-picker 那份皮的 root 规则落在
438
+ [data-scope='color-swatch-picker'][data-part='root'] 上,而这里没有那个节点,所以根上挂的那几个私有槽
439
+ (格子边长、间距、徽标尺寸、语气色、图标尺)与排布得在这儿照抄一遍;格子的皮仍归色板那一份。
440
+ 浮层里的色板走小号格子:与滑块的拇指、数值框一个量级,整块面板才不会被色板撑开 */
441
+ [data-scope='color-picker'][data-part='swatch-picker'] {
442
+ --xh-_color-swatch-picker-cell: var(--xh-color-picker-swatch-cell, var(--xh-control-h-sm));
443
+ --xh-_color-swatch-picker-gap: var(--xh-color-picker-swatch-gap, var(--xh-control-gap-sm));
444
+ --xh-_color-swatch-picker-indicator: var(--xh-control-indicator-sm);
445
+ --xh-_color-swatch-picker-mark: calc(var(--xh-_color-swatch-picker-indicator) - var(--xh-space-1));
446
+ --xh-_color-swatch-picker-accent: var(--xh-_tone, var(--xh-bg-brand));
447
+ --xh-icon-size: var(--xh-color-picker-swatch-icon-size, var(--xh-_color-swatch-picker-mark));
448
+
469
449
  display: flex;
470
450
  flex-wrap: wrap;
471
- gap: var(--xh-color-picker-swatch-gap, var(--xh-space-1));
472
- }
473
-
474
- /* 每格都是原生按钮、各占一个 Tab 位;背景由连接层内联给 */
475
- [data-scope='color-picker'][data-part='swatch-item'] {
476
- inline-size: var(--xh-color-picker-swatch-item-size, 1.25rem);
477
- block-size: var(--xh-color-picker-swatch-item-size, 1.25rem);
478
- padding: 0;
479
- border: var(--xh-stroke-thin) solid var(--xh-color-picker-swatch-border, var(--xh-border-default));
480
- border-radius: var(--xh-color-picker-swatch-radius, var(--xh-shape-inset));
481
- cursor: pointer;
482
- }
483
-
484
- /* 正被选中的那一格:环画在盒子外面,不挤占色块本身的面积 */
485
- [data-scope='color-picker'][data-part='swatch-item'][data-state='checked'] {
486
- outline: var(--xh-ring-width) solid var(--xh-color-picker-swatch-ring, var(--xh-bg-brand));
487
- outline-offset: var(--xh-ring-offset);
488
- }
489
-
490
- [data-scope='color-picker'][data-part='swatch-item']:focus-visible {
491
- outline: var(--xh-ring-width) solid var(--xh-ring-focus);
492
- outline-offset: var(--xh-ring-offset);
451
+ align-items: center;
452
+ gap: var(--xh-color-picker-swatch-picker-gap, var(--xh-_color-swatch-picker-gap));
493
453
  }
494
454
 
495
- [data-scope='color-picker'][data-part='swatch-item']:disabled {
455
+ [data-scope='color-picker'][data-part='swatch-picker'][data-disabled] {
496
456
  cursor: not-allowed;
497
- opacity: var(--xh-state-disabled-opacity);
498
457
  }
499
458
 
500
459
  /* 任何 display 都会盖掉 UA 的 [hidden]{display:none}:
501
460
  凡是被赋了 display 的角色节点都要显式让位,漏一处收起态就失效。
502
- 连接层当下只往 content 上写 hidden,其余几处是给作者自己收起某一块留的后路。 */
461
+ content 的收起交给 presence:退场结束后由适配器写内联 display:none,避免截断动画。 */
503
462
  [data-scope='color-picker'][data-part='root'][hidden],
504
463
  [data-scope='color-picker'][data-part='trigger'][hidden],
505
- [data-scope='color-picker'][data-part='swatch'][hidden],
506
- [data-scope='color-picker'][data-part='content'][hidden],
507
- [data-scope='color-picker'][data-part='area'][hidden],
464
+ [data-scope='color-picker'][data-part='saturation-area'][hidden],
508
465
  [data-scope='color-picker'][data-part='area-thumb'][hidden],
509
- [data-scope='color-picker'][data-part='channel-slider'][hidden],
510
- [data-scope='color-picker'][data-part='channel-slider-thumb'][hidden],
466
+ [data-scope='color-picker'][data-part='hue-slider'][hidden],
467
+ [data-scope='color-picker'][data-part='alpha-slider'][hidden],
511
468
  [data-scope='color-picker'][data-part='eye-dropper-trigger'][hidden],
512
- [data-scope='color-picker'][data-part='swatch-group'][hidden] {
469
+ [data-scope='color-picker'][data-part='swatch-picker'][hidden] {
513
470
  display: none;
514
471
  }
515
472
 
@@ -528,4 +485,35 @@
528
485
  white-space: nowrap;
529
486
  pointer-events: none;
530
487
  }
488
+
489
+ @media print {
490
+ /* 打印:定位层与遮罩是交互期才存在的东西,落到纸上只会盖住底下的正文。
491
+ 收起写在这份皮肤里而不是 reset:reset 层排在组件层之前,组件层里任何一条 display 都压得住它。 */
492
+ [data-scope='color-picker'][data-part='positioner'] {
493
+ display: none;
494
+ }
495
+ }
496
+
497
+ /*
498
+ * 高对比档:取色面画的就是颜色本身,被系统换掉之后整个组件不再能取色。这一处退出强制着色,
499
+ * 自己保住原色;退出之后它不再跟着系统底色走,补一圈系统描边把它从背景里框出来。
500
+ * 触发钮里的色块归 Swatch 家族、两条滑块的轨道与色板的格子归各自那份皮,都已各自退出强制着色。
501
+ */
502
+ @media (forced-colors: active) {
503
+ /* 高对比档里底色被系统换掉,取色按钮按下那一档用系统高亮反色画回 */
504
+ [data-scope='color-picker'][data-part='eye-dropper-trigger']:not(:disabled):is(:active, [data-pressed]) {
505
+ background: Highlight;
506
+ color: HighlightText;
507
+ }
508
+
509
+ [data-scope='color-picker'][data-part='saturation-area'],
510
+ [data-scope='color-picker'][data-part='saturation-area']::before {
511
+ forced-color-adjust: none;
512
+ }
513
+
514
+ [data-scope='color-picker'][data-part='saturation-area'] {
515
+ outline: var(--xh-stroke-thin) solid ButtonBorder;
516
+ outline-offset: calc(-1 * var(--xh-stroke-thin));
517
+ }
518
+ }
531
519
  }