@xihan-ui/styles 2.1.0 → 3.1.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 +1261 -0
  2. package/README.md +6 -1
  3. package/component-tokens.d.ts +533 -96
  4. package/components.tokens.json +35461 -26045
  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 +128 -50
  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 +56 -0
  37. package/css/date-picker.css +132 -26
  38. package/css/date-range-picker.css +337 -14
  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 +20 -18
  49. package/css/file-upload.css +125 -135
  50. package/css/flex.css +324 -8
  51. package/css/float-button.css +263 -38
  52. package/css/floating-panel.css +53 -19
  53. package/css/form.css +31 -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 +435 -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 +175 -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 +103 -17
  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 +271 -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 +13824 -4030
  147. package/index.unlayered.css +13403 -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
@@ -6,6 +6,7 @@
6
6
  /* 定义 image viewer 样式。 */
7
7
 
8
8
  @import '../family/action-control.css';
9
+ @import '../family/loading-ring.css';
9
10
 
10
11
  /* 共享关键帧由 family/motion.css 提供,本皮肤 @import 它,单独引入仍成立。 */
11
12
  @import '../family/motion.css';
@@ -35,7 +36,7 @@
35
36
  background: transparent;
36
37
  }
37
38
 
38
- [data-scope='image-viewer'][data-part='backdrop'][data-state='open'] {
39
+ [data-scope='image-viewer'][data-part='backdrop'][data-state='open']:not([data-instant]) {
39
40
  animation: xh-fade-in var(--xh-motion-duration-enter) var(--xh-motion-ease-enter);
40
41
  }
41
42
 
@@ -75,7 +76,8 @@
75
76
  color: var(--xh-image-viewer-fg, var(--xh-color-neutral-0));
76
77
  }
77
78
 
78
- [data-scope='image-viewer'][data-part='content'][data-state='open'] {
79
+ /* 挂载时就开着的那一段(data-instant)属于首帧,直接呈现 */
80
+ [data-scope='image-viewer'][data-part='content'][data-state='open']:not([data-instant]) {
79
81
  animation: xh-fade-in var(--xh-motion-duration-enter) var(--xh-motion-ease-enter);
80
82
  }
81
83
 
@@ -104,29 +106,67 @@
104
106
  cursor: progress;
105
107
  }
106
108
 
