@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/card.css CHANGED
@@ -5,6 +5,8 @@
5
5
 
6
6
  /* 定义 card 样式。 */
7
7
 
8
+ @import '../family/motion.css';
9
+
8
10
  @layer xihan.components {
9
11
  /* 皮肤在场的标记:开发模式下按 scope 探一次,取不到就说明这份皮肤没被引入。 */
10
12
  [data-scope='card'] {
@@ -34,6 +36,13 @@
34
36
  /* 形态按根面三选一:outline 即基础规则(描边 + surface 底 + raised),subtle 淡底 + 透明占位边 + 无影
35
37
  (淡底与阴影互斥),ghost 三件都不画(占位边保住 1px 边位,三档几何一致);不承诺悬停或尺寸等额外行为。 */
36
38
  [data-scope='card'][data-part='root'][data-variant='subtle'] {
39
+ /* 淡底容器:坐在它上面的控件按淡底阶梯换面(200 → 300),可交互卡片自己的悬停与按下读同一支私有槽。
40
+ host 槽只写不读,值由私有槽供给,两边同源 */
41
+ --xh-_card-host-bg-hover: var(--xh-bg-subtle-hover);
42
+ --xh-_card-host-bg-pressed: var(--xh-bg-subtle-active);
43
+ --xh-action-host-bg-hover: var(--xh-_card-host-bg-hover);
44
+ --xh-action-host-bg-pressed: var(--xh-_card-host-bg-pressed);
45
+
37
46
  border-color: transparent;
38
47
  background: var(--xh-card-bg, var(--xh-bg-subtle));
39
48
  box-shadow: var(--xh-card-shadow, none);
@@ -45,6 +54,106 @@
45
54
  box-shadow: var(--xh-card-shadow, none);
46
55
  }
47
56
 
57
+ /* —— 整卡可交互 ——
58
+ 点击区由 trigger 的 ::after 铺满整张卡片,可及名与 Tab 位只归 trigger 这个原生链接或按钮。
59
+ 反馈按根面分:outline 是 raised 面,悬停抬高一档海拔(raised → lifted),按下换到白底阶梯的 200;
60
+ subtle / ghost 没有影,按承载面阶梯换面(淡底 200 → 300,无壳 100 → 200)。
61
+ 抬起只走影、不走位移,减弱动效下仍是淡变。按下 press 时长切面,松开按 micro 回落。
62
+ 按下认根的 :active:点击区是 trigger 的伪元素,按在卡片任一处都会让根进入 :active;
63
+ 脚部叠在点击区之上,按脚部里的按钮时根也是 :active,这一档排除掉 */
64
+ [data-scope='card'][data-part='root'][data-interactive] {
65
+ transition-property: background-color, box-shadow;
66
+ transition-duration: var(--xh-motion-duration-micro);
67
+ transition-timing-function: var(--xh-motion-ease-enter);
68
+ }
69
+
70
+ [data-scope='card'][data-part='root'][data-interactive][data-variant='outline']:hover {
71
+ box-shadow: var(--xh-card-shadow-hover, var(--xh-elevation-lifted));
72
+ }
73
+
74
+ [data-scope='card'][data-part='root'][data-interactive][data-variant='subtle']:hover {
75
+ background: var(--xh-card-bg-hover, var(--xh-_card-host-bg-hover));
76
+ }
77
+
78
+ [data-scope='card'][data-part='root'][data-interactive][data-variant='ghost']:hover {
79
+ background: var(--xh-card-bg-hover, var(--xh-bg-subtle));
80
+ }
81
+
82
+ [data-scope='card'][data-part='root'][data-interactive]:active:not(:has([data-scope='card'][data-part='footer']:active)) {
83
+ transition-duration: var(--xh-motion-duration-press);
84
+ }
85
+
86
+ [data-scope='card'][data-part='root'][data-interactive][data-variant='outline']:active:not(:has([data-scope='card'][data-part='footer']:active)) {
87
+ background: var(--xh-card-bg-pressed, var(--xh-bg-subtle-hover-opaque));
88
+ }
89
+
90
+ [data-scope='card'][data-part='root'][data-interactive][data-variant='subtle']:active:not(:has([data-scope='card'][data-part='footer']:active)) {
91
+ background: var(--xh-card-bg-pressed, var(--xh-_card-host-bg-pressed));
92
+ }
93
+
94
+ [data-scope='card'][data-part='root'][data-interactive][data-variant='ghost']:active:not(:has([data-scope='card'][data-part='footer']:active)) {
95
+ background: var(--xh-card-bg-pressed, var(--xh-bg-subtle-hover));
96
+ }
97
+
98
+ /* trigger 读作标题本身:链接不带 UA 的蓝字下划线,按钮不带 UA 的框与底 */
99
+ [data-scope='card'][data-part='trigger'] {
100
+ padding: 0;
101
+ border: 0;
102
+ background: none;
103
+ color: inherit;
104
+ font: inherit;
105
+ text-align: inherit;
106
+ text-decoration: none;
107
+ cursor: pointer;
108
+ }
109
+
110
+ /* 点击区铺满整张卡片:相对根定位(根是 position: relative),外扩一条描边宽盖住边框。
111
+ trigger 与根之间的祖先不能再建定位上下文,否则点击区只铺到那一层 */
112
+ [data-scope='card'][data-part='root'][data-interactive] [data-scope='card'][data-part='trigger']::after {
113
+ content: '';
114
+ position: absolute;
115
+ inset: calc(-1 * var(--xh-stroke-thin));
116
+ border-radius: var(--xh-card-radius, var(--xh-shape-surface));
117
+ }
118
+
119
+ /* 焦点环画在整张卡片外沿:环是点击区的轮廓,读者看到的可交互范围与点得到的范围一致 */
120
+ [data-scope='card'][data-part='root'][data-interactive] [data-scope='card'][data-part='trigger']:focus-visible {
121
+ outline: none;
122
+ }
123
+
124
+ [data-scope='card'][data-part='root'][data-interactive] [data-scope='card'][data-part='trigger']:focus-visible::after {
125
+ outline: var(--xh-ring-width) solid var(--xh-_ring-color, var(--xh-ring-focus));
126
+ outline-offset: var(--xh-ring-offset);
127
+ }
128
+
129
+ /* footer 叠在点击区之上:里面另放的按钮照常可点,footer 的空白处不触发整卡 */
130
+ [data-scope='card'][data-part='root'][data-interactive] [data-scope='card'][data-part='footer'] {
131
+ position: relative;
132
+ }
133
+
134
+ /* liquid 档的交互光:可交互卡片进入悬停时,一道光沿 1px 描边扫过一次,与 Button 实心钮同一配方。
135
+ 光只走描边、不进面,取卡片前景色;只在细指针可悬停的设备上播,强制色下不画装饰光。
136
+ 减弱动效下时长归 1ms,一闪即过 */
137
+ @media (hover: hover) and (pointer: fine) and (forced-colors: none) {
138
+ :where([data-material='liquid']) [data-scope='card'][data-part='root'][data-interactive]:hover::after {
139
+ content: '';
140
+ position: absolute;
141
+ inset: calc(-1 * var(--xh-stroke-thin));
142
+ border: var(--xh-stroke-thin) solid transparent;
143
+ border-radius: inherit;
144
+ background: linear-gradient(100deg, transparent 42%, currentColor 50%, transparent 58%) border-box no-repeat;
145
+ background-size: 300% 100%;
146
+ background-position: 0% 0;
147
+ pointer-events: none;
148
+ mask:
149
+ linear-gradient(currentColor 0 0) padding-box exclude,
150
+ linear-gradient(currentColor 0 0);
151
+ animation: xh-glint var(--xh-card-glint-duration, var(--xh-motion-duration-glint)) var(--xh-motion-ease-enter) both;
152
+ /* 光从行首扫向行尾:rtl 下按方向符号把这一圈水平镜像,扫向跟着掉头,缓动不变 */
153
+ scale: var(--xh-direction-sign) 1;
154
+ }
155
+ }
156
+
48
157
  [data-scope='card'][data-part='header'] {
49
158
  display: flex;
50
159
  flex-direction: column;
@@ -59,7 +168,7 @@
59
168
  color: var(--xh-card-title-fg, var(--xh-fg-default));
60
169
  font-size: var(--xh-card-title-font-size, var(--xh-text-label-size));
61
170
  font-weight: var(--xh-card-title-font-weight, var(--xh-font-weight-semibold));
62
- line-height: var(--xh-card-title-leading, var(--xh-leading-relaxed));
171
+ line-height: var(--xh-card-title-leading, var(--xh-leading-tight));
63
172
  }
64
173
 
65
174
  [data-scope='card'][data-part='description'] {
@@ -95,6 +204,11 @@
95
204
  border-color: CanvasText;
96
205
  box-shadow: none;
97
206
  }
207
+
208
+ /* 高对比档里换底与抬起都被系统抹平:可交互卡片的悬停与按下改由描边表出,三档形态同一条 */
209
+ [data-scope='card'][data-part='root'][data-interactive]:is(:hover, :active) {
210
+ border-color: Highlight;
211
+ }
98
212
  }
99
213
 
100
214
  /* 声明过 display 就盖掉 UA 的 [hidden]{display:none},各部件在文件末尾统一还原。 */
package/css/carousel.css CHANGED
@@ -6,6 +6,7 @@
6
6
  /* 定义 carousel 样式。 */
7
7
 
8
8
  @import '../family/action-control.css';
9
+ @import '../family/material.css';
9
10
 
10
11
  @layer xihan.components {
11
12
  /* 皮肤在场的标记:开发模式下按 scope 探一次,取不到就说明这份皮肤没被引入。 */
@@ -16,11 +17,6 @@
16
17
  /* 根节点建立自己的覆盖层:视口占满容器,导航与分页压在内容之上,
17
18
  isolation 把内部层号关在本组件内,不参与页面级层序。 */
18
19
  [data-scope='carousel'][data-part='root'] {
19
- /* 三颗控制钮浮在媒体之上,缺省 M2 磨砂面:背景、边缘、顶光、投影与磨砂从同一份配方取,
20
- 高对比、减少透明度、打印和强制色便能一起降级。三支写在根上:check-elevation-role 按赋值点认海拔角色 */
21
- --xh-_carousel-trigger-bg: var(--xh-material-frosted-bg);
22
- --xh-_carousel-trigger-border: var(--xh-material-frosted-border);
23
- --xh-_carousel-trigger-shadow: var(--xh-material-frosted-shadow);
24
20
  /* 自动播放开启时由 Headless 写入真实间隔;0ms 只用于未接入运行时的静态标记。 */
25
21
  --xh-_carousel-autoplay-duration: 0ms;
26
22
  --xh-_carousel-progress-from: 0 1;
@@ -56,14 +52,14 @@
56
52
  }
57
53
 
58
54
  /* 被位移的那条轨道。
59
- transform 归连接层:整页位移与拖拽中的像素偏移都写在它的内联 style 上,
55
+ translate 归连接层:整页位移与拖拽中的像素偏移都写在它的内联 style 上,
60
56
  样式层再碰这条轴就会把两个位移互相覆盖,画面当场错位。
61
57
  这里只负责排布与过渡 */
62
58
  [data-scope='carousel'][data-part='list'] {
63
59
  display: flex;
64
60
  flex-direction: row;
65
61
  block-size: 100%;
66
- transition: transform var(--xh-carousel-duration, var(--xh-motion-duration-slide))
62
+ transition: translate var(--xh-carousel-duration, var(--xh-motion-duration-slide))
67
63
  var(--xh-carousel-ease, var(--xh-motion-ease-slide));
68
64
  }
69
65
 
@@ -79,7 +75,42 @@
79
75
  整条轨道的位移这一档每帧都在改,合成层只在这一档备好,松手随 data-dragging 一起撤掉 */
80
76
  [data-scope='carousel'][data-part='list'][data-dragging] {
81
77
  transition: none;
82
- will-change: transform;
78
+ will-change: translate;
79
+ }
80
+
81
+ /* 松手后由弹簧带着松手速度逐帧把轨道收到落定位置,同样不能再叠一层过渡;落定即撤 */
82
+ /* 回绕落定后轨道已无动画地归位:下一次翻页撤掉这个标记,过渡照常 */
83
+ [data-scope='carousel'][data-part='list'][data-snapped] {
84
+ transition: none;
85
+ }
86
+
87
+ [data-scope='carousel'][data-part='list'][data-animating] {
88
+ transition: none;
89
+ will-change: translate;
90
+ }
91
+
92
+ /* 淡变换页:条目叠进同一格,轨道不位移(连接层不写页位移)。
93
+ 当前一张压在上面淡入,离开的那一张同一段淡出、淡完才藏起——visibility 在两端之间插值时取 visible,
94
+ 过渡走到末端才落成 hidden。时长与曲线跟平移同一档:减弱动效下 slide 为 1ms,直接换 */
95
+ [data-scope='carousel'][data-part='list'][data-effect='fade']:not([hidden]) {
96
+ display: grid;
97
+ grid-template: minmax(0, 1fr) / minmax(0, 1fr);
98
+ transition: none;
99
+ }
100
+
101
+ [data-scope='carousel'][data-part='list'][data-effect='fade'] > [data-scope='carousel'][data-part='item'] {
102
+ grid-area: 1 / 1;
103
+ opacity: 0;
104
+ visibility: hidden;
105
+ transition-property: opacity, visibility;
106
+ transition-duration: var(--xh-carousel-duration, var(--xh-motion-duration-slide));
107
+ transition-timing-function: var(--xh-carousel-ease, var(--xh-motion-ease-slide));
108
+ }
109
+
110
+ [data-scope='carousel'][data-part='list'][data-effect='fade'] > [data-scope='carousel'][data-part='item'][data-inview] {
111
+ z-index: 1;
112
+ opacity: 1;
113
+ visibility: visible;
83
114
  }
84
115
 
85
116
  /* 一张幻灯片。
@@ -102,35 +133,39 @@
102
133
  /* 两端按钮与播放开关:浮在媒体之上的单图标圆钮,接 Action Control floating 档:
103
134
  盒型(md = box-lg 48px,圆形)、四态面、0.97 按压与 44px 命中区由家族配方给出,组件没有 size 轴、固定 md。
104
135
  连接层不投影 variant:面由这里桥接到磨砂缺省(使用者槽 → 磨砂面),悬停 / 按下的底走画布承载的阶梯
105
- (100 → 200),边缘与投影不动;这里只留定位、桥接槽与图标尺 */
136
+ (100 → 200,取不透明档:钮压在图上,半透明的墨色盖不住画面),边缘与投影不动;这里只留定位、桥接槽与图标尺 */
106
137
  [data-scope='carousel'][data-part='prev-trigger'],
107
138
  [data-scope='carousel'][data-part='next-trigger'],
108
139
  [data-scope='carousel'][data-part='autoplay-trigger'] {
109
- --xh-action-bg-rest: var(--xh-carousel-trigger-bg, var(--xh-_carousel-trigger-bg));
110
- --xh-action-bg-hover: var(--xh-carousel-trigger-bg-hover, var(--xh-bg-subtle));
111
- --xh-action-bg-pressed: var(--xh-carousel-trigger-bg-active, var(--xh-bg-subtle-hover));
112
- --xh-action-bg-focus-visible: var(--xh-carousel-trigger-bg, var(--xh-material-frosted-focus-surface));
113
- --xh-action-bg-disabled: var(--xh-carousel-trigger-bg, var(--xh-_carousel-trigger-bg));
114
- --xh-action-fg-rest: var(--xh-carousel-trigger-fg, var(--xh-material-frosted-fg));
115
- --xh-action-fg-hover: var(--xh-carousel-trigger-fg, var(--xh-material-frosted-fg));
116
- --xh-action-fg-pressed: var(--xh-carousel-trigger-fg, var(--xh-material-frosted-fg));
117
- --xh-action-fg-focus-visible: var(--xh-carousel-trigger-fg, var(--xh-material-frosted-fg));
118
- --xh-action-border-rest: var(--xh-carousel-trigger-border, var(--xh-_carousel-trigger-border));
119
- --xh-action-border-hover: var(--xh-carousel-trigger-border, var(--xh-_carousel-trigger-border));
120
- --xh-action-border-pressed: var(--xh-carousel-trigger-border, var(--xh-_carousel-trigger-border));
121
- --xh-action-border-focus-visible: var(--xh-carousel-trigger-border, var(--xh-_carousel-trigger-border));
122
- --xh-action-border-disabled: var(--xh-carousel-trigger-border, var(--xh-_carousel-trigger-border));
123
- --xh-action-shadow-rest: var(--xh-carousel-trigger-shadow, var(--xh-_carousel-trigger-shadow));
124
- --xh-action-shadow-hover: var(--xh-carousel-trigger-shadow-hover, var(--xh-_carousel-trigger-shadow));
125
- --xh-action-shadow-pressed: var(--xh-carousel-trigger-shadow, var(--xh-_carousel-trigger-shadow));
126
- --xh-action-shadow-focus-visible: var(--xh-carousel-trigger-shadow, var(--xh-_carousel-trigger-shadow));
127
- --xh-action-shadow-disabled: var(--xh-carousel-trigger-shadow, var(--xh-_carousel-trigger-shadow));
140
+ /* 面走材质家族配方(family/material.css):frosted 档的底、交互阶梯、描边、投影、1px 顶光与背景滤镜,
141
+ liquid 档由配方换成液态面;这里把使用者槽接到 Action Control 的桥接槽 */
142
+ --xh-action-bg-rest: var(--xh-carousel-trigger-bg, var(--xh-_material-bg));
143
+ --xh-action-bg-hover: var(--xh-carousel-trigger-bg-hover, var(--xh-_material-bg-hover));
144
+ --xh-action-bg-pressed: var(--xh-carousel-trigger-bg-active, var(--xh-_material-bg-pressed));
145
+ --xh-action-bg-focus-visible: var(--xh-carousel-trigger-bg, var(--xh-_material-bg-focus));
146
+ --xh-action-bg-disabled: var(--xh-carousel-trigger-bg, var(--xh-_material-bg));
147
+ --xh-action-fg-rest: var(--xh-carousel-trigger-fg, var(--xh-_material-fg));
148
+ --xh-action-fg-hover: var(--xh-carousel-trigger-fg, var(--xh-_material-fg));
149
+ --xh-action-fg-pressed: var(--xh-carousel-trigger-fg, var(--xh-_material-fg));
150
+ --xh-action-fg-focus-visible: var(--xh-carousel-trigger-fg, var(--xh-_material-fg));
151
+ --xh-action-border-rest: var(--xh-carousel-trigger-border, var(--xh-_material-border));
152
+ --xh-action-border-hover: var(--xh-carousel-trigger-border, var(--xh-_material-border));
153
+ --xh-action-border-pressed: var(--xh-carousel-trigger-border, var(--xh-_material-border));
154
+ --xh-action-border-focus-visible: var(--xh-carousel-trigger-border, var(--xh-_material-border));
155
+ --xh-action-border-disabled: var(--xh-carousel-trigger-border, var(--xh-_material-border));
156
+ --xh-action-shadow-rest: var(--xh-carousel-trigger-shadow, var(--xh-_material-shadow));
157
+ --xh-action-shadow-hover: var(--xh-carousel-trigger-shadow-hover, var(--xh-_material-shadow));
158
+ --xh-action-shadow-pressed: var(--xh-carousel-trigger-shadow, var(--xh-_material-shadow));
159
+ --xh-action-shadow-focus-visible: var(--xh-carousel-trigger-shadow, var(--xh-_material-shadow));
160
+ --xh-action-shadow-disabled: var(--xh-carousel-trigger-shadow, var(--xh-_material-shadow));
161
+ --xh-action-highlight-rest: var(--xh-_material-highlight);
162
+ --xh-action-highlight-hover: var(--xh-_material-highlight);
163
+ --xh-action-highlight-pressed: var(--xh-_material-highlight);
164
+ --xh-action-highlight-focus-visible: var(--xh-_material-highlight);
165
+ --xh-action-highlight-disabled: var(--xh-_material-highlight);
166
+ --xh-action-bg-hover: var(--xh-carousel-trigger-bg-hover, var(--xh-bg-subtle-opaque));
167
+ --xh-action-bg-pressed: var(--xh-carousel-trigger-bg-active, var(--xh-bg-subtle-hover-opaque));
128
168
  /* M2 顶光走配方的高光通道 */
129
- --xh-action-highlight-rest: var(--xh-material-frosted-highlight);
130
- --xh-action-highlight-hover: var(--xh-material-frosted-highlight);
131
- --xh-action-highlight-pressed: var(--xh-material-frosted-highlight);
132
- --xh-action-highlight-focus-visible: var(--xh-material-frosted-highlight);
133
- --xh-action-highlight-disabled: var(--xh-material-frosted-highlight);
134
169
  --xh-action-radius: var(--xh-carousel-trigger-radius, var(--xh-_action-profile-radius));
135
170
  --xh-action-visual-size: var(--xh-carousel-trigger-size, var(--xh-_action-profile-visual-size));
136
171
  /* 作者塞进来的图标跟着 floating 档走(md 24px),与皮肤画的兜底字形同一把尺 */
@@ -138,8 +173,6 @@
138
173
 
139
174
  position: absolute;
140
175
  z-index: 1;
141
- -webkit-backdrop-filter: var(--xh-material-frosted-backdrop);
142
- backdrop-filter: var(--xh-material-frosted-backdrop);
143
176
  }
144
177
 
145
178
  [data-scope='carousel'][data-part='prev-trigger'],
@@ -212,6 +245,28 @@
212
245
  translate: -50% 0;
213
246
  }
214
247
 
248
+ /* 起点是逻辑属性、平移是物理通道:rtl 下行内分量掉头,分页条才落回中线 */
249
+ [data-scope='carousel'][data-part='indicator-group'][data-orientation='horizontal']:dir(rtl) {
250
+ translate: 50% 0;
251
+ }
252
+
253
+ /* liquid 档:分页点托在一条液态胶囊上(不贴边的一维栏取 pill),压在任何媒体上都看得清。
254
+ 胶囊是墨色域,点的中性色随之取墨色;胶囊本身不可按,不挂按住形变 */
255
+ :where([data-material='liquid']) [data-scope='carousel'][data-part='indicator-group'][data-xh-liquid] {
256
+ padding: var(--xh-carousel-indicator-group-p, var(--xh-space-2));
257
+ border: var(--xh-stroke-thin) solid var(--xh-material-liquid-border);
258
+ border-radius: var(--xh-carousel-indicator-group-radius, var(--xh-shape-pill));
259
+ background: var(--xh-_liquid-bg);
260
+ box-shadow: var(--xh-_liquid-shadow);
261
+ -webkit-backdrop-filter: var(--xh-material-liquid-backdrop);
262
+ backdrop-filter: var(--xh-material-liquid-backdrop);
263
+ /* 翻页换到深浅不同的图上时色调翻转:底色、细线与投影一起淡变 */
264
+ transition:
265
+ background-color var(--xh-motion-duration-micro) var(--xh-motion-ease-enter),
266
+ border-color var(--xh-motion-duration-micro) var(--xh-motion-ease-enter),
267
+ box-shadow var(--xh-motion-duration-micro) var(--xh-motion-ease-enter);
268
+ }
269
+
215
270
  /* 分页点与 Tour 的步骤点同一种语言:8px 圆点,当前页拉长成 20px 胶囊并换品牌色。
216
271
  本体就是那颗点:没有文字(页码交给作者,默认不显示),底色即标记。
217
272
  悬停 / 按下的回执落在点的颜色上:中性标记按前景阶梯加深一档、再加深一档;当前页按品牌阶梯压一档 */
@@ -226,14 +281,14 @@
226
281
  padding: 0;
227
282
  border: 0;
228
283
  border-radius: var(--xh-carousel-indicator-radius, var(--xh-shape-circle));
229
- background: var(--xh-carousel-indicator-bg, var(--xh-border-default));
284
+ background: var(--xh-carousel-indicator-bg, var(--xh-bg-subtle-hover-opaque));
230
285
  font-size: 0;
231
286
  /* 自动播放的进度条画在点里,超出胶囊的那截裁掉 */
232
287
  overflow: hidden;
233
288
  cursor: pointer;
234
289
  transition:
235
- inline-size var(--xh-motion-duration-micro) var(--xh-motion-ease-continuous),
236
- block-size var(--xh-motion-duration-micro) var(--xh-motion-ease-continuous),
290
+ inline-size var(--xh-motion-duration-move) var(--xh-motion-ease-continuous),
291
+ block-size var(--xh-motion-duration-move) var(--xh-motion-ease-continuous),
237
292
  background-color var(--xh-motion-duration-micro) var(--xh-motion-ease-enter),
238
293
  scale var(--xh-motion-duration-release) var(--xh-motion-ease-release);
239
294
  }
