@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.
- package/CHANGELOG.md +1227 -0
- package/README.md +6 -1
- package/component-tokens.d.ts +505 -96
- package/components.tokens.json +34636 -25846
- package/css/accordion.css +34 -8
- package/css/alert.css +59 -1
- package/css/anchor.css +46 -8
- package/css/approval.css +116 -76
- package/css/avatar-group.css +1 -1
- package/css/avatar.css +13 -5
- package/css/back-top.css +61 -42
- package/css/badge.css +62 -12
- package/css/bar-code.css +1 -1
- package/css/breadcrumb.css +62 -3
- package/css/button-group.css +4 -4
- package/css/button.css +67 -19
- package/css/calendar-picker.css +19 -0
- package/css/calendar-range-picker.css +39 -2
- package/css/card.css +115 -1
- package/css/carousel.css +148 -43
- package/css/cartesian-chart.css +830 -0
- package/css/cascader.css +181 -65
- package/css/checkbox-group.css +59 -89
- package/css/checkbox.css +16 -49
- package/css/citation.css +470 -0
- package/css/clipboard.css +20 -63
- package/css/code-view.css +101 -6
- package/css/collapsible.css +34 -8
- package/css/color-field.css +18 -0
- package/css/color-picker.css +55 -58
- package/css/color-slider.css +22 -15
- package/css/color-swatch-picker.css +3 -1
- package/css/combobox.css +80 -33
- package/css/command.css +45 -43
- package/css/context-menu.css +39 -22
- package/css/date-field.css +23 -0
- package/css/date-picker.css +57 -22
- package/css/date-range-picker.css +301 -12
- package/css/description.css +17 -1
- package/css/descriptions.css +42 -0
- package/css/dialog.css +94 -36
- package/css/diff-view.css +97 -12
- package/css/download-trigger.css +44 -78
- package/css/drawer.css +160 -119
- package/css/editable.css +19 -0
- package/css/empty-state.css +7 -6
- package/css/field-array.css +36 -0
- package/css/field.css +16 -18
- package/css/file-upload.css +125 -135
- package/css/flex.css +324 -8
- package/css/float-button.css +165 -38
- package/css/floating-panel.css +53 -19
- package/css/form.css +23 -17
- package/css/funnel-chart.css +106 -0
- package/css/graph-chart.css +205 -0
- package/css/grid-list.css +235 -0
- package/css/grid.css +252 -1
- package/css/heatmap.css +119 -36
- package/css/hierarchy-chart.css +298 -0
- package/css/hover-card.css +31 -14
- package/css/icon.css +100 -0
- package/css/image-cropper.css +33 -7
- package/css/image-viewer.css +167 -22
- package/css/image.css +23 -4
- package/css/input-group.css +11 -13
- package/css/json-viewer.css +50 -2
- package/css/layout.css +68 -18
- package/css/liquid.css +106 -0
- package/css/list.css +1 -1
- package/css/listbox.css +46 -6
- package/css/loading-bar.css +27 -13
- package/css/log.css +129 -33
- package/css/markdown-stream.css +1 -1
- package/css/marquee.css +163 -7
- package/css/matrix-code.css +1 -1
- package/css/mention.css +35 -19
- package/css/menu.css +35 -21
- package/css/menubar.css +36 -20
- package/css/message-feed.css +172 -51
- package/css/navigation-menu.css +172 -11
- package/css/notification.css +429 -108
- package/css/number-field.css +22 -0
- package/css/page-header.css +3 -1
- package/css/pagination.css +126 -24
- package/css/password-input.css +40 -8
- package/css/pie-chart.css +247 -0
- package/css/popconfirm.css +44 -50
- package/css/popover.css +50 -14
- package/css/progress.css +308 -10
- package/css/prompt-input.css +36 -0
- package/css/question-flow.css +97 -57
- package/css/radar-chart.css +233 -0
- package/css/radio-group.css +363 -5
- package/css/rating.css +21 -23
- package/css/reasoning.css +61 -54
- package/css/resizable.css +6 -1
- package/css/sankey-chart.css +174 -0
- package/css/scroll-area.css +32 -0
- package/css/scrollbar.css +1 -1
- package/css/select.css +74 -55
- package/css/side-nav.css +173 -24
- package/css/signature-pad.css +16 -1
- package/css/skeleton.css +13 -14
- package/css/slider.css +35 -13
- package/css/sortable.css +37 -7
- package/css/sparkline.css +164 -0
- package/css/spinner.css +50 -22
- package/css/splitter.css +7 -1
- package/css/statistic.css +10 -0
- package/css/steps.css +248 -29
- package/css/switch.css +23 -48
- package/css/table.css +158 -118
- package/css/tabs.css +231 -19
- package/css/tag-group.css +27 -3
- package/css/tag.css +53 -12
- package/css/tags-input.css +40 -3
- package/css/text-field.css +19 -0
- package/css/time-field.css +20 -1
- package/css/time-picker.css +44 -15
- package/css/time-range-picker.css +45 -16
- package/css/timeline.css +1 -1
- package/css/toggle-group.css +4 -4
- package/css/toggle.css +4 -3
- package/css/tool-call.css +59 -51
- package/css/toolbar.css +101 -3
- package/css/tooltip.css +15 -2
- package/css/tour.css +42 -12
- package/css/transfer.css +98 -75
- package/css/tree-select.css +232 -53
- package/css/tree.css +201 -55
- package/css/truncate.css +55 -12
- package/css/typography.css +93 -0
- package/css/virtualizer.css +56 -0
- package/css/watermark.css +23 -0
- package/family/action-control.css +14 -5
- package/family/chart.css +480 -0
- package/family/check-mark.css +94 -0
- package/family/choice-card.css +97 -0
- package/family/collection-item.css +9 -15
- package/family/field-chrome.css +1 -12
- package/family/loading-ring.css +95 -0
- package/family/material.css +72 -0
- package/family/menu-choice.css +56 -0
- package/family/motion.css +207 -10
- package/family/tag-list.css +59 -0
- package/index.css +22997 -13678
- package/index.unlayered.css +12928 -3605
- package/package.json +20 -8
- package/css/gradient-text.css +0 -91
- package/css/icon-wrapper.css +0 -81
- package/css/segmented.css +0 -280
- package/css/toast.css +0 -499
package/css/accordion.css
CHANGED
|
@@ -184,8 +184,12 @@
|
|
|
184
184
|
flex: none;
|
|
185
185
|
color: var(--xh-accordion-indicator-fg, var(--xh-fg-muted));
|
|
186
186
|
line-height: var(--xh-leading-none);
|
|
187
|
-
|
|
188
|
-
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
/* 指示器与正文同档转向:收起时取 collapse 档,展开时(下面的打开态)取 expand 档。
|
|
190
|
+
首帧就在的朝向直接呈现(data-instant),第一次开合起才转 */
|
|
191
|
+
[data-scope='accordion'][data-part='indicator']:not([data-instant]) {
|
|
192
|
+
transition: rotate var(--xh-motion-duration-collapse) var(--xh-motion-ease-enter-strong);
|
|
189
193
|
}
|
|
190
194
|
|
|
191
195
|
/* 没写内容就由皮肤画;作者往部件里塞了自己的图形,这条规则即不命中 */
|
|
@@ -204,6 +208,10 @@
|
|
|
204
208
|
rotate: 180deg;
|
|
205
209
|
}
|
|
206
210
|
|
|
211
|
+
[data-scope='accordion'][data-part='indicator'][data-state='open']:not([data-instant]) {
|
|
212
|
+
transition: rotate var(--xh-motion-duration-expand) var(--xh-motion-ease-enter-strong);
|
|
213
|
+
}
|
|
214
|
+
|
|
207
215
|
/* 这里刻意没有 [data-part='content'][hidden] { display: none }:补了动画一帧都播不出来。
|
|
208
216
|
收起由适配器在退场结束后写内联 display 落成,退场窗口内靠 connect 发的 inert 挡住焦点 */
|
|
209
217
|
[data-scope='accordion'][data-part='content'] {
|
|
@@ -221,14 +229,32 @@
|
|
|
221
229
|
line-height: var(--xh-leading-normal);
|
|
222
230
|
}
|
|
223
231
|
|
|
224
|
-
/*
|
|
225
|
-
[data-scope='accordion'][data-part='content'][data-state='open'] {
|
|
226
|
-
|
|
227
|
-
|
|
232
|
+
/* 展开与收起只在开合时播:首帧就在的展开 / 收起直接呈现(data-instant) */
|
|
233
|
+
[data-scope='accordion'][data-part='content'][data-state='open']:not([data-instant]) {
|
|
234
|
+
animation: xh-disclosure-expand var(--xh-motion-duration-expand) var(--xh-motion-ease-enter-strong);
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
[data-scope='accordion'][data-part='content'][data-state='closed']:not([data-instant]) {
|
|
238
|
+
animation: xh-disclosure-collapse var(--xh-motion-duration-collapse) var(--xh-motion-ease-exit) forwards;
|
|
228
239
|
}
|
|
229
240
|
|
|
230
|
-
|
|
231
|
-
|
|
241
|
+
@media (forced-colors: active) {
|
|
242
|
+
/* 兜底字形是 mask 挖出来的一块底色,这一档里底色被系统换成 Canvas,字形跟着消失。
|
|
243
|
+
字形退出强制换色、直接写系统色(不能取 currentColor:退出强制换色的伪元素读到的是被系统换掉之前的作者色):
|
|
244
|
+
按钮面上取 ButtonText,悬停与按下时家族把按钮涂成 Highlight、字形换 HighlightText;
|
|
245
|
+
禁用取 GrayText */
|
|
246
|
+
[data-scope='accordion'][data-part='indicator']:empty::before {
|
|
247
|
+
forced-color-adjust: none;
|
|
248
|
+
background-color: ButtonText;
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
[data-scope='accordion'][data-part='trigger']:not([data-disabled]):not([data-loading]):is(:hover, :active, [data-pressed]) [data-scope='accordion'][data-part='indicator']:empty::before {
|
|
252
|
+
background-color: HighlightText;
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
[data-scope='accordion'][data-part='trigger'][data-disabled] [data-scope='accordion'][data-part='indicator']:empty::before {
|
|
256
|
+
background-color: GrayText;
|
|
257
|
+
}
|
|
232
258
|
}
|
|
233
259
|
}
|
|
234
260
|
|
package/css/alert.css
CHANGED
|
@@ -7,6 +7,23 @@
|
|
|
7
7
|
|
|
8
8
|
/* Alert 独立皮肤同时传递引入关闭钮的动作控件配方;full bundle 递归去重。 */
|
|
9
9
|
@import '../family/action-control.css';
|
|
10
|
+
/* 淡出的关键帧由 family/motion.css 提供,本皮肤 @import 它,单独引入仍成立。 */
|
|
11
|
+
@import '../family/motion.css';
|
|
12
|
+
|
|
13
|
+
@layer xihan.motion {
|
|
14
|
+
/* 关闭时收起占位:从连接层量下的整块高度收到 0,内缩与描边一起收掉 */
|
|
15
|
+
@keyframes xh-alert-collapse {
|
|
16
|
+
from {
|
|
17
|
+
block-size: var(--xh-_alert-exit-block-size);
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
to {
|
|
21
|
+
block-size: 0;
|
|
22
|
+
padding-block: 0;
|
|
23
|
+
border-block-width: 0;
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
}
|
|
10
27
|
|
|
11
28
|
@layer xihan.components {
|
|
12
29
|
/* 皮肤在场的标记:开发模式下按 scope 探一次,取不到就说明这份皮肤没被引入。 */
|
|
@@ -22,7 +39,8 @@
|
|
|
22
39
|
|
|
23
40
|
display: flex;
|
|
24
41
|
align-items: flex-start;
|
|
25
|
-
|
|
42
|
+
/* 指示符盒自带 --xh-space-1 内衬:与间距合起来,字形到正文 12px,与 Notification 同一个距离 */
|
|
43
|
+
gap: var(--xh-alert-gap, var(--xh-space-2));
|
|
26
44
|
padding-block: var(--xh-alert-py, var(--xh-surface-py-sm));
|
|
27
45
|
padding-inline: var(--xh-alert-px, var(--xh-surface-px-sm));
|
|
28
46
|
border: var(--xh-stroke-thin) solid var(--xh-alert-border, var(--xh-border-default));
|
|
@@ -34,6 +52,27 @@
|
|
|
34
52
|
line-height: var(--xh-alert-leading, var(--xh-leading-normal));
|
|
35
53
|
}
|
|
36
54
|
|
|
55
|
+
/* 横幅:页面顶部的通栏,贴着页面或容器的边铺满整行。贴边的三条边是页面自己的边,画出来只会压在边上;
|
|
56
|
+
边界只留朝向页面内容的块尾一道,与页面内容同一层、同一种描边。贴边铺满的栏不取圆角:
|
|
57
|
+
圆了会在两个角露出底下的页面。面与语气规则与页内提示相同,横幅不换底色 */
|
|
58
|
+
[data-scope='alert'][data-part='root'][data-banner] {
|
|
59
|
+
inline-size: 100%;
|
|
60
|
+
border-block-start-width: 0;
|
|
61
|
+
border-inline-width: 0;
|
|
62
|
+
border-radius: 0;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
/* 关闭的退场:先淡出,再把占位收起——下面的内容跟着一路平移上来,而不是整块跳上来。
|
|
66
|
+
收占位接在淡出之后(延迟一个 exit),播完连接层才写 hidden。收起态常挂 hidden,这条只在退场途中命中;
|
|
67
|
+
减弱动效下收占位瞬时完成,淡出照常 */
|
|
68
|
+
[data-scope='alert'][data-part='root'][data-state='closed'] {
|
|
69
|
+
box-sizing: border-box;
|
|
70
|
+
overflow: hidden;
|
|
71
|
+
animation:
|
|
72
|
+
xh-fade-out var(--xh-motion-duration-exit) var(--xh-motion-ease-exit) forwards,
|
|
73
|
+
xh-alert-collapse var(--xh-motion-duration-collapse) var(--xh-motion-ease-exit) var(--xh-motion-duration-exit) forwards;
|
|
74
|
+
}
|
|
75
|
+
|
|
37
76
|
/* 收起态连接层给的是 hidden 属性,而上面声明了 display——
|
|
38
77
|
漏掉这条,关掉的提示还会一直摊在页面上 */
|
|
39
78
|
[data-scope='alert'][data-part='root'][hidden] {
|
|
@@ -186,4 +225,23 @@
|
|
|
186
225
|
[data-scope='alert'][data-part='action'][hidden] {
|
|
187
226
|
display: none;
|
|
188
227
|
}
|
|
228
|
+
|
|
229
|
+
@media (forced-colors: active) {
|
|
230
|
+
/* 兜底字形是 mask 挖出来的一块底色,这一档里底色被系统换成 Canvas,字形跟着消失。
|
|
231
|
+
字形退出强制换色、直接写系统色(不能取 currentColor:退出强制换色的伪元素读到的是被系统换掉之前的作者色):
|
|
232
|
+
按钮面上取 ButtonText,悬停与按下时家族把按钮涂成 Highlight、字形换 HighlightText;
|
|
233
|
+
禁用取 GrayText */
|
|
234
|
+
[data-scope='alert'][data-part='close-trigger']:empty::before {
|
|
235
|
+
forced-color-adjust: none;
|
|
236
|
+
background-color: ButtonText;
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
[data-scope='alert'][data-part='close-trigger']:not([data-disabled]):not([data-loading]):is(:hover, :active, [data-pressed]):empty::before {
|
|
240
|
+
background-color: HighlightText;
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
[data-scope='alert'][data-part='close-trigger'][data-disabled]:empty::before {
|
|
244
|
+
background-color: GrayText;
|
|
245
|
+
}
|
|
246
|
+
}
|
|
189
247
|
}
|
package/css/anchor.css
CHANGED
|
@@ -127,21 +127,32 @@
|
|
|
127
127
|
overflow: hidden;
|
|
128
128
|
}
|
|
129
129
|
|
|
130
|
-
/*
|
|
131
|
-
|
|
130
|
+
/* 当前链接的四个几何量由机器量好、连接层写成私有槽 --xh-_anchor-indicator-x / -y / -w / -h
|
|
131
|
+
(它量得到,样式表量不到);这里按排布取主轴那两支,落点交给 translate(只走合成),
|
|
132
|
+
另管交叉轴的贴边与粗细,以及长什么样。它是可选部件——不渲染它时,
|
|
132
133
|
当前那一节的链接自画一条同规格的静态线(见下) */
|
|
133
134
|
[data-scope='anchor'][data-part='indicator'] {
|
|
135
|
+
/* 还没量到时的落点,量到即被机器写的私有槽盖过 */
|
|
136
|
+
--xh-_anchor-indicator-x: 0;
|
|
137
|
+
--xh-_anchor-indicator-y: 0;
|
|
138
|
+
--xh-_anchor-indicator-w: 0;
|
|
139
|
+
--xh-_anchor-indicator-h: 0;
|
|
140
|
+
--xh-_anchor-indicator-stretch: 0;
|
|
141
|
+
|
|
134
142
|
position: absolute;
|
|
135
143
|
display: block;
|
|
136
144
|
/* 指示条也是列表项,宿主给 li 的外边距会把绝对定位的它推离条目 */
|
|
137
145
|
margin: 0;
|
|
146
|
+
inset-block-start: 0;
|
|
138
147
|
inset-inline-start: calc(var(--xh-anchor-indicator-thickness, var(--xh-stroke-thick)) * -1);
|
|
139
148
|
inline-size: var(--xh-anchor-indicator-thickness, var(--xh-stroke-thick));
|
|
149
|
+
block-size: var(--xh-_anchor-indicator-h);
|
|
140
150
|
border-radius: var(--xh-anchor-indicator-radius, var(--xh-shape-pill));
|
|
141
151
|
background: var(--xh-anchor-indicator-color, var(--xh-_anchor-accent));
|
|
152
|
+
translate: 0 var(--xh-_anchor-indicator-y);
|
|
142
153
|
transition:
|
|
143
|
-
|
|
144
|
-
block-size var(--xh-motion-duration-
|
|
154
|
+
translate var(--xh-motion-duration-move) var(--xh-motion-ease-continuous),
|
|
155
|
+
block-size var(--xh-motion-duration-move) var(--xh-motion-ease-continuous);
|
|
145
156
|
}
|
|
146
157
|
|
|
147
158
|
/* display 会盖掉 hidden 属性的 UA 规则,无激活项时显式让位 */
|
|
@@ -151,13 +162,40 @@
|
|
|
151
162
|
|
|
152
163
|
/* 横排:指示条改躺在底边的轨道上,交叉轴换成块轴 */
|
|
153
164
|
[data-scope='anchor'][data-part='indicator'][data-orientation='horizontal'] {
|
|
154
|
-
inset-
|
|
165
|
+
inset-block-start: auto;
|
|
166
|
+
inset-inline-start: 0;
|
|
155
167
|
inset-block-end: calc(var(--xh-anchor-indicator-thickness, var(--xh-stroke-thick)) * -1);
|
|
156
|
-
inline-size:
|
|
168
|
+
inline-size: var(--xh-_anchor-indicator-w);
|
|
157
169
|
block-size: var(--xh-anchor-indicator-thickness, var(--xh-stroke-thick));
|
|
170
|
+
translate: var(--xh-_anchor-indicator-x) 0;
|
|
158
171
|
transition:
|
|
159
|
-
|
|
160
|
-
inline-size var(--xh-motion-duration-
|
|
172
|
+
translate var(--xh-motion-duration-move) var(--xh-motion-ease-continuous),
|
|
173
|
+
inline-size var(--xh-motion-duration-move) var(--xh-motion-ease-continuous);
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
/* translate 只认物理方向:RTL 下行首在右边,起始缘量出的距离往左推 */
|
|
177
|
+
[data-scope='anchor'][data-part='indicator'][data-orientation='horizontal']:dir(rtl) {
|
|
178
|
+
translate: calc(-1 * var(--xh-_anchor-indicator-x)) 0;
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
/* 首次落位与同一项的重量(窗口缩放、换上正式字体)直接到位,只有换项才滑:连接层在这一落点投影
|
|
182
|
+
data-instant。写在排布那几条之后,同一特异性按先后压过它们单写的过渡 */
|
|
183
|
+
[data-scope='anchor'][data-part='indicator'][data-instant] {
|
|
184
|
+
transition: none;
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
/* 液态档:两沿由弹簧逐帧推着走(连接层每一帧写好盒子),几何量不再补过渡;
|
|
188
|
+
被拉长时在另一个方向上压扁(竖排缺省压行向,横排压块向),表达体积守恒,拉长到目标的两倍时压到 --xh-motion-scale-squash */
|
|
189
|
+
:where([data-material='liquid']) [data-scope='anchor'][data-part='indicator'] {
|
|
190
|
+
--xh-_anchor-indicator-squash: max(var(--xh-motion-scale-squash), calc(1 - var(--xh-_anchor-indicator-stretch) * (1 - var(--xh-motion-scale-squash))));
|
|
191
|
+
|
|
192
|
+
scale: var(--xh-_anchor-indicator-squash) 1;
|
|
193
|
+
transition: none;
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
:where([data-material='liquid']) [data-scope='anchor'][data-part='indicator'][data-orientation='horizontal'] {
|
|
197
|
+
scale: 1 var(--xh-_anchor-indicator-squash);
|
|
198
|
+
transition: none;
|
|
161
199
|
}
|
|
162
200
|
|
|
163
201
|
/* 目录里没放 indicator 部件时,当前那一节的链接自画一条静态指示线(导航当前页):
|
package/css/approval.css
CHANGED
|
@@ -5,44 +5,11 @@
|
|
|
5
5
|
|
|
6
6
|
/* 定义 approval 样式。 */
|
|
7
7
|
|
|
8
|
+
/* 共享关键帧由 family/motion.css 提供,本皮肤 @import 它,单独引入仍成立。 */
|
|
9
|
+
@import '../family/motion.css';
|
|
8
10
|
/* 独立皮肤同时传递引入授权行与两颗钮的动作控件配方,full bundle 递归去重。 */
|
|
9
11
|
@import '../family/action-control.css';
|
|
10
|
-
|
|
11
|
-
@layer xihan.motion {
|
|
12
|
-
/* 动画名的查找只认「文档里有没有这个名字」:引用别处文件里的名字,那份文件不一定在场,
|
|
13
|
-
动画会静默地整个不跑。每份皮肤都能单独引入,所以它用到的关键帧都写在自己身上。 */
|
|
14
|
-
|
|
15
|
-
/* 幅度走令牌,减弱动效时由令牌层归零;位移用独立属性而非 transform 简写 */
|
|
16
|
-
@keyframes xh-approval-in {
|
|
17
|
-
from {
|
|
18
|
-
opacity: 0;
|
|
19
|
-
translate: 0 var(--xh-motion-distance-md);
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
to {
|
|
23
|
-
opacity: 1;
|
|
24
|
-
translate: 0 0;
|
|
25
|
-
}
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
@keyframes xh-approval-result-in {
|
|
29
|
-
from {
|
|
30
|
-
opacity: 0;
|
|
31
|
-
scale: var(--xh-motion-scale-enter);
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
to {
|
|
35
|
-
opacity: 1;
|
|
36
|
-
scale: 1;
|
|
37
|
-
}
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
@keyframes xh-approval-rotate {
|
|
41
|
-
to {
|
|
42
|
-
rotate: 360deg;
|
|
43
|
-
}
|
|
44
|
-
}
|
|
45
|
-
}
|
|
12
|
+
@import '../family/loading-ring.css';
|
|
46
13
|
|
|
47
14
|
@layer xihan.components {
|
|
48
15
|
/* 皮肤在场的标记:开发模式下按 scope 探一次,取不到就说明这份皮肤没被引入。 */
|
|
@@ -66,6 +33,8 @@
|
|
|
66
33
|
--xh-_approval-item-font-size: var(--xh-control-font-md);
|
|
67
34
|
--xh-_approval-note-font-size: var(--xh-control-font-md);
|
|
68
35
|
|
|
36
|
+
/* 定位基准:待决的呼吸点钉在右上角 */
|
|
37
|
+
position: relative;
|
|
69
38
|
display: flex;
|
|
70
39
|
flex-direction: column;
|
|
71
40
|
gap: var(--xh-approval-gap, var(--xh-_approval-gap));
|
|
@@ -74,8 +43,13 @@
|
|
|
74
43
|
border-radius: var(--xh-approval-radius, var(--xh-shape-surface));
|
|
75
44
|
background: var(--xh-approval-bg, var(--xh-bg-surface));
|
|
76
45
|
box-shadow: var(--xh-approval-shadow, none);
|
|
77
|
-
|
|
78
|
-
|
|
46
|
+
/* 判定落定时描边随语气换色:属状态换色,与别处悬停、选中、校验的换色同一档 */
|
|
47
|
+
transition: border-color var(--xh-motion-duration-micro) var(--xh-motion-ease-enter);
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
/* 卡片出现时滑入;落在首帧就在的列表条目里(历史消息)时直接呈现,不跟着整屏一起入场 */
|
|
51
|
+
[data-scope='approval'][data-part='root']:not([data-scope][data-part='item'][data-instant] *) {
|
|
52
|
+
animation: xh-item-in var(--xh-motion-duration-enter) var(--xh-motion-ease-enter-strong);
|
|
79
53
|
}
|
|
80
54
|
|
|
81
55
|
/* 上面声明的 display 会盖掉 UA 的 [hidden]{display:none},这里补回 */
|
|
@@ -83,6 +57,48 @@
|
|
|
83
57
|
display: none;
|
|
84
58
|
}
|
|
85
59
|
|
|
60
|
+
/* 待决的呼吸点:钉在右上角(RTL 下左上),不占作者排的版面;颜色随语气,没写语气时取警示色。
|
|
61
|
+
呼吸只表达「正在进行、需要被察觉」:明暗与缩放的起伏持续到判定落定,外扩光环同周期播 3 轮后停下;
|
|
62
|
+
判过了连接层就收起它,由结果那一格接着表达 */
|
|
63
|
+
[data-scope='approval'][data-part='pending-indicator'] {
|
|
64
|
+
position: absolute;
|
|
65
|
+
inset-block-start: var(--xh-approval-p, var(--xh-_approval-p));
|
|
66
|
+
inset-inline-end: var(--xh-approval-p, var(--xh-_approval-p));
|
|
67
|
+
inline-size: var(--xh-approval-pending-indicator-size, var(--xh-space-2));
|
|
68
|
+
block-size: var(--xh-approval-pending-indicator-size, var(--xh-space-2));
|
|
69
|
+
border-radius: var(--xh-approval-pending-indicator-radius, var(--xh-shape-circle));
|
|
70
|
+
background: var(--xh-approval-pending-indicator-color, var(--xh-_tone, var(--xh-fg-warning)));
|
|
71
|
+
animation: xh-breathe var(--xh-motion-loop-breathe) var(--xh-motion-ease-breathe) infinite;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
[data-scope='approval'][data-part='pending-indicator']::after {
|
|
75
|
+
content: '';
|
|
76
|
+
position: absolute;
|
|
77
|
+
inset: 0;
|
|
78
|
+
border-radius: inherit;
|
|
79
|
+
background: inherit;
|
|
80
|
+
opacity: 0;
|
|
81
|
+
pointer-events: none;
|
|
82
|
+
animation: xh-breathe-halo var(--xh-motion-loop-breathe) var(--xh-motion-ease-breathe) 3;
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
/* 减弱动效:两者都停,圆点停在满不透明度,光环不出现 */
|
|
86
|
+
@media (prefers-reduced-motion: reduce) {
|
|
87
|
+
[data-scope='approval'][data-part='pending-indicator'],
|
|
88
|
+
[data-scope='approval'][data-part='pending-indicator']::after {
|
|
89
|
+
animation: none;
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
:where([data-motion='reduce']) [data-scope='approval'][data-part='pending-indicator'],
|
|
94
|
+
:where([data-motion='reduce']) [data-scope='approval'][data-part='pending-indicator']::after {
|
|
95
|
+
animation: none;
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
[data-scope='approval'][data-part='pending-indicator'][hidden] {
|
|
99
|
+
display: none;
|
|
100
|
+
}
|
|
101
|
+
|
|
86
102
|
/* 语气只染描边:作者定的强调,待决时把这块面从正文里提出来 */
|
|
87
103
|
[data-scope='approval'][data-part='root'][data-tone] {
|
|
88
104
|
border-color: var(--xh-approval-border, var(--xh-_tone, var(--xh-border-default)));
|
|
@@ -198,7 +214,7 @@
|
|
|
198
214
|
inline-size: var(--xh-approval-indicator-size, var(--xh-control-indicator-size));
|
|
199
215
|
block-size: var(--xh-approval-indicator-size, var(--xh-control-indicator-size));
|
|
200
216
|
transition:
|
|
201
|
-
background var(--xh-motion-duration-micro) var(--xh-motion-ease-enter),
|
|
217
|
+
background-color var(--xh-motion-duration-micro) var(--xh-motion-ease-enter),
|
|
202
218
|
border-color var(--xh-motion-duration-micro) var(--xh-motion-ease-enter),
|
|
203
219
|
color var(--xh-motion-duration-micro) var(--xh-motion-ease-enter);
|
|
204
220
|
}
|
|
@@ -272,6 +288,13 @@
|
|
|
272
288
|
color: var(--xh-fg-disabled);
|
|
273
289
|
}
|
|
274
290
|
|
|
291
|
+
/* 要求写理由而空着就按了拒绝:描边换成无效色;焦点也已带到这里,焦点环压在描边外面,一并换色 */
|
|
292
|
+
[data-scope='approval'][data-part='note'][data-invalid] {
|
|
293
|
+
--xh-_ring-color: var(--xh-approval-note-ring-invalid, var(--xh-ring-invalid));
|
|
294
|
+
|
|
295
|
+
border-color: var(--xh-approval-note-border-invalid, var(--xh-border-invalid));
|
|
296
|
+
}
|
|
297
|
+
|
|
275
298
|
/* 剩余时间:等宽数字,逐秒跳字时不左右晃 */
|
|
276
299
|
[data-scope='approval'][data-part='timer'] {
|
|
277
300
|
display: block;
|
|
@@ -289,25 +312,31 @@
|
|
|
289
312
|
display: inline-flex;
|
|
290
313
|
align-self: flex-start;
|
|
291
314
|
align-items: center;
|
|
292
|
-
gap: var(--xh-approval-result-gap, var(--xh-space-
|
|
293
|
-
padding-inline: var(--xh-approval-result-px, var(--xh-space-
|
|
294
|
-
padding-block: var(--xh-approval-result-py, var(--xh-space-
|
|
315
|
+
gap: var(--xh-approval-result-gap, var(--xh-space-1));
|
|
316
|
+
padding-inline: var(--xh-approval-result-px, var(--xh-space-1_5));
|
|
317
|
+
padding-block: var(--xh-approval-result-py, var(--xh-space-0_5));
|
|
318
|
+
border: var(--xh-stroke-thin) solid transparent;
|
|
295
319
|
border-radius: var(--xh-approval-result-radius, var(--xh-shape-pill));
|
|
296
|
-
background: var(--xh-approval-result-bg,
|
|
297
|
-
color: var(--xh-approval-result-fg, var(--xh-fg
|
|
320
|
+
background: var(--xh-approval-result-bg, var(--xh-_tone-subtle));
|
|
321
|
+
color: var(--xh-approval-result-fg, var(--xh-_tone-fg));
|
|
298
322
|
font-size: var(--xh-approval-result-font-size, var(--xh-text-caption-size));
|
|
299
|
-
font-weight: var(--xh-approval-result-font-weight, var(--xh-
|
|
300
|
-
|
|
323
|
+
font-weight: var(--xh-approval-result-font-weight, var(--xh-font-weight-medium));
|
|
324
|
+
line-height: var(--xh-control-indicator-md);
|
|
325
|
+
}
|
|
326
|
+
|
|
327
|
+
/* 落定结果弹出;落在首帧就在的列表条目里(历史消息)时直接呈现,不跟着整屏一起入场 */
|
|
328
|
+
[data-scope='approval'][data-part='result']:not([data-scope][data-part='item'][data-instant] *) {
|
|
329
|
+
animation: xh-pop-in var(--xh-motion-duration-enter) var(--xh-motion-ease-enter-strong);
|
|
301
330
|
}
|
|
302
331
|
|
|
303
332
|
[data-scope='approval'][data-part='result'][hidden] {
|
|
304
333
|
display: none;
|
|
305
334
|
}
|
|
306
335
|
|
|
307
|
-
/*
|
|
336
|
+
/* 超时按拒绝收口,两者同档(连接层同投 danger 语气):视觉上不该看着像第三种结果 */
|
|
308
337
|
[data-scope='approval'][data-part='result']:is([data-state='denied'], [data-state='expired']) {
|
|
309
|
-
background: var(--xh-approval-result-bg-denied,
|
|
310
|
-
color: var(--xh-approval-result-fg-denied, var(--xh-fg
|
|
338
|
+
background: var(--xh-approval-result-bg-denied, var(--xh-_tone-subtle));
|
|
339
|
+
color: var(--xh-approval-result-fg-denied, var(--xh-_tone-fg));
|
|
311
340
|
}
|
|
312
341
|
|
|
313
342
|
/* 动作行:两颗按钮靠右排,间距归库管。
|
|
@@ -397,35 +426,17 @@
|
|
|
397
426
|
圆环挂在这一行上而不是某一颗钮上:连接层只拿到「有一条判定在途」,
|
|
398
427
|
拿不到是哪一颗按下的,画在两颗钮上会有一颗在说假话 */
|
|
399
428
|
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
/* 圆环那一枚跟着两颗钮的字号走,不跟页面的:download-trigger 与 clipboard 的圆环
|
|
405
|
-
1em 量的都是它所在那颗钮,这里的宿主是整行,不锁字号就会比按钮上的大一圈 */
|
|
406
|
-
font-size: var(--xh-approval-action-font-size, var(--xh-text-label-size));
|
|
407
|
-
inline-size: 1em;
|
|
408
|
-
block-size: 1em;
|
|
409
|
-
border: var(--xh-stroke-thin) solid transparent;
|
|
410
|
-
border-block-start-color: currentColor;
|
|
411
|
-
border-radius: var(--xh-shape-circle);
|
|
412
|
-
animation: xh-approval-rotate var(--xh-approval-loading-duration, var(--xh-spin-duration)) var(--xh-motion-ease-loop) infinite;
|
|
413
|
-
}
|
|
414
|
-
|
|
415
|
-
/* 减少动效:圆环停下并整圈换成虚线,静止的形状仍然读得出"还没好"。
|
|
416
|
-
两条规则是同一件事的两个触发条件:系统偏好与作者打的 data-motion */
|
|
417
|
-
@media (prefers-reduced-motion: reduce) {
|
|
418
|
-
[data-scope='approval'][data-part='root'][data-loading] [data-scope='approval'][data-part='footer']::before {
|
|
419
|
-
border-style: dotted;
|
|
420
|
-
border-color: currentColor;
|
|
421
|
-
animation: none;
|
|
422
|
-
}
|
|
429
|
+
/* 环由加载环配方画在这一行的 ::before 上(连接层投影 data-xh-loading-ring 与 data-loading),
|
|
430
|
+
随在途淡入淡出、转与停;直径取所在尺寸档的图标档,转速认使用者槽 */
|
|
431
|
+
[data-scope='approval'][data-part='footer'] {
|
|
432
|
+
--xh-_loading-ring-duration: var(--xh-approval-loading-duration, var(--xh-motion-loop-spin));
|
|
423
433
|
}
|
|
424
434
|
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
435
|
+
[data-scope='approval'][data-part='footer']::before {
|
|
436
|
+
content: '';
|
|
437
|
+
flex: none;
|
|
438
|
+
inline-size: var(--xh-_approval-icon-size);
|
|
439
|
+
block-size: var(--xh-_approval-icon-size);
|
|
429
440
|
}
|
|
430
441
|
|
|
431
442
|
/* 尺寸档改内衬、间距、按钮高度、行内字号与图标档 */
|
|
@@ -458,4 +469,33 @@
|
|
|
458
469
|
--xh-_approval-item-font-size: var(--xh-control-font-lg);
|
|
459
470
|
--xh-_approval-note-font-size: var(--xh-control-font-lg);
|
|
460
471
|
}
|
|
472
|
+
|
|
473
|
+
/* 强制色:底色会被系统背景吃掉,呼吸点改用系统前景色 */
|
|
474
|
+
@media (forced-colors: active) {
|
|
475
|
+
[data-scope='approval'][data-part='pending-indicator'] {
|
|
476
|
+
background: CanvasText;
|
|
477
|
+
}
|
|
478
|
+
}
|
|
479
|
+
|
|
480
|
+
@media print {
|
|
481
|
+
/* 打印:待决的呼吸点是一瞬间的状态,纸上没有「等着人来判」 */
|
|
482
|
+
[data-scope='approval'][data-part='pending-indicator'] {
|
|
483
|
+
display: none;
|
|
484
|
+
}
|
|
485
|
+
}
|
|
486
|
+
|
|
487
|
+
@media (forced-colors: active) {
|
|
488
|
+
/* 兜底字形是 mask 挖出来的一块底色,这一档里底色被系统换成 Canvas,字形跟着消失。
|
|
489
|
+
字形退出强制换色、直接写系统色(不能取 currentColor:退出强制换色的伪元素读到的是被系统换掉之前的作者色):
|
|
490
|
+
落在勾选盒自己的实心面上(这一档里是 Canvas),整行悬停不换面,取 CanvasText;
|
|
491
|
+
禁用取 GrayText */
|
|
492
|
+
[data-scope='approval'][data-part='item-indicator']:not([data-state='unchecked']):empty::before {
|
|
493
|
+
forced-color-adjust: none;
|
|
494
|
+
background-color: CanvasText;
|
|
495
|
+
}
|
|
496
|
+
|
|
497
|
+
[data-scope='approval'][data-part='item'][data-disabled] [data-scope='approval'][data-part='item-indicator']:not([data-state='unchecked']):empty::before {
|
|
498
|
+
background-color: GrayText;
|
|
499
|
+
}
|
|
500
|
+
}
|
|
461
501
|
}
|
package/css/avatar-group.css
CHANGED
|
@@ -85,7 +85,7 @@
|
|
|
85
85
|
inline-size: var(--xh-_avatar-group-size);
|
|
86
86
|
block-size: var(--xh-_avatar-group-size);
|
|
87
87
|
border-radius: var(--xh-avatar-group-radius, var(--xh-shape-circle));
|
|
88
|
-
background: var(--xh-avatar-group-overflow-item-bg, var(--xh-bg-muted));
|
|
88
|
+
background: var(--xh-avatar-group-overflow-item-bg, var(--xh-bg-muted-opaque));
|
|
89
89
|
color: var(--xh-avatar-group-overflow-item-fg, var(--xh-fg-muted));
|
|
90
90
|
font-size: var(--xh-_avatar-group-font-size);
|
|
91
91
|
font-weight: var(--xh-avatar-group-font-weight, var(--xh-font-weight-medium));
|
package/css/avatar.css
CHANGED
|
@@ -24,7 +24,8 @@
|
|
|
24
24
|
inline-size: var(--xh-avatar-size, var(--xh-control-h-md));
|
|
25
25
|
block-size: var(--xh-avatar-size, var(--xh-control-h-md));
|
|
26
26
|
border-radius: var(--xh-avatar-radius, var(--xh-shape-circle));
|
|
27
|
-
|
|
27
|
+
/* 头像在头像组里层叠:底取淡底的不透明档,半透明会透出压在下面的那一枚 */
|
|
28
|
+
background: var(--xh-avatar-bg, var(--xh-bg-subtle-opaque));
|
|
28
29
|
color: var(--xh-avatar-fg, var(--xh-fg-muted));
|
|
29
30
|
font-size: var(--xh-avatar-font-size, var(--xh-text-secondary-size));
|
|
30
31
|
font-weight: var(--xh-avatar-font-weight, var(--xh-font-weight-medium));
|
|
@@ -53,13 +54,13 @@
|
|
|
53
54
|
两条声明都把 --xh-avatar-bg / --xh-avatar-fg 排在语气值前面:使用者槽仍是最外那一层,
|
|
54
55
|
写了 tone 的那一枚照样受外层统一控制。整块带 [data-tone] 限定,没写语气的头像逐值不变 */
|
|
55
56
|
[data-scope='avatar'][data-part='root'][data-tone] {
|
|
56
|
-
background: var(--xh-avatar-bg, var(--xh-_tone-subtle, var(--xh-bg-subtle)));
|
|
57
|
+
background: var(--xh-avatar-bg, var(--xh-_tone-subtle, var(--xh-bg-subtle-opaque)));
|
|
57
58
|
color: var(--xh-avatar-fg, var(--xh-_tone-fg, var(--xh-fg-muted)));
|
|
58
59
|
}
|
|
59
60
|
|
|
60
61
|
/* 不声明 display,加载完成前的 hidden 直接交给浏览器的 [hidden] 规则收起。
|
|
61
|
-
载完那一刻 hidden
|
|
62
|
-
|
|
62
|
+
载完那一刻 hidden 撤掉、这个节点从不显示变为显示,淡入在那一刻起跑;
|
|
63
|
+
回退内容同一刻开始淡出(见下),两者交叉,中间不露一拍底色 */
|
|
63
64
|
[data-scope='avatar'][data-part='image'] {
|
|
64
65
|
inline-size: 100%;
|
|
65
66
|
block-size: 100%;
|
|
@@ -77,7 +78,14 @@
|
|
|
77
78
|
text-transform: uppercase;
|
|
78
79
|
}
|
|
79
80
|
|
|
80
|
-
/*
|
|
81
|
+
/* 图片载好:回退内容浮到图片之上原地淡出,与图片的淡入交叉;播完连接层才写 hidden */
|
|
82
|
+
[data-scope='avatar'][data-part='fallback'][data-state='loaded'] {
|
|
83
|
+
position: absolute;
|
|
84
|
+
inset: 0;
|
|
85
|
+
animation: xh-fade-out var(--xh-motion-duration-enter) var(--xh-motion-ease-enter) forwards;
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
/* display 会盖掉 hidden 属性的 UA 规则:载入中等过 fallbackDelay 之前、以及淡出播完之后收起 */
|
|
81
89
|
[data-scope='avatar'][data-part='fallback'][hidden] {
|
|
82
90
|
display: none;
|
|
83
91
|
}
|