107
- /* 取图期间在画面正中垫一块占位面:不垫的话打开一张几 MB 的原图,
108
- 台前是一整块什么都没有的暗底,用户分不清是在加载还是这张图坏了 */
109
- [data-scope='image-viewer'][data-part='viewport'][data-loading]::after {
109
+ /* 取图期间画面正中一枚加载环:不给的话打开一张几 MB 的原图,台前是一整块什么都没有的暗底,
110
+ 用户分不清是在加载还是这张图坏了。环由加载环配方画(连接层投影 data-xh-loading-ring),
111
+ 随 data-loading 淡入淡出;前景随看片层的白墨域 */
112
+ [data-scope='image-viewer'][data-part='viewport'] {
113
+ /* 画面正中那两枚状态图形(加载环与警示字形)的尺:看片台是整幅画面,取控件图标档的最大一档 */
114
+ --xh-icon-size: var(--xh-image-viewer-status-size, var(--xh-glyph-size-lg));
115
+ }
116
+
117
+ [data-scope='image-viewer'][data-part='viewport']::before {
118
+ content: '';
119
+ position: absolute;
120
+ inline-size: var(--xh-icon-size, var(--xh-glyph-size-md));
121
+ block-size: var(--xh-icon-size, var(--xh-glyph-size-md));
122
+ }
123
+
124
+ /* 取图失败:画面正中一枚警示字形(取危险色,非颜色通道),替掉浏览器画的破图与替代文字 */
125
+ [data-scope='image-viewer'][data-part='viewport'][data-error]::after {
110
126
  content: '';
111
127
  position: absolute;
112
- inline-size: var(--xh-image-viewer-loading-size, calc(var(--xh-control-h-lg) * 3));
113
- block-size: var(--xh-image-viewer-loading-size, calc(var(--xh-control-h-lg) * 3));
114
- border-radius: var(--xh-image-viewer-loading-radius, var(--xh-shape-surface));
115
- background: var(--xh-image-viewer-loading-bg, var(--xh-bg-surface-raised));
128
+ inline-size: var(--xh-icon-size, var(--xh-glyph-size-md));
129
+ block-size: var(--xh-icon-size, var(--xh-glyph-size-md));
130
+ background-color: var(--xh-image-viewer-error-fg, var(--xh-fg-danger));
131
+ -webkit-mask: var(--xh-glyph-mark-warning) center / contain no-repeat;
132
+ mask: var(--xh-glyph-mark-warning) center / contain no-repeat;
116
133
  }
117
134
 
118
135
  [data-scope='image-viewer'][data-part='image'] {
119
136
  max-inline-size: 90%;
120
137
  max-block-size: 85%;
121
138
  user-select: none;
122
- /* 变换是内联 style 写的,只给缩放旋转一点缓动;拖拽平移要跟手,不缓 */
123
- transition: transform var(--xh-motion-duration-micro) var(--xh-motion-ease-continuous);
139
+ /* 位移、旋转与缩放都是内联 style 写的,只给按钮带来的缩放旋转一点缓动;拖拽平移要跟手,不缓。
140
+ 新图取到之后淡入 */
141
+ transition:
142
+ translate var(--xh-motion-duration-nudge) var(--xh-motion-ease-continuous),
143
+ rotate var(--xh-motion-duration-nudge) var(--xh-motion-ease-continuous),
144
+ scale var(--xh-motion-duration-nudge) var(--xh-motion-ease-continuous),
145
+ opacity var(--xh-motion-duration-enter) var(--xh-motion-ease-enter);
146
+ }
147
+
148
+ /* 取图期间(打开与换下标):换图那一刻变换直接归位、不补间——转过、放大过的旧图不当着用户转回、缩回;
149
+ 旧图随即让位,视口垫着的占位面顶上,不露底色闪一拍。取到之后撤掉这一档,按上面的进场档淡入 */
150
+ [data-scope='image-viewer'][data-part='image'][data-loading] {
151
+ opacity: 0;
152
+ transition: none;
124
153
  }
125
154
 
126
- /* 拖拽期间变换每帧都在改:只在这一档备好合成层,松手后随 data-dragging 一起撤掉 */
155
+ /* 载不出来的图不露浏览器的破图:整张让位给视口正中的警示字形,替代文字仍在可及树里 */
156
+ [data-scope='image-viewer'][data-part='image'][data-error] {
157
+ visibility: hidden;
158
+ }
159
+
160
+ /* 拖拽期间平移每帧都在改:只在这一档备好合成层,松手后随 data-dragging 一起撤掉 */
127
161
  [data-scope='image-viewer'][data-part='image'][data-dragging] {
128
162
  transition: none;
129
- will-change: transform;
163
+ will-change: translate;
164
+ }
165
+
166
+ /* 松手后弹簧带着平移惯性滑行、越出范围时回弹,同样逐帧写变换,不能再叠一层过渡;落定即撤 */
167
+ [data-scope='image-viewer'][data-part='image'][data-animating] {
168
+ transition: none;
169
+ will-change: translate;
130
170
  }
131
171
 
132
172
  /* —— 悬浮件共用:半透明深底加浅字 ——
@@ -155,6 +195,11 @@
155
195
  border-radius: var(--xh-image-viewer-toolbar-radius-outer, var(--xh-image-viewer-overlay-radius, var(--xh-shape-surface)));
156
196
  }
157
197
 
198
+ /* 起点是逻辑属性、平移是物理通道:rtl 下行内分量掉头,工具条与计数才落回中线 */
199
+ [data-scope='image-viewer'][data-part='toolbar']:dir(rtl) {
200
+ translate: 50% 0;
201
+ }
202
+
158
203
  /* 工具条里的七颗钮:接 Action Control icon 档 xs(24px 视觉盒),底色交给工具条,本体只管命中区与按压。
159
204
  悬停 / 按下的底从 chrome 那层深底派生,不取页面的 --xh-bg-subtle-* 阶梯。
160
205
  position 交给配方的 relative:粗指针下 44px 命中区 ::after 以钮自身为包含块;
@@ -169,7 +214,7 @@
169
214
  --xh-action-fg-hover: currentColor;
170
215
  --xh-action-fg-pressed: currentColor;
171
216
  --xh-action-fg-focus-visible: currentColor;
172
- --xh-action-fg-disabled: currentColor;
217
+ --xh-action-fg-disabled: var(--xh-fg-disabled);
173
218
  --xh-action-border-rest: transparent;
174
219
  --xh-action-border-hover: transparent;
175
220
  --xh-action-border-pressed: transparent;
@@ -188,6 +233,10 @@
188
233
  font-size: var(--xh-text-secondary-size);
189
234
  }
190
235
 
236
+ [data-scope='image-viewer'][data-part='counter']:dir(rtl) {
237
+ translate: 50% 0;
238
+ }
239
+
191
240
  /* 两颗翻页钮:浮在图上的单图标圆钮,接 Action Control floating 档 md(48px,正方盒取 circle)。
192
241
  面桥接到自家深色 chrome:跟的是图上那层半透明深底不是页面底色,所以不取 frosted 缺省面,
193
242
  也不取语义档的 --xh-bg-subtle-*;到头时是原生 disabled,压不动的东西不给回应 */
@@ -202,7 +251,7 @@
202
251
  --xh-action-fg-hover: currentColor;
203
252
  --xh-action-fg-pressed: currentColor;
204
253
  --xh-action-fg-focus-visible: currentColor;
205
- --xh-action-fg-disabled: currentColor;
254
+ --xh-action-fg-disabled: var(--xh-fg-disabled);
206
255
  --xh-action-border-rest: transparent;
207
256
  --xh-action-border-hover: transparent;
208
257
  --xh-action-border-pressed: transparent;
@@ -227,7 +276,8 @@
227
276
  translate: 0 -50%;
228
277
  }