@@ -299,7 +354,8 @@
299
354
  }
300
355
 
301
356
  /* 自动播放的进度:胶囊是品牌淡底当轨道(仍是「当前」语义;淡底上公共环够对比,不灌环色),
302
- 品牌填充条从起点沿轨道方向长满这一页的时长;暂停时定住 */
357
+ 品牌填充条从起点沿轨道方向长满这一页的时长。计时器每次恢复都重计一整个间隔,
358
+ 进度条跟它同一口径:暂停时回到起点,恢复时从头走 */
303
359
  [data-scope='carousel'][data-part='root'][data-autoplay]
304
360
  [data-scope='carousel'][data-part='indicator'][data-current],
305
361
  [data-scope='carousel'][data-part='root'][data-paused]
@@ -322,7 +378,8 @@
322
378
 
323
379
  [data-scope='carousel'][data-part='root'][data-paused]
324
380
  [data-scope='carousel'][data-part='indicator'][data-current]::before {
325
- animation-play-state: paused;
381
+ animation: none;
382
+ scale: var(--xh-_carousel-progress-from);
326
383
  }
327
384
 
328
385
  /* 纵轨:胶囊沿块轴拉长,进度条从上往下长 */
@@ -350,6 +407,17 @@
350
407
  rotate: 90deg;
