@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.
- package/CHANGELOG.md +1261 -0
- package/README.md +6 -1
- package/component-tokens.d.ts +533 -96
- package/components.tokens.json +35461 -26045
- 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 +128 -50
- 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 +56 -0
- package/css/date-picker.css +132 -26
- package/css/date-range-picker.css +337 -14
- 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 +20 -18
- package/css/file-upload.css +125 -135
- package/css/flex.css +324 -8
- package/css/float-button.css +263 -38
- package/css/floating-panel.css +53 -19
- package/css/form.css +31 -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 +435 -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 +175 -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 +103 -17
- 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 +271 -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 +13824 -4030
- package/index.unlayered.css +13403 -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/menu.css
CHANGED
|
@@ -7,7 +7,9 @@
|
|
|
7
7
|
|
|
8
8
|
/* 共享关键帧由 family/motion.css 提供,条目走 Collection Item 家族;本皮肤 @import 它们,单独引入仍成立。 */
|
|
9
9
|
@import '../family/collection-item.css';
|
|
10
|
+
@import '../family/menu-choice.css';
|
|
10
11
|
@import '../family/motion.css';
|
|
12
|
+
@import '../family/material.css';
|
|
11
13
|
|
|
12
14
|
@layer xihan.components {
|
|
13
15
|
/* 皮肤在场的标记:开发模式下按 scope 探一次,取不到就说明这份皮肤没被引入。 */
|
|
@@ -67,6 +69,15 @@
|
|
|
67
69
|
}
|
|
68
70
|
|
|
69
71
|
[data-scope='menu'][data-part='content'] {
|
|
72
|
+
/* 材质由家族配方画(family/material.css 的 frosted 面:描边、底、1px 顶光、前景、投影与背景滤镜),
|
|
73
|
+
这里只把使用者槽接进来 */
|
|
74
|
+
--xh-frosted-bg: var(--xh-menu-content-bg, var(--xh-_material-bg));
|
|
75
|
+
--xh-frosted-border: var(--xh-menu-border, var(--xh-_material-border));
|
|
76
|
+
--xh-frosted-fg: var(--xh-menu-content-fg, var(--xh-_material-fg));
|
|
77
|
+
--xh-frosted-shadow: var(--xh-menu-content-shadow, var(--xh-_material-shadow));
|
|
78
|
+
--xh-frosted-backdrop: var(--xh-menu-backdrop, var(--xh-_material-backdrop));
|
|
79
|
+
--xh-frosted-highlight: var(--xh-menu-highlight, var(--xh-_material-highlight));
|
|
80
|
+
|
|
70
81
|
/* 条目外的字形(分组标题等)按档取尺,缺省 md,随 data-size 换档;条目里作者放的图标由家族随
|
|
71
82
|
data-xh-collection-size 下发。菜单自绘的状态字形(标记位的盒、子菜单的展开 chevron)不读这支:
|
|
72
83
|
它们是指示符,走 --xh-control-indicator-* 一族——标记位在自己身上把 --xh-icon-size 改接到盒的尺,
|
|
@@ -92,13 +103,7 @@
|
|
|
92
103
|
max-block-size: min(var(--xh-menu-max-h, var(--xh-overlay-menu-max-h)), var(--xh-_menu-available-h));
|
|
93
104
|
padding-block: var(--xh-menu-content-py, var(--xh-surface-pad-xs));
|
|
94
105
|
padding-inline: var(--xh-menu-content-px, var(--xh-surface-pad-xs));
|
|
95
|
-
border: var(--xh-stroke-thin) solid var(--xh-menu-border, var(--xh-material-frosted-border));
|
|
96
106
|
border-radius: var(--xh-menu-content-radius, var(--xh-shape-overlay));
|
|
97
|
-
background: var(--xh-menu-content-bg, var(--xh-material-frosted-bg));
|
|
98
|
-
color: var(--xh-menu-content-fg, var(--xh-material-frosted-fg));
|
|
99
|
-
box-shadow: var(--xh-menu-content-shadow, var(--xh-material-frosted-shadow));
|
|
100
|
-
-webkit-backdrop-filter: var(--xh-menu-backdrop, var(--xh-material-frosted-backdrop));
|
|
101
|
-
backdrop-filter: var(--xh-menu-backdrop, var(--xh-material-frosted-backdrop));
|
|
102
107
|
/* 条目超过上限就在菜单内部滚。条目的焦点环是内收的,滚动容器裁在内边距缘上,环切不着。
|
|
103
108
|
浮层滚动面:到底后不把滚动链穿透给页面 */
|
|
104
109
|
overflow-y: auto;
|
|
@@ -106,18 +111,6 @@
|
|
|
106
111
|
pointer-events: auto;
|
|
107
112
|
}
|
|
108
113
|
|
|
109
|
-
/* 顶光是独立装饰层,不替换真实边框;高对比/强制色归零后四边轮廓仍完整。 */
|
|
110
|
-
[data-scope='menu'][data-part='content']::before {
|
|
111
|
-
content: '';
|
|
112
|
-
position: absolute;
|
|
113
|
-
inset-block-start: 0;
|
|
114
|
-
inset-inline: 0;
|
|
115
|
-
block-size: var(--xh-stroke-thin);
|
|
116
|
-
border-radius: inherit;
|
|
117
|
-
background: var(--xh-menu-highlight, var(--xh-material-frosted-highlight));
|
|
118
|
-
pointer-events: none;
|
|
119
|
-
}
|
|
120
|
-
|
|
121
114
|
/* 这里刻意没有 [data-part='content'][hidden] { display: none },与 dialog 一致:
|
|
122
115
|
收起态连接层会给 content 打 hidden,而上面那条 display 正是要盖掉 UA 的
|
|
123
116
|
[hidden]{display:none}——退场动画得先能播。presence 读的是 content 的 animationName,
|
|
@@ -129,7 +122,8 @@
|
|
|
129
122
|
outline: none;
|
|
130
123
|
}
|
|
131
124
|
|
|
132
|
-
|
|
125
|
+
/* 挂载时就开着的那一段(data-instant)属于首帧,直接呈现 */
|
|
126
|
+
[data-scope='menu'][data-part='content'][data-state='open']:not([data-instant]) {
|
|
133
127
|
animation: xh-overlay-slide-in var(--xh-motion-duration-enter) var(--xh-motion-ease-enter-strong);
|
|
134
128
|
}
|
|
135
129
|
|
|
@@ -168,7 +162,7 @@
|
|
|
168
162
|
--xh-collection-inline-padding: var(--xh-menu-item-px, var(--xh-_menu-item-px));
|
|
169
163
|
--xh-collection-gap: 0;
|
|
170
164
|
--xh-collection-font-size: var(--xh-menu-item-font-size, var(--xh-_menu-font-size));
|
|
171
|
-
--xh-collection-radius: var(--xh-menu-item-radius, var(--xh-shape-
|
|
165
|
+
--xh-collection-radius: var(--xh-menu-item-radius, var(--xh-shape-inset));
|
|
172
166
|
--xh-collection-fg-rest: var(--xh-menu-item-fg, var(--xh-material-frosted-fg));
|
|
173
167
|
--xh-collection-fg-hover: var(--xh-menu-item-fg, var(--xh-material-frosted-fg));
|
|
174
168
|
--xh-collection-fg-keyboard-highlight: var(--xh-menu-item-fg, var(--xh-material-frosted-fg));
|
|
@@ -239,7 +233,8 @@
|
|
|
239
233
|
order: 2;
|
|
240
234
|
min-inline-size: 0;
|
|
241
235
|
color: var(--xh-menu-item-description-fg, var(--xh-material-frosted-fg-muted));
|
|
242
|
-
|
|
236
|
+
/* 与同一行的快捷键、Select 等列表的说明同档:控件次级字号,不取 caption 令牌 */
|
|
237
|
+
font-size: var(--xh-menu-item-description-font-size, var(--xh-control-caption-md));
|
|
243
238
|
white-space: nowrap;
|
|
244
239
|
text-overflow: ellipsis;
|
|
245
240
|
overflow: hidden;
|
|
@@ -347,4 +342,23 @@
|
|
|
347
342
|
display: none;
|
|
348
343
|
}
|
|
349
344
|
}
|
|
345
|
+
|
|
346
|
+
@media (forced-colors: active) {
|
|
347
|
+
/* 兜底字形是 mask 挖出来的一块底色,这一档里底色被系统换成 Canvas,字形跟着消失。
|
|
348
|
+
字形退出强制换色、直接写系统色(不能取 currentColor:退出强制换色的伪元素读到的是被系统换掉之前的作者色):
|
|
349
|
+
条目面上取 CanvasText;按下与没被高亮时的悬停,家族把条目涂成 Highlight,字形换 HighlightText;
|
|
350
|
+
禁用取 GrayText */
|
|
351
|
+
[data-scope='menu'][data-part='item'][aria-haspopup='menu']::after {
|
|
352
|
+
forced-color-adjust: none;
|
|
353
|
+
background-color: CanvasText;
|
|
354
|
+
}
|
|
355
|
+
|
|
356
|
+
[data-scope='menu'][data-part='item'][aria-haspopup='menu']:not([aria-disabled='true'], [data-disabled], [aria-busy='true'], [data-error]):is(:active, [data-pressed], :hover:not(:focus-visible, [data-highlighted]))::after {
|
|
357
|
+
background-color: HighlightText;
|
|
358
|
+
}
|
|
359
|
+
|
|
360
|
+
[data-scope='menu'][data-part='item'][aria-haspopup='menu']:is([aria-disabled='true'], [data-disabled])::after {
|
|
361
|
+
background-color: GrayText;
|
|
362
|
+
}
|
|
363
|
+
}
|
|
350
364
|
}
|
package/css/menubar.css
CHANGED
|
@@ -7,7 +7,9 @@
|
|
|
7
7
|
|
|
8
8
|
/* 共享关键帧由 family/motion.css 提供,条目走 Collection Item 家族;本皮肤 @import 它们,单独引入仍成立。 */
|
|
9
9
|
@import '../family/collection-item.css';
|
|
10
|
+
@import '../family/menu-choice.css';
|
|
10
11
|
@import '../family/motion.css';
|
|
12
|
+
@import '../family/material.css';
|
|
11
13
|
|
|
12
14
|
@layer xihan.components {
|
|
13
15
|
/* 皮肤在场的标记:开发模式下按 scope 探一次,取不到就说明这份皮肤没被引入。 */
|
|
@@ -166,6 +168,15 @@
|
|
|
166
168
|
}
|
|
167
169
|
|
|
168
170
|
[data-scope='menubar'][data-part='content'] {
|
|
171
|
+
/* 材质由家族配方画(family/material.css 的 frosted 面:描边、底、1px 顶光、前景、投影与背景滤镜),
|
|
172
|
+
这里只把使用者槽接进来 */
|
|
173
|
+
--xh-frosted-bg: var(--xh-menubar-content-bg, var(--xh-_material-bg));
|
|
174
|
+
--xh-frosted-border: var(--xh-menubar-border, var(--xh-_material-border));
|
|
175
|
+
--xh-frosted-fg: var(--xh-menubar-content-fg, var(--xh-_material-fg));
|
|
176
|
+
--xh-frosted-shadow: var(--xh-menubar-content-shadow, var(--xh-_material-shadow));
|
|
177
|
+
--xh-frosted-backdrop: var(--xh-menubar-backdrop, var(--xh-_material-backdrop));
|
|
178
|
+
--xh-frosted-highlight: var(--xh-menubar-highlight, var(--xh-_material-highlight));
|
|
179
|
+
|
|
169
180
|
position: relative;
|
|
170
181
|
display: flex;
|
|
171
182
|
flex-direction: column;
|
|
@@ -178,13 +189,7 @@
|
|
|
178
189
|
max-block-size: min(var(--xh-menubar-max-h, var(--xh-overlay-menu-max-h)), var(--xh-_menubar-available-h));
|
|
179
190
|
padding-block: var(--xh-menubar-content-py, var(--xh-surface-pad-xs));
|
|
180
191
|
padding-inline: var(--xh-menubar-content-px, var(--xh-surface-pad-xs));
|
|
181
|
-
border: var(--xh-stroke-thin) solid var(--xh-menubar-border, var(--xh-material-frosted-border));
|
|
182
192
|
border-radius: var(--xh-menubar-content-radius, var(--xh-shape-overlay));
|
|
183
|
-
background: var(--xh-menubar-content-bg, var(--xh-material-frosted-bg));
|
|
184
|
-
color: var(--xh-menubar-content-fg, var(--xh-material-frosted-fg));
|
|
185
|
-
box-shadow: var(--xh-menubar-content-shadow, var(--xh-material-frosted-shadow));
|
|
186
|
-
-webkit-backdrop-filter: var(--xh-menubar-backdrop, var(--xh-material-frosted-backdrop));
|
|
187
|
-
backdrop-filter: var(--xh-menubar-backdrop, var(--xh-material-frosted-backdrop));
|
|
188
193
|
/* 条目超过上限就在菜单内部滚。条目的焦点环是内收的,滚动容器裁在内边距缘上,环切不着。
|
|
189
194
|
浮层滚动面:到底后不把滚动链穿透给页面 */
|
|
190
195
|
overflow-y: auto;
|
|
@@ -192,18 +197,6 @@
|
|
|
192
197
|
pointer-events: auto;
|
|
193
198
|
}
|
|
194
199
|
|
|
195
|
-
/* 顶光叠在真实四边 border 内侧;强制色撤掉装饰后,完整轮廓仍然存在。 */
|
|
196
|
-
[data-scope='menubar'][data-part='content']::before {
|
|
197
|
-
content: '';
|
|
198
|
-
position: absolute;
|
|
199
|
-
inset-block-start: 0;
|
|
200
|
-
inset-inline: 0;
|
|
201
|
-
block-size: var(--xh-stroke-thin);
|
|
202
|
-
border-radius: inherit;
|
|
203
|
-
background: var(--xh-menubar-highlight, var(--xh-material-frosted-highlight));
|
|
204
|
-
pointer-events: none;
|
|
205
|
-
}
|
|
206
|
-
|
|
207
200
|
/* display 会盖掉 hidden 属性的 UA 规则,收起态显式让位。
|
|
208
201
|
连接层给 content 发 hidden,这一条漏了整张菜单就永远收不起来 */
|
|
209
202
|
/* 这里刻意没有 [data-part='content'][hidden] { display: none },与 dialog 一致:
|
|
@@ -268,7 +261,7 @@
|
|
|
268
261
|
--xh-collection-inline-padding: var(--xh-menubar-item-px, var(--xh-_menubar-item-px));
|
|
269
262
|
--xh-collection-gap: 0;
|
|
270
263
|
--xh-collection-font-size: var(--xh-menubar-item-font-size, var(--xh-_menubar-font-size));
|
|
271
|
-
--xh-collection-radius: var(--xh-menubar-item-radius, var(--xh-shape-
|
|
264
|
+
--xh-collection-radius: var(--xh-menubar-item-radius, var(--xh-shape-inset));
|
|
272
265
|
--xh-collection-fg-rest: var(--xh-menubar-item-fg, var(--xh-material-frosted-fg));
|
|
273
266
|
--xh-collection-fg-hover: var(--xh-menubar-item-fg, var(--xh-material-frosted-fg));
|
|
274
267
|
--xh-collection-fg-keyboard-highlight: var(--xh-menubar-item-fg, var(--xh-material-frosted-fg));
|
|
@@ -366,7 +359,8 @@
|
|
|
366
359
|
order: 2;
|
|
367
360
|
min-inline-size: 0;
|
|
368
361
|
color: var(--xh-menubar-item-description-fg, var(--xh-material-frosted-fg-muted));
|
|
369
|
-
|
|
362
|
+
/* 与同一行的快捷键、Select 等列表的说明同档:控件次级字号,不取 caption 令牌 */
|
|
363
|
+
font-size: var(--xh-menubar-item-description-font-size, var(--xh-control-caption-md));
|
|
370
364
|
white-space: nowrap;
|
|
371
365
|
text-overflow: ellipsis;
|
|
372
366
|
overflow: hidden;
|
|
@@ -437,4 +431,26 @@
|
|
|
437
431
|
background: CanvasText;
|
|
438
432
|
}
|
|
439
433
|
}
|
|
434
|
+
|
|
435
|
+
@media (forced-colors: active) {
|
|
436
|
+
/* 兜底字形是 mask 挖出来的一块底色,这一档里底色被系统换成 Canvas,字形跟着消失。
|
|
437
|
+
字形退出强制换色、直接写系统色(不能取 currentColor:退出强制换色的伪元素读到的是被系统换掉之前的作者色):
|
|
438
|
+
条目面上取 CanvasText;按下与没被高亮时的悬停,家族把条目涂成 Highlight,字形换 HighlightText;
|
|
439
|
+
禁用取 GrayText */
|
|
440
|
+
[data-scope='menubar'][data-part='item'][aria-haspopup='menu']::after,
|
|
441
|
+
[data-scope='menubar'][data-part='item-indicator']:empty::before {
|
|
442
|
+
forced-color-adjust: none;
|
|
443
|
+
background-color: CanvasText;
|
|
444
|
+
}
|
|
445
|
+
|
|
446
|
+
[data-scope='menubar'][data-part='item'][aria-haspopup='menu']:not([aria-disabled='true'], [data-disabled], [aria-busy='true'], [data-error]):is(:active, [data-pressed], :hover:not(:focus-visible, [data-highlighted]))::after,
|
|
447
|
+
[data-scope='menubar'][data-part='item']:not([aria-disabled='true'], [data-disabled], [aria-busy='true'], [data-error]):is(:active, [data-pressed], :hover:not(:focus-visible, [data-highlighted])) [data-scope='menubar'][data-part='item-indicator']:empty::before {
|
|
448
|
+
background-color: HighlightText;
|
|
449
|
+
}
|
|
450
|
+
|
|
451
|
+
[data-scope='menubar'][data-part='item'][aria-haspopup='menu']:is([aria-disabled='true'], [data-disabled])::after,
|
|
452
|
+
[data-scope='menubar'][data-part='item']:is([aria-disabled='true'], [data-disabled]) [data-scope='menubar'][data-part='item-indicator']:empty::before {
|
|
453
|
+
background-color: GrayText;
|
|
454
|
+
}
|
|
455
|
+
}
|
|
440
456
|
}
|
package/css/message-feed.css
CHANGED
|
@@ -5,37 +5,11 @@
|
|
|
5
5
|
|
|
6
6
|
/* 定义 message feed 样式。 */
|
|
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
|
-
@keyframes xh-message-feed-item-in {
|
|
16
|
-
from {
|
|
17
|
-
opacity: 0;
|
|
18
|
-
translate: 0 var(--xh-motion-distance-md);
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
to {
|
|
22
|
-
opacity: 1;
|
|
23
|
-
translate: 0 0;
|
|
24
|
-
}
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
@keyframes xh-message-feed-button-in {
|
|
28
|
-
from {
|
|
29
|
-
opacity: 0;
|
|
30
|
-
scale: var(--xh-motion-scale-enter);
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
to {
|
|
34
|
-
opacity: 1;
|
|
35
|
-
scale: 1;
|
|
36
|
-
}
|
|
37
|
-
}
|
|
38
|
-
}
|
|
12
|
+
@import '../family/material.css';
|
|
39
13
|
|
|
40
14
|
@layer xihan.components {
|
|
41
15
|
/* 皮肤在场的标记:开发模式下按 scope 探一次,取不到就说明这份皮肤没被引入。 */
|
|
@@ -85,14 +59,62 @@
|
|
|
85
59
|
display: none;
|
|
86
60
|
}
|
|
87
61
|
|
|
88
|
-
/*
|
|
89
|
-
|
|
62
|
+
/* 已发送、等首个片段:列表之后一颗呼吸的圆点,行首与消息内容对齐。
|
|
63
|
+
呼吸只表达「正在进行、给不出进度」:明暗与缩放的起伏持续到首个片段到来,外扩光环同周期播 3 轮后停下。
|
|
64
|
+
连接层只在 submitted 时撤掉 hidden */
|
|
65
|
+
[data-scope='message-feed'][data-part='pending-indicator'] {
|
|
66
|
+
position: relative;
|
|
67
|
+
display: block;
|
|
68
|
+
inline-size: var(--xh-message-feed-pending-indicator-size, var(--xh-space-2));
|
|
69
|
+
block-size: var(--xh-message-feed-pending-indicator-size, var(--xh-space-2));
|
|
70
|
+
margin-block-end: var(--xh-message-feed-p, var(--xh-_message-feed-p));
|
|
71
|
+
margin-inline-start: var(--xh-message-feed-p, var(--xh-_message-feed-p));
|
|
72
|
+
border-radius: var(--xh-message-feed-pending-indicator-radius, var(--xh-shape-circle));
|
|
73
|
+
background: var(--xh-message-feed-pending-indicator-color, var(--xh-fg-muted));
|
|
74
|
+
animation: xh-breathe var(--xh-motion-loop-breathe) var(--xh-motion-ease-breathe) infinite;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
[data-scope='message-feed'][data-part='pending-indicator']::after {
|
|
78
|
+
content: '';
|
|
79
|
+
position: absolute;
|
|
80
|
+
inset: 0;
|
|
81
|
+
border-radius: inherit;
|
|
82
|
+
background: inherit;
|
|
83
|
+
opacity: 0;
|
|
84
|
+
pointer-events: none;
|
|
85
|
+
animation: xh-breathe-halo var(--xh-motion-loop-breathe) var(--xh-motion-ease-breathe) 3;
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
/* 减弱动效:两者都停,圆点停在满不透明度,光环不出现 */
|
|
89
|
+
@media (prefers-reduced-motion: reduce) {
|
|
90
|
+
[data-scope='message-feed'][data-part='pending-indicator'],
|
|
91
|
+
[data-scope='message-feed'][data-part='pending-indicator']::after {
|
|
92
|
+
animation: none;
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
:where([data-motion='reduce']) [data-scope='message-feed'][data-part='pending-indicator'],
|
|
97
|
+
:where([data-motion='reduce']) [data-scope='message-feed'][data-part='pending-indicator']::after {
|
|
98
|
+
animation: none;
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
[data-scope='message-feed'][data-part='pending-indicator'][hidden] {
|
|
102
|
+
display: none;
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
/* 一条消息。默认整行铺开,左右分侧由使用者按 data-role 自己写 */
|
|
90
106
|
[data-scope='message-feed'][data-part='item'] {
|
|
91
107
|
display: flex;
|
|
92
108
|
flex-direction: column;
|
|
93
109
|
gap: var(--xh-message-feed-item-gap, var(--xh-space-1));
|
|
94
110
|
border-radius: var(--xh-message-feed-item-radius, var(--xh-shape-surface));
|
|
95
|
-
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
/* 新到的消息进场,同一批按到达顺序错开;首帧就在的历史消息直接呈现(自己或 list 带 data-instant)。
|
|
114
|
+
进场只动 opacity 与 translate:改高度会扰动粘底补偿量到的 scrollHeight */
|
|
115
|
+
[data-scope='message-feed'][data-part='item']:not([data-instant], [data-instant] > *) {
|
|
116
|
+
animation: xh-item-in var(--xh-motion-duration-enter) var(--xh-motion-ease-enter-strong) backwards;
|
|
117
|
+
animation-delay: calc(var(--xh-_stagger-index, 0) * var(--xh-motion-stagger-step));
|
|
96
118
|
}
|
|
97
119
|
|
|
98
120
|
[data-scope='message-feed'][data-part='item'][hidden] {
|
|
@@ -115,26 +137,39 @@
|
|
|
115
137
|
frosted 四件套(底 + 边 + 影 + 磨砂),这里只把使用者槽映射到桥接槽:
|
|
116
138
|
字形按 xs 档取 --xh-_action-profile-glyph-size(16px),与 log / back-top 同一把尺 */
|
|
117
139
|
[data-scope='message-feed'][data-part='scroll-to-end-trigger'] {
|
|
118
|
-
|
|
140
|
+
/* 面走材质家族配方(family/material.css):frosted 档的底、交互阶梯、描边、投影、1px 顶光与背景滤镜,
|
|
141
|
+
liquid 档由配方换成液态面;这里把使用者槽接到 Action Control 的桥接槽 */
|
|
142
|
+
--xh-action-bg-rest: var(--xh-message-feed-scroll-to-end-trigger-bg, var(--xh-_material-bg));
|
|
143
|
+
--xh-action-bg-hover: var(--xh-message-feed-scroll-to-end-trigger-bg-hover, var(--xh-_material-bg-hover));
|
|
144
|
+
--xh-action-bg-pressed: var(--xh-_material-bg-pressed);
|
|
145
|
+
--xh-action-bg-focus-visible: var(--xh-message-feed-scroll-to-end-trigger-bg, var(--xh-_material-bg-focus));
|
|
146
|
+
--xh-action-bg-disabled: var(--xh-message-feed-scroll-to-end-trigger-bg, var(--xh-_material-bg));
|
|
147
|
+
--xh-action-fg-rest: var(--xh-message-feed-scroll-to-end-trigger-fg, var(--xh-_material-fg));
|
|
148
|
+
--xh-action-fg-hover: var(--xh-message-feed-scroll-to-end-trigger-fg, var(--xh-_material-fg));
|
|
149
|
+
--xh-action-fg-pressed: var(--xh-message-feed-scroll-to-end-trigger-fg, var(--xh-_material-fg));
|
|
150
|
+
--xh-action-fg-focus-visible: var(--xh-message-feed-scroll-to-end-trigger-fg, var(--xh-_material-fg));
|
|
151
|
+
--xh-action-border-rest: var(--xh-message-feed-scroll-to-end-trigger-border, var(--xh-_material-border));
|
|
152
|
+
--xh-action-border-hover: var(--xh-message-feed-scroll-to-end-trigger-border, var(--xh-_material-border));
|
|
153
|
+
--xh-action-border-pressed: var(--xh-message-feed-scroll-to-end-trigger-border, var(--xh-_material-border));
|
|
154
|
+
--xh-action-border-focus-visible: var(--xh-message-feed-scroll-to-end-trigger-border, var(--xh-_material-border));
|
|
155
|
+
--xh-action-border-disabled: var(--xh-message-feed-scroll-to-end-trigger-border, var(--xh-_material-border));
|
|
156
|
+
--xh-action-shadow-rest: var(--xh-message-feed-scroll-to-end-trigger-shadow, var(--xh-_material-shadow));
|
|
157
|
+
--xh-action-shadow-hover: var(--xh-message-feed-scroll-to-end-trigger-shadow, var(--xh-_material-shadow));
|
|
158
|
+
--xh-action-shadow-pressed: var(--xh-message-feed-scroll-to-end-trigger-shadow, var(--xh-_material-shadow));
|
|
159
|
+
--xh-action-shadow-focus-visible: var(--xh-message-feed-scroll-to-end-trigger-shadow, var(--xh-_material-shadow));
|
|
160
|
+
--xh-action-shadow-disabled: var(--xh-message-feed-scroll-to-end-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);
|
|
119
166
|
--xh-action-visual-size: var(--xh-message-feed-scroll-to-end-trigger-size, var(--xh-_action-profile-visual-size));
|
|
120
167
|
--xh-action-radius: var(--xh-message-feed-scroll-to-end-trigger-radius, var(--xh-shape-circle));
|
|
121
|
-
--xh-action-bg-rest: var(--xh-message-feed-scroll-to-end-trigger-bg, var(--xh-material-frosted-bg));
|
|
122
|
-
--xh-action-bg-hover: var(--xh-message-feed-scroll-to-end-trigger-bg-hover, var(--xh-_action-variant-bg-hover));
|
|
123
|
-
--xh-action-border-rest: var(--xh-message-feed-scroll-to-end-trigger-border, var(--xh-material-frosted-border));
|
|
124
|
-
--xh-action-border-hover: var(--xh-message-feed-scroll-to-end-trigger-border, var(--xh-material-frosted-border));
|
|
125
|
-
--xh-action-border-pressed: var(--xh-message-feed-scroll-to-end-trigger-border, var(--xh-material-frosted-border));
|
|
126
|
-
--xh-action-border-focus-visible: var(--xh-message-feed-scroll-to-end-trigger-border, var(--xh-material-frosted-border));
|
|
127
|
-
--xh-action-shadow-rest: var(--xh-_message-feed-scroll-to-end-trigger-shadow);
|
|
128
|
-
--xh-action-shadow-hover: var(--xh-_message-feed-scroll-to-end-trigger-shadow);
|
|
129
|
-
--xh-action-shadow-pressed: var(--xh-_message-feed-scroll-to-end-trigger-shadow);
|
|
130
|
-
--xh-action-fg-rest: var(--xh-message-feed-scroll-to-end-trigger-fg, var(--xh-material-frosted-fg));
|
|
131
168
|
--xh-icon-size: var(--xh-message-feed-icon-size, var(--xh-_action-profile-glyph-size));
|
|
132
169
|
|
|
133
170
|
position: absolute;
|
|
134
171
|
inset-block-end: var(--xh-message-feed-scroll-to-end-trigger-inset, var(--xh-space-4));
|
|
135
172
|
inset-inline-end: var(--xh-message-feed-scroll-to-end-trigger-inset, var(--xh-space-4));
|
|
136
|
-
-webkit-backdrop-filter: var(--xh-material-frosted-backdrop);
|
|
137
|
-
backdrop-filter: var(--xh-material-frosted-backdrop);
|
|
138
173
|
}
|
|
139
174
|
|
|
140
175
|
/* 连接层收起按钮时写 hidden 属性,家族那条 display 会盖掉 UA 规则,这里补回 */
|
|
@@ -142,13 +177,20 @@
|
|
|
142
177
|
display: none;
|
|
143
178
|
}
|
|
144
179
|
|
|
145
|
-
/*
|
|
180
|
+
/* 收起不卸载:离底时冒出来播进场,回底时先播完退场、连接层才写 hidden 藏起。
|
|
181
|
+
不写 display,可见性归上面那条 [hidden] 管;退场途中不再接指针 */
|
|
146
182
|
[data-scope='message-feed'][data-part='scroll-to-end-trigger'][data-state='visible'] {
|
|
147
|
-
animation: xh-
|
|
183
|
+
animation: xh-pop-in var(--xh-motion-duration-enter) var(--xh-motion-ease-enter-strong);
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
[data-scope='message-feed'][data-part='scroll-to-end-trigger'][data-state='hidden']:not([hidden]) {
|
|
187
|
+
pointer-events: none;
|
|
188
|
+
animation: xh-pop-out var(--xh-motion-duration-exit) var(--xh-motion-ease-exit) forwards;
|
|
148
189
|
}
|
|
149
190
|
|
|
150
|
-
/*
|
|
151
|
-
[data-scope='message-feed'][data-part='scroll-to-end-trigger']:empty::before
|
|
191
|
+
/* 没写内容(或只放了未读数角标)就由皮肤画一枚向下的字形;作者往按钮里塞了自己的图形,这条规则即不命中 */
|
|
192
|
+
[data-scope='message-feed'][data-part='scroll-to-end-trigger']:empty::before,
|
|
193
|
+
[data-scope='message-feed'][data-part='scroll-to-end-trigger']:has(> [data-part='unread-count']:only-child)::before {
|
|
152
194
|
content: '';
|
|
153
195
|
display: inline-block;
|
|
154
196
|
inline-size: var(--xh-icon-size, var(--xh-glyph-size-sm));
|
|
@@ -188,10 +230,89 @@
|
|
|
188
230
|
white-space: nowrap;
|
|
189
231
|
}
|
|
190
232
|
|
|
233
|
+
/* 消息之间的分隔(按日期分组):一行次级标注居中,两侧各一道内部分隔线 */
|
|
234
|
+
[data-scope='message-feed'][data-part='separator'] {
|
|
235
|
+
display: flex;
|
|
236
|
+
align-items: center;
|
|
237
|
+
gap: var(--xh-message-feed-separator-gap, var(--xh-space-3));
|
|
238
|
+
color: var(--xh-message-feed-separator-fg, var(--xh-fg-subtle));
|
|
239
|
+
font-size: var(--xh-message-feed-separator-font-size, var(--xh-text-caption-size));
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
[data-scope='message-feed'][data-part='separator']::before,
|
|
243
|
+
[data-scope='message-feed'][data-part='separator']::after {
|
|
244
|
+
flex: 1;
|
|
245
|
+
border-block-start: var(--xh-stroke-thin) solid var(--xh-message-feed-separator-line, var(--xh-border-subtle));
|
|
246
|
+
content: '';
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
[data-scope='message-feed'][data-part='separator'][hidden] {
|
|
250
|
+
display: none;
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
/* 回到底部上的未读数:状态 chip,钉在按钮行尾上角外侧,不改按钮盒 */
|
|
254
|
+
[data-scope='message-feed'][data-part='unread-count'] {
|
|
255
|
+
position: absolute;
|
|
256
|
+
inset-block-start: calc(-1 * var(--xh-space-1));
|
|
257
|
+
inset-inline-end: calc(-1 * var(--xh-space-1));
|
|
258
|
+
box-sizing: border-box;
|
|
259
|
+
min-inline-size: var(--xh-message-feed-unread-count-size, var(--xh-space-4));
|
|
260
|
+
block-size: var(--xh-message-feed-unread-count-size, var(--xh-space-4));
|
|
261
|
+
padding-inline: var(--xh-message-feed-unread-count-px, var(--xh-space-1));
|
|
262
|
+
border-radius: var(--xh-message-feed-unread-count-radius, var(--xh-shape-pill));
|
|
263
|
+
background: var(--xh-message-feed-unread-count-bg, var(--xh-bg-brand));
|
|
264
|
+
color: var(--xh-message-feed-unread-count-fg, var(--xh-fg-on-brand));
|
|
265
|
+
font-size: var(--xh-message-feed-unread-count-font-size, var(--xh-text-caption-size));
|
|
266
|
+
font-variant-numeric: tabular-nums;
|
|
267
|
+
line-height: var(--xh-message-feed-unread-count-size, var(--xh-space-4));
|
|
268
|
+
text-align: center;
|
|
269
|
+
pointer-events: none;
|
|
270
|
+
}
|
|
271
|
+
|
|
272
|
+
[data-scope='message-feed'][data-part='unread-count'][hidden] {
|
|
273
|
+
display: none;
|
|
274
|
+
}
|
|
275
|
+
|
|
191
276
|
@media print {
|
|
192
|
-
/*
|
|
193
|
-
|
|
277
|
+
/* 打印:回到底部这颗钮只有在能滚的地方才成立,落到纸上是一颗按不动的按钮;
|
|
278
|
+
等首个片段的呼吸点是一瞬间的状态,纸上没有「正在进行」。 */
|
|
279
|
+
[data-scope='message-feed'][data-part='scroll-to-end-trigger'],
|
|
280
|
+
[data-scope='message-feed'][data-part='pending-indicator'] {
|
|
194
281
|
display: none;
|
|
195
282
|
}
|
|
196
283
|
}
|
|
284
|
+
|
|
285
|
+
/* 强制色:底色会被系统背景吃掉,圆点改用系统前景色 */
|
|
286
|
+
@media (forced-colors: active) {
|
|
287
|
+
[data-scope='message-feed'][data-part='pending-indicator'] {
|
|
288
|
+
background: CanvasText;
|
|
289
|
+
}
|
|
290
|
+
|
|
291
|
+
[data-scope='message-feed'][data-part='unread-count'] {
|
|
292
|
+
background: Highlight;
|
|
293
|
+
color: HighlightText;
|
|
294
|
+
}
|
|
295
|
+
}
|
|
296
|
+
|
|
297
|
+
@media (forced-colors: active) {
|
|
298
|
+
/* 兜底字形是 mask 挖出来的一块底色,这一档里底色被系统换成 Canvas,字形跟着消失。
|
|
299
|
+
字形退出强制换色、直接写系统色(不能取 currentColor:退出强制换色的伪元素读到的是被系统换掉之前的作者色):
|
|
300
|
+
按钮面上取 ButtonText,悬停与按下时家族把按钮涂成 Highlight、字形换 HighlightText;
|
|
301
|
+
禁用取 GrayText */
|
|
302
|
+
[data-scope='message-feed'][data-part='scroll-to-end-trigger']:empty::before,
|
|
303
|
+
[data-scope='message-feed'][data-part='scroll-to-end-trigger']:has(> [data-part='unread-count']:only-child)::before {
|
|
304
|
+
forced-color-adjust: none;
|
|
305
|
+
background-color: ButtonText;
|
|
306
|
+
}
|
|
307
|
+
|
|
308
|
+
[data-scope='message-feed'][data-part='scroll-to-end-trigger']:not([data-disabled]):not([data-loading]):is(:hover, :active, [data-pressed]):empty::before,
|
|
309
|
+
[data-scope='message-feed'][data-part='scroll-to-end-trigger']:not([data-disabled]):not([data-loading]):is(:hover, :active, [data-pressed]):has(> [data-part='unread-count']:only-child)::before {
|
|
310
|
+
background-color: HighlightText;
|
|
311
|
+
}
|
|
312
|
+
|
|
313
|
+
[data-scope='message-feed'][data-part='scroll-to-end-trigger'][data-disabled]:empty::before,
|
|
314
|
+
[data-scope='message-feed'][data-part='scroll-to-end-trigger'][data-disabled]:has(> [data-part='unread-count']:only-child)::before {
|
|
315
|
+
background-color: GrayText;
|
|
316
|
+
}
|
|
317
|
+
}
|
|
197
318
|
}
|