229
278
 
230
- /* 右上角的关闭钮:接 Action Control icon 档 lg(40px,触控靶走 lg),圆角走控件档;面与翻页钮同一层深色 chrome */
279
+ /* 右上角的关闭钮:悬浮在媒体上的单图标动作,与翻页钮同走 Action Control floating 档(sm = 40px、圆形);
280
+ 面与翻页钮同一层深色 chrome */
231
281
  [data-scope='image-viewer'][data-part='close-trigger'] {
232
282
  --xh-action-bg-rest: var(--xh-_image-viewer-chrome-bg);
233
283
  --xh-action-bg-hover: var(--xh-image-viewer-close-bg-hover, var(--xh-_image-viewer-chrome-bg-hover));
@@ -239,13 +289,13 @@
239
289
  --xh-action-fg-hover: var(--xh-image-viewer-close-fg, currentColor);
240
290
  --xh-action-fg-pressed: var(--xh-image-viewer-close-fg, currentColor);
241
291
  --xh-action-fg-focus-visible: var(--xh-image-viewer-close-fg, currentColor);
242
- --xh-action-fg-disabled: var(--xh-image-viewer-close-fg, currentColor);
292
+ --xh-action-fg-disabled: var(--xh-fg-disabled);
243
293
  --xh-action-border-rest: transparent;
244
294
  --xh-action-border-hover: transparent;
245
295
  --xh-action-border-pressed: transparent;
246
296
  --xh-action-border-focus-visible: transparent;
247
297
  --xh-action-border-disabled: transparent;
248
- --xh-action-radius: var(--xh-image-viewer-close-radius, var(--xh-shape-control));
298
+ --xh-action-radius: var(--xh-image-viewer-close-radius, var(--xh-shape-circle));
249
299
  --xh-action-visual-size: var(--xh-image-viewer-close-size, var(--xh-_action-profile-visual-size));
250
300
  --xh-icon-size: var(--xh-image-viewer-icon-size, var(--xh-_action-profile-glyph-size));
251
301
 
@@ -255,6 +305,80 @@
255
305
  inset-inline-end: max(var(--xh-space-6), env(safe-area-inset-left), env(safe-area-inset-right));
256
306
  }
257
307
 