351
408
  }
352
409
 
410
+ [data-scope='carousel'][data-part='root'][data-orientation='vertical']
411
+ > :is([data-part='prev-trigger'], [data-part='next-trigger']):dir(rtl) {
412
+ translate: 50% 0;
413
+ }
414
+
415
+ /* 纵轨的翻页钮整颗转了 90°,形变会跟着转到错的方向,这一档不挂 */
416
+ :where([data-material='liquid']) [data-scope='carousel'][data-part='root'][data-orientation='vertical']
417
+ > :is([data-part='prev-trigger'], [data-part='next-trigger'])[data-xh-liquid] {
418
+ transform: none;
419
+ }
420
+
353
421
  [data-scope='carousel'][data-part='root'][data-orientation='vertical']
354
422
  > [data-part='prev-trigger'] {
355
423
  inset-block-start: var(--xh-carousel-control-inset, var(--xh-space-3));
@@ -498,14 +566,19 @@
498
566
  inline-size: var(--xh-carousel-indicator-size, var(--xh-space-2));
499
567
  block-size: var(--xh-carousel-indicator-size, var(--xh-space-2));
500
568
  border-radius: var(--xh-carousel-indicator-radius, var(--xh-shape-circle));
501
- background: var(--xh-carousel-indicator-bg, var(--xh-border-default));
569
+ background: var(--xh-carousel-indicator-bg, var(--xh-bg-subtle-hover-opaque));
502
570
  translate: -50% -50%;
571
+ /* 当前点伸长是跨尺寸的换位(move),与细指针下盒子本身的伸长同一档 */
503
572
  transition:
504
- inline-size var(--xh-motion-duration-micro) var(--xh-motion-ease-continuous),
505
- block-size var(--xh-motion-duration-micro) var(--xh-motion-ease-continuous),
573
+ inline-size var(--xh-motion-duration-move) var(--xh-motion-ease-continuous),
574
+ block-size var(--xh-motion-duration-move) var(--xh-motion-ease-continuous),
506
575
  background-color var(--xh-motion-duration-micro) var(--xh-motion-ease-enter);
507
576
  }