308
+ /* liquid 档:data-material="liquid" 下控制层换成液态面,深色纱那一套只属于 standard 档。
309
+ 液态面按下层(使用者的图片、遮罩)写墨色域,前景跟着墨色走,不再钉在浅字上。
310
+ 工具条是不贴边的一维栏、计数是一行字的 chip,取 pill;翻页与关闭是媒体控制钮,取 circle */
311
+ :where([data-material='liquid']) [data-scope='image-viewer'][data-part='toolbar'][data-xh-liquid],
312
+ :where([data-material='liquid']) [data-scope='image-viewer'][data-part='counter'][data-xh-liquid] {
313
+ border: var(--xh-stroke-thin) solid var(--xh-material-liquid-border);
314
+ background: var(--xh-image-viewer-chrome-bg, var(--xh-_liquid-bg));
315
+ color: var(--xh-material-liquid-fg);
316
+ box-shadow: var(--xh-_liquid-shadow);
317
+ -webkit-backdrop-filter: var(--xh-material-liquid-backdrop);
318
+ backdrop-filter: var(--xh-material-liquid-backdrop);
319
+ /* 换到深浅不同的图上时色调翻转:底色、字色、细线与投影一起淡变 */
320
+ transition:
321
+ background-color var(--xh-motion-duration-micro) var(--xh-motion-ease-enter),
322
+ border-color var(--xh-motion-duration-micro) var(--xh-motion-ease-enter),
323
+ color var(--xh-motion-duration-micro) var(--xh-motion-ease-enter),
324
+ box-shadow var(--xh-motion-duration-micro) var(--xh-motion-ease-enter);
325
+ }
326
+
327
+ :where([data-material='liquid']) [data-scope='image-viewer'][data-part='toolbar'][data-xh-liquid] {
328
+ border-radius: var(--xh-image-viewer-toolbar-radius-outer, var(--xh-image-viewer-overlay-radius, var(--xh-shape-pill)));
329
+ }
330
+
331
+ :where([data-material='liquid']) [data-scope='image-viewer'][data-part='counter'][data-xh-liquid] {
332
+ border-radius: var(--xh-image-viewer-counter-radius, var(--xh-image-viewer-overlay-radius, var(--xh-shape-pill)));
333
+ }
334
+
335
+ /* 工具条里的钮:悬停 / 按下取墨色淡底阶梯,工具条这块液态面就是它们的墨色域 */
336
+ :where([data-material='liquid']) [data-scope='image-viewer'][data-part='toolbar'][data-xh-liquid] > [data-part] {
337
+ --xh-action-bg-hover: var(--xh-image-viewer-action-bg-hover, var(--xh-bg-subtle));
338
+ --xh-action-bg-pressed: var(--xh-image-viewer-action-bg-active, var(--xh-bg-subtle-hover));
339
+ }
340
+
341
+ :where([data-material='liquid']) [data-scope='image-viewer'][data-part='prev-trigger'][data-xh-liquid],
342
+ :where([data-material='liquid']) [data-scope='image-viewer'][data-part='next-trigger'][data-xh-liquid],
343
+ :where([data-material='liquid']) [data-scope='image-viewer'][data-part='close-trigger'][data-xh-liquid] {
344
+ --xh-action-bg-rest: var(--xh-image-viewer-chrome-bg, var(--xh-_liquid-bg));
345
+ --xh-action-bg-hover: var(--xh-image-viewer-action-bg-hover, var(--xh-_liquid-bg-hover));
346
+ --xh-action-bg-pressed: var(--xh-image-viewer-action-bg-active, var(--xh-_liquid-bg-pressed));
347
+ --xh-action-bg-focus-visible: var(--xh-image-viewer-chrome-bg, var(--xh-material-liquid-focus-surface));
348
+ --xh-action-bg-disabled: var(--xh-image-viewer-chrome-bg, var(--xh-_liquid-bg));
349
+ --xh-action-fg-rest: var(--xh-material-liquid-fg);
350
+ --xh-action-fg-hover: var(--xh-material-liquid-fg);
351
+ --xh-action-fg-pressed: var(--xh-material-liquid-fg);
352
+ --xh-action-fg-focus-visible: var(--xh-material-liquid-fg);
353
+ --xh-action-border-rest: var(--xh-material-liquid-border);
354
+ --xh-action-border-hover: var(--xh-material-liquid-border);
355
+ --xh-action-border-pressed: var(--xh-material-liquid-border);
356
+ --xh-action-border-focus-visible: var(--xh-material-liquid-border);
357
+ --xh-action-border-disabled: var(--xh-material-liquid-border);
358
+ --xh-action-fg-disabled: var(--xh-fg-disabled);
359
+ --xh-action-shadow-rest: var(--xh-_liquid-shadow);
360
+ --xh-action-shadow-hover: var(--xh-_liquid-shadow);
361
+ --xh-action-shadow-pressed: var(--xh-_liquid-shadow);
362
+ --xh-action-shadow-focus-visible: var(--xh-_liquid-shadow);
363
+ --xh-action-shadow-disabled: var(--xh-_liquid-shadow);
364
+
365
+ color: var(--xh-material-liquid-fg);
366
+ -webkit-backdrop-filter: var(--xh-material-liquid-backdrop);
367
+ backdrop-filter: var(--xh-material-liquid-backdrop);
368
+ transform: var(--xh-_liquid-deform);
369
+ }
370
+
371
+ /* 叉的前景仍认使用者的那支槽;圆钮取 circle */
372
+ :where([data-material='liquid']) [data-scope='image-viewer'][data-part='close-trigger'][data-xh-liquid] {
373
+ --xh-action-fg-rest: var(--xh-image-viewer-close-fg, var(--xh-material-liquid-fg));
374
+ --xh-action-fg-hover: var(--xh-image-viewer-close-fg, var(--xh-material-liquid-fg));
375
+ --xh-action-fg-pressed: var(--xh-image-viewer-close-fg, var(--xh-material-liquid-fg));
376
+ --xh-action-fg-focus-visible: var(--xh-image-viewer-close-fg, var(--xh-material-liquid-fg));
377
+ --xh-action-bg-hover: var(--xh-image-viewer-close-bg-hover, var(--xh-_liquid-bg-hover));
378
+ --xh-action-bg-pressed: var(--xh-image-viewer-close-bg-active, var(--xh-_liquid-bg-pressed));
379
+ --xh-action-radius: var(--xh-image-viewer-close-radius, var(--xh-shape-circle));
380
+ }
381
+
258
382
  /* 三颗钮的面是一层深色纱,纱底下是使用者的图片,环色算不出稳定的取值。
259
383
  content 把前景钉死在浅字上、三颗钮的前景随它继承,环取 currentColor 即是那支浅字,
260
384
  不随图片内容也不随主题翻 */
@@ -268,10 +392,6 @@
268
392
  display: none;
269
393
  }
270
394
 
271
- [data-scope='image-viewer'] button[data-part]:disabled {
272
- opacity: var(--xh-state-disabled-opacity);
273
- }
274
-
275
395
  /* 没写内容就由皮肤画兜底字形;作者往部件里塞了自己的图形,这几条即不命中 */
276
396
  [data-scope='image-viewer'][data-part='zoom-in-trigger']:empty::before {
277
397
  content: '';
@@ -390,4 +510,29 @@
390
510
  display: none;
391
511
  }
392
512
  }
513
+
514
+ @media (forced-colors: active) {
515
+ /* 兜底字形是 mask 挖出来的一块底色,这一档里底色被系统换成 Canvas,字形跟着消失。
516
+ 字形退出强制换色、直接写系统色(不能取 currentColor:退出强制换色的伪元素读到的是被系统换掉之前的作者色):
517
+ 按钮面上取 ButtonText,悬停与按下时家族把按钮涂成 Highlight、字形换 HighlightText;
518
+ 落在 Canvas 面上的取 CanvasText;
519
+ 禁用取 GrayText */
520
+ [data-scope='image-viewer'][data-part='viewport'][data-error]::after {
521
+ forced-color-adjust: none;
522
+ background-color: CanvasText;
523
+ }
524
+
525
+ [data-scope='image-viewer']:is([data-part='zoom-in-trigger'], [data-part='zoom-out-trigger'], [data-part='rotate-left-trigger'], [data-part='rotate-right-trigger'], [data-part='flip-horizontal-trigger'], [data-part='flip-vertical-trigger'], [data-part='prev-trigger'], [data-part='next-trigger'], [data-part='close-trigger']):empty::before {
526
+ forced-color-adjust: none;
527
+ background-color: ButtonText;
528
+ }
529
+
530
+ [data-scope='image-viewer']:is([data-part='zoom-in-trigger'], [data-part='zoom-out-trigger'], [data-part='rotate-left-trigger'], [data-part='rotate-right-trigger'], [data-part='flip-horizontal-trigger'], [data-part='flip-vertical-trigger'], [data-part='prev-trigger'], [data-part='next-trigger'], [data-part='close-trigger']):not([data-disabled]):not([data-loading]):is(:hover, :active, [data-pressed]):empty::before {
531
+ background-color: HighlightText;
532
+ }
533
+
534
+ [data-scope='image-viewer']:is([data-part='zoom-in-trigger'], [data-part='zoom-out-trigger'], [data-part='rotate-left-trigger'], [data-part='rotate-right-trigger'], [data-part='flip-horizontal-trigger'], [data-part='flip-vertical-trigger'], [data-part='prev-trigger'], [data-part='next-trigger'], [data-part='close-trigger'])[data-disabled]:empty::before {
535
+ background-color: GrayText;
536
+ }
537
+ }
393
538
  }