508
577
 
578
+ [data-scope='carousel'][data-part='indicator']:dir(rtl)::after {
579
+ translate: 50% -50%;
580
+ }
581
+
509
582
  [data-scope='carousel'][data-part='indicator']:is(:active, [data-pressed]):not([data-current])::after {
510
583
  background: var(--xh-carousel-indicator-bg-active, var(--xh-fg-default));
511
584
  }
@@ -546,6 +619,13 @@
546
619
  translate: -50% -50%;
547
620
  }
548
621
 
622
+ [data-scope='carousel'][data-part='root'][data-autoplay]
623
+ [data-scope='carousel'][data-part='indicator'][data-current]:dir(rtl)::before,
624
+ [data-scope='carousel'][data-part='root'][data-paused]
625
+ [data-scope='carousel'][data-part='indicator'][data-current]:dir(rtl)::before {
626
+ translate: 50% -50%;
627
+ }
628
+
549
629
  [data-scope='carousel'][data-part='indicator-group'][data-orientation='vertical']
550
630
  > [data-scope='carousel'][data-part='indicator'][data-current]::after,
551
631
  [data-scope='carousel'][data-part='root'][data-autoplay]
@@ -558,6 +638,31 @@
558
638
  block-size: var(--xh-carousel-indicator-size-current, var(--xh-space-5));