package/css/image.css CHANGED
@@ -42,18 +42,30 @@
42
42
  animation: xh-fade-in var(--xh-motion-duration-enter) var(--xh-motion-ease-enter);
43
43
  }
44
44
 
45
- /* 铺满图位的占位层:加载期间占住画面,作者往里放骨架屏或模糊小图 */
45
+ /* 占位层还在(正淡出)时图片不再自己淡入:它在占位层底下直接落位,由占位层的淡出揭开,
46
+ 模糊小图与图片交叉,不先透出一拍底色 */
47
+ [data-scope='image'][data-part='root']:has(> [data-part='placeholder']:not([hidden])) > [data-part='image'] {
48
+ animation: none;
49
+ }
50
+
51
+ /* 铺满图位的占位层:加载期间占住画面,作者往里放骨架屏或模糊小图。它叠在图位自己的淡底上,
52
+ 取不透明档,不与底下那层叠深 */
46
53
  [data-scope='image'][data-part='placeholder'] {
47
54
  position: absolute;
48
55
  inset: 0;
49
56
  display: flex;
50
57
  align-items: center;
51
58
  justify-content: center;
52
- background: var(--xh-image-placeholder-bg, var(--xh-bg-subtle-hover));
59
+ background: var(--xh-image-placeholder-bg, var(--xh-bg-subtle-hover-opaque));
53
60
  color: var(--xh-image-placeholder-fg, var(--xh-fg-subtle));
54
61
  }
55
62
 
56
- /* display 会盖掉 hidden 属性的 UA 规则:图片落位与失败后都靠这条收起 */
63
+ /* 图片落位或失败:占位层原地淡出(它盖在图位之上),播完连接层才写 hidden */
64
+ [data-scope='image'][data-part='placeholder']:is([data-state='loaded'], [data-state='error']) {
65
+ animation: xh-fade-out var(--xh-motion-duration-enter) var(--xh-motion-ease-enter) forwards;
66
+ }
67
+
68
+ /* display 会盖掉 hidden 属性的 UA 规则:淡出播完之后靠这条收起 */
57
69
  [data-scope='image'][data-part='placeholder'][hidden] {
58
70
  display: none;
59
71
  }
@@ -72,7 +84,14 @@
72
84
  user-select: none;
73
85
  }
74
86
 
75
- /* display 会盖掉 hidden 属性的 UA 规则:延迟窗口内与加载完成后都靠这条收起 */
87
+ /* 图片载好:回退内容浮到图片之上原地淡出,与图片的淡入交叉;播完连接层才写 hidden */
88
+ [data-scope='image'][data-part='fallback'][data-state='loaded'] {
89
+ position: absolute;
90
+ inset: 0;
91
+ animation: xh-fade-out var(--xh-motion-duration-enter) var(--xh-motion-ease-enter) forwards;
92
+ }
93
+
94
+ /* display 会盖掉 hidden 属性的 UA 规则:延迟窗口内与淡出播完之后靠这条收起 */
76
95
  [data-scope='image'][data-part='fallback'][hidden] {
77
96
  display: none;
78
97
  }
@@ -33,6 +33,8 @@
33
33
  display: inline-flex;
34
34
  box-sizing: border-box;
35
35
  align-items: stretch;
36
+ /* 整组是一个字段:不传尺寸时与单个字段同宽,组里的字段让位占满前后缀之外的那段 */
37
+ inline-size: var(--xh-input-group-w, var(--xh-control-w));
36
38
  border-radius: var(--xh-input-group-radius, var(--xh-shape-control));
37
39
  background: var(--xh-input-group-bg, var(--xh-_input-group-bg));
38
40
  box-shadow: var(--xh-input-group-shadow, var(--xh-_input-group-shadow));
@@ -40,7 +42,7 @@
40
42
  /* 父容器给不出这么宽时整组跟着收,不越出父容器 */
41
43
  max-inline-size: 100%;
42
44
  transition:
43
- background var(--xh-motion-duration-micro) var(--xh-motion-ease-enter),
45
+ background-color var(--xh-motion-duration-micro) var(--xh-motion-ease-enter),
44
46
  box-shadow var(--xh-motion-duration-micro) var(--xh-motion-ease-enter);
45
47
  }
46
48
 
@@ -175,6 +177,14 @@
175
177
  box-shadow: none;
176
178
  }
177
179
 
180
+ /* 组里的字段(带字段外壳的控件)占满前后缀与动作之外的剩余宽度,自己的缺省宽让位;
181
+ 前后缀、按钮这些段按内容宽,不跟着撑开 */
182
+ [data-scope='input-group'][data-part='root'] > :is([data-xh-field-chrome], :has([data-xh-field-chrome])) {
183
+ flex: 1 1 0%;
184
+ min-inline-size: 0;
185
+ inline-size: auto;
186
+ }
187
+
178
188
  /* 每一段都是定位元素,动作控件的悬停面可以浮到外轮廓之上。 */
179
189
  [data-scope='input-group'][data-part='root'] > * {
180
190
  position: relative;
@@ -239,18 +249,6 @@
239
249
  display: none;
240
250
  }
241
251
 