559
639
  }
560
640
  }
641
+
642
+ @media (forced-colors: active) {
643
+ /* 兜底字形是 mask 挖出来的一块底色,这一档里底色被系统换成 Canvas,字形跟着消失。
644
+ 字形退出强制换色、直接写系统色(不能取 currentColor:退出强制换色的伪元素读到的是被系统换掉之前的作者色):
645
+ 按钮面上取 ButtonText,悬停与按下时家族把按钮涂成 Highlight、字形换 HighlightText;
646
+ 禁用取 GrayText */
647
+ [data-scope='carousel']:is([data-part='prev-trigger'], [data-part='next-trigger']):empty::before,
648
+ [data-scope='carousel'][data-part='autoplay-trigger'][data-state='running']:empty::before,
649
+ [data-scope='carousel'][data-part='autoplay-trigger'][data-state='paused']:empty::before {
650
+ forced-color-adjust: none;
651
+ background-color: ButtonText;
652
+ }
653
+
654
+ [data-scope='carousel']:is([data-part='prev-trigger'], [data-part='next-trigger']):not([data-disabled]):not([data-loading]):is(:hover, :active, [data-pressed]):empty::before,
655
+ [data-scope='carousel'][data-part='autoplay-trigger'][data-state='running']:not([data-disabled]):not([data-loading]):is(:hover, :active, [data-pressed]):empty::before,
656
+ [data-scope='carousel'][data-part='autoplay-trigger'][data-state='paused']:not([data-disabled]):not([data-loading]):is(:hover, :active, [data-pressed]):empty::before {
657
+ background-color: HighlightText;
658
+ }
659
+
660
+ [data-scope='carousel']:is([data-part='prev-trigger'], [data-part='next-trigger'])[data-disabled]:empty::before,
661
+ [data-scope='carousel'][data-part='autoplay-trigger'][data-state='running'][data-disabled]:empty::before,
662
+ [data-scope='carousel'][data-part='autoplay-trigger'][data-state='paused'][data-disabled]:empty::before {
663
+ background-color: GrayText;
664
+ }
665
+ }
561
666
  }
562
667
 
563
668
  @layer xihan.motion {