242
- @media (prefers-reduced-motion: reduce) {
243
- [data-scope='input-group'][data-part='root'],
244
- [data-scope='input-group'][data-part='root']::before {
245
- transition: none;
246
- }
247
- }
248
-
249
- :where([data-motion='reduce']) [data-scope='input-group'][data-part='root'],
250
- :where([data-motion='reduce']) [data-scope='input-group'][data-part='root']::before {
251
- transition: none;
252
- }
253
-
254
252
  @media (forced-colors: active) {
255
253
  [data-scope='input-group'][data-part='root'] {
256
254
  background: Canvas;
@@ -133,7 +133,7 @@
133
133
  padding-inline: var(--xh-json-viewer-row-px, var(--xh-space-1));
134
134
  border-radius: var(--xh-json-viewer-row-radius, var(--xh-shape-inset));
135
135
  white-space: nowrap;
136
- transition: background var(--xh-motion-duration-micro) var(--xh-motion-ease-enter);
136
+ transition: background-color var(--xh-motion-duration-micro) var(--xh-motion-ease-enter);
137
137
  }
138
138
 
139
139
  [data-scope='json-viewer'][data-part='item'][hidden],
@@ -235,7 +235,7 @@
235
235
  [data-scope='json-viewer'][data-part='branch-indicator'] {
236
236
  display: inline-block;
237
237
  line-height: var(--xh-leading-none);
238
- transition: rotate var(--xh-motion-duration-micro) var(--xh-motion-ease-enter-strong);
238
+ transition: rotate var(--xh-motion-duration-nudge) var(--xh-motion-ease-enter-strong);
239
239
  }
240
240
 
241
241
  [data-scope='json-viewer'][data-part='branch-indicator'][hidden] {
@@ -311,6 +311,23 @@
311
311
  display: none;
312
312
  }
313
313
 
314
+ /*
315
+ * 搜索命中的那一段:与 Highlight 的命中片段同一身份(品牌淡底 + 品牌深字),浏览器给 mark 的固定亮黄不随主题走。
316
+ * 在命中之间逐个走时停住的那一行(data-current),片段换成品牌实心,一眼分得出「现在停在哪」。
317
+ */
318
+ [data-scope='json-viewer'][data-part='mark'] {
319
+ border-radius: var(--xh-json-viewer-mark-radius, var(--xh-shape-inset));
320
+ background: var(--xh-json-viewer-mark-bg, var(--xh-bg-brand-subtle));
321
+ color: var(--xh-json-viewer-mark-fg, var(--xh-fg-brand-strong));
322
+ }
323
+
324
+ [data-scope='json-viewer'][data-part='branch'][data-current] > [data-scope='json-viewer'][data-part='branch-control'] > [data-scope='json-viewer'][data-part='branch-text'] > [data-scope='json-viewer'][data-part='mark'],
325
+ [data-scope='json-viewer'][data-part='item'][data-current] > [data-scope='json-viewer'][data-part='item-key'] > [data-scope='json-viewer'][data-part='mark'],
326
+ [data-scope='json-viewer'][data-part='item'][data-current] > [data-scope='json-viewer'][data-part='item-value'] > [data-scope='json-viewer'][data-part='mark'] {
327
+ background: var(--xh-json-viewer-mark-bg-current, var(--xh-bg-brand));
328
+ color: var(--xh-json-viewer-mark-fg-current, var(--xh-fg-on-brand));
329
+ }
330
+
314
331
  /*
315
332
  * 高对比档:分支行的按压面常态靠底色深一档表出,这一档里底色被统一换成 Canvas,
316
333
  * 按住那一下与静息塌成同一个样子;用系统高亮反色画回来,行里的键名、摘要与箭头跟着换成反色前景
@@ -321,6 +338,18 @@
321
338
  color: HighlightText;
322
339
  }
323
340
 
341
+ /* 系统色下底色统一成 Canvas:命中片段改画一圈正文色的框,停住的那一条换成系统高亮 */
342
+ [data-scope='json-viewer'][data-part='mark'] {
343
+ outline: var(--xh-stroke-thin) solid CanvasText;
344
+ }
345
+
346
+ [data-scope='json-viewer'][data-part='branch'][data-current] > [data-scope='json-viewer'][data-part='branch-control'] > [data-scope='json-viewer'][data-part='branch-text'] > [data-scope='json-viewer'][data-part='mark'],
347
+ [data-scope='json-viewer'][data-part='item'][data-current] > [data-scope='json-viewer'][data-part='item-key'] > [data-scope='json-viewer'][data-part='mark'],
348
+ [data-scope='json-viewer'][data-part='item'][data-current] > [data-scope='json-viewer'][data-part='item-value'] > [data-scope='json-viewer'][data-part='mark'] {
349
+ background: Highlight;
350
+ color: HighlightText;
351
+ }
352
+
324
353
  [data-scope='json-viewer'][data-part='branch-control']:not([data-disabled]):is(:active, [data-pressed]) [data-scope='json-viewer'][data-part='branch-text'],
325
354
  [data-scope='json-viewer'][data-part='branch-control']:not([data-disabled]):is(:active, [data-pressed]) [data-scope='json-viewer'][data-part='branch-text']::after,
326
355
  [data-scope='json-viewer'][data-part='branch-control']:not([data-disabled]):is(:active, [data-pressed]) [data-scope='json-viewer'][data-part='preview'],
@@ -328,4 +357,23 @@
328
357
  color: HighlightText;
329
358
  }
330
359
  }
360
+
361
+ @media (forced-colors: active) {
362
+ /* 兜底字形是 mask 挖出来的一块底色,这一档里底色被系统换成 Canvas,字形跟着消失。
363
+ 字形退出强制换色、直接写系统色(不能取 currentColor:退出强制换色的伪元素读到的是被系统换掉之前的作者色):
364
+ 分支行上取 CanvasText,按下时整行涂成 Highlight、字形换 HighlightText;
365
+ 禁用取 GrayText */
366
+ [data-scope='json-viewer'][data-part='branch-indicator']:empty::before {
367
+ forced-color-adjust: none;
368
+ background-color: CanvasText;
369
+ }
370
+
371
+ [data-scope='json-viewer'][data-part='branch-control']:not([data-disabled]):is(:active, [data-pressed]) [data-scope='json-viewer'][data-part='branch-indicator']:empty::before {
372
+ background-color: HighlightText;
373
+ }
374
+
375
+ [data-scope='json-viewer'][data-part='branch-control'][data-disabled] [data-scope='json-viewer'][data-part='branch-indicator']:empty::before {
376
+ background-color: GrayText;
377
+ }
378
+ }
331
379
  }