@xihan-ui/styles 1.0.0-alpha.2 → 1.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 +2177 -0
- package/README.md +1 -1
- package/css/accordion.css +80 -6
- package/css/alert.css +43 -14
- package/css/anchor.css +8 -8
- package/css/avatar-group.css +7 -3
- package/css/avatar.css +9 -3
- package/css/back-top.css +22 -1
- package/css/badge.css +104 -32
- package/css/breadcrumb.css +25 -5
- package/css/button-group.css +18 -13
- package/css/button.css +48 -11
- package/css/calendar.css +150 -7
- package/css/card.css +20 -11
- package/css/carousel.css +36 -5
- package/css/cascader.css +211 -124
- package/css/checkbox-group.css +72 -22
- package/css/checkbox.css +70 -13
- package/css/clipboard.css +2 -1
- package/css/code-block.css +12 -7
- package/css/collapsible.css +49 -3
- package/css/color-picker.css +132 -46
- package/css/combobox.css +132 -60
- package/css/composer.css +5 -3
- package/css/context-menu.css +113 -74
- package/css/date-field.css +93 -16
- package/css/date-picker.css +293 -72
- package/css/descriptions.css +11 -5
- package/css/dialog.css +47 -14
- package/css/download-trigger.css +76 -0
- package/css/drawer.css +57 -16
- package/css/dynamic-input.css +75 -17
- package/css/editable.css +12 -10
- package/css/ellipsis.css +7 -1
- package/css/empty-state.css +22 -12
- package/css/field.css +16 -6
- package/css/fieldset.css +69 -0
- package/css/file-upload.css +46 -8
- package/css/flex.css +13 -7
- package/css/float-button.css +23 -1
- package/css/floating-panel.css +316 -0
- package/css/form.css +4 -4
- package/css/grid.css +11 -5
- package/css/heatmap.css +411 -0
- package/css/highlight.css +2 -2
- package/css/hotkeys.css +90 -0
- package/css/hover-card.css +43 -45
- package/css/image-cropper.css +233 -0
- package/css/image-viewer.css +155 -17
- package/css/image.css +2 -2
- package/css/infinite-scroll.css +1 -1
- package/css/json-viewer.css +274 -0
- package/css/layout.css +19 -15
- package/css/list.css +22 -13
- package/css/listbox.css +24 -6
- package/css/loading-bar.css +12 -5
- package/css/log.css +7 -3
- package/css/marquee.css +9 -0
- package/css/masonry.css +63 -0
- package/css/mention.css +100 -36
- package/css/menu.css +127 -50
- package/css/menubar.css +155 -61
- package/css/navigation-menu.css +56 -31
- package/css/notification.css +377 -0
- package/css/number-animation.css +3 -3
- package/css/number-field.css +182 -19
- package/css/overlay-arrow.css +51 -0
- package/css/page-header.css +12 -5
- package/css/pagination.css +171 -14
- package/css/password-input.css +356 -0
- package/css/pin-input.css +15 -12
- package/css/popconfirm.css +55 -12
- package/css/popover.css +73 -45
- package/css/popselect.css +207 -57
- package/css/progress.css +54 -8
- package/css/qr-code.css +1 -1
- package/css/radio-group.css +27 -10
- package/css/rating.css +4 -4
- package/css/reset.css +17 -0
- package/css/result.css +21 -11
- package/css/scroll-area.css +61 -89
- package/css/scrollbar.css +170 -0
- package/css/segmented.css +215 -0
- package/css/select.css +298 -131
- package/css/separator.css +2 -2
- package/css/side-nav.css +127 -24
- package/css/signature-pad.css +144 -0
- package/css/skeleton.css +7 -1
- package/css/slider.css +14 -12
- package/css/space.css +117 -0
- package/css/spinner.css +22 -10
- package/css/statistic.css +9 -9
- package/css/steps.css +29 -12
- package/css/switch.css +57 -8
- package/css/table.css +146 -44
- package/css/tabs.css +13 -5
- package/css/tag.css +179 -0
- package/css/tags-input.css +80 -42
- package/css/text-field.css +151 -38
- package/css/thread.css +11 -3
- package/css/time-field.css +99 -18
- package/css/time-picker.css +261 -71
- package/css/timeline.css +15 -15
- package/css/timer.css +119 -0
- package/css/toast.css +129 -55
- package/css/toggle-group.css +30 -4
- package/css/toggle.css +12 -6
- package/css/tone.css +57 -22
- package/css/toolbar.css +1 -1
- package/css/tooltip.css +40 -31
- package/css/tour.css +112 -61
- package/css/transfer.css +98 -21
- package/css/tree-select.css +215 -89
- package/css/tree.css +131 -5
- package/css/typography.css +5 -5
- package/css/undefined.css +12 -1
- package/css/virtualizer.css +3 -1
- package/css/watermark.css +1 -2
- package/index.css +18 -1
- package/index.unlayered.css +10356 -3255
- package/package.json +20 -4
- package/css/toaster.css +0 -74
package/css/text-field.css
CHANGED
|
@@ -5,16 +5,20 @@
|
|
|
5
5
|
}
|
|
6
6
|
|
|
7
7
|
/* root 只负责纵向堆叠:标签一行、输入行一行。
|
|
8
|
-
|
|
9
|
-
|
|
8
|
+
输入框与清空按钮收进 control 部件即得一体式:视觉盒画在 control 上,框内两件都退成透明分段。
|
|
9
|
+
不写 control 时退回两件并排的观感(下方 input 与清空按钮的基础规则原样生效) */
|
|
10
10
|
[data-scope='text-field'][data-part='root'] {
|
|
11
|
+
/* 作者塞进来的图标跟着控件的尺寸档走;它自己写了 size 时仍以作者的为准 */
|
|
12
|
+
--xh-icon-size: var(--xh-text-field-icon-size, var(--xh-glyph-size-md));
|
|
13
|
+
|
|
11
14
|
/* 尺寸档只换这几个私有槽,标题、输入框与清空按钮都从 root 继承它们,
|
|
12
15
|
换档不必给每个部件各写一条选择器 */
|
|
13
16
|
--xh-_text-field-h: var(--xh-control-h-md);
|
|
14
17
|
--xh-_text-field-px: var(--xh-control-px-md);
|
|
15
|
-
--xh-_text-field-
|
|
16
|
-
--xh-_text-field-
|
|
17
|
-
--xh-_text-field-
|
|
18
|
+
--xh-_text-field-gap: var(--xh-control-gap-md);
|
|
19
|
+
--xh-_text-field-font-size: var(--xh-control-font-md);
|
|
20
|
+
--xh-_text-field-label-font-size: var(--xh-control-font-md);
|
|
21
|
+
--xh-_text-field-action-font-size: var(--xh-control-caption-md);
|
|
18
22
|
|
|
19
23
|
/* 形态档只换这三个私有槽:底、常态描边、悬停描边 */
|
|
20
24
|
--xh-_text-field-bg: var(--xh-bg-canvas);
|
|
@@ -24,7 +28,7 @@
|
|
|
24
28
|
/* 语气只落在聚焦这一处:环与聚焦态描边。正文颜色不归它管。
|
|
25
29
|
没写 data-tone 时 --xh-_tone 没被声明,退回原来的聚焦环色与常态描边 */
|
|
26
30
|
--xh-_text-field-ring: var(--xh-ring-focus);
|
|
27
|
-
--xh-_text-field-border-focus: var(--xh-text-field-input-border, var(--xh-_tone, var(--xh-border-control)));
|
|
31
|
+
--xh-_text-field-border-focus: var(--xh-text-field-input-border, var(--xh-_tone, var(--xh-border-control-focus)));
|
|
28
32
|
|
|
29
33
|
display: inline-flex;
|
|
30
34
|
flex-direction: column;
|
|
@@ -39,19 +43,23 @@
|
|
|
39
43
|
/* —— 尺寸 —— */
|
|
40
44
|
/* 缺省档写在上面的基础规则里 */
|
|
41
45
|
[data-scope='text-field'][data-part='root'][data-size='sm'] {
|
|
46
|
+
--xh-icon-size: var(--xh-text-field-icon-size, var(--xh-glyph-size-sm));
|
|
42
47
|
--xh-_text-field-h: var(--xh-control-h-sm);
|
|
43
48
|
--xh-_text-field-px: var(--xh-control-px-sm);
|
|
44
|
-
--xh-_text-field-
|
|
45
|
-
--xh-_text-field-
|
|
46
|
-
--xh-_text-field-
|
|
49
|
+
--xh-_text-field-gap: var(--xh-control-gap-sm);
|
|
50
|
+
--xh-_text-field-font-size: var(--xh-control-font-sm);
|
|
51
|
+
--xh-_text-field-label-font-size: var(--xh-control-font-sm);
|
|
52
|
+
--xh-_text-field-action-font-size: var(--xh-control-caption-sm);
|
|
47
53
|
}
|
|
48
54
|
|
|
49
55
|
[data-scope='text-field'][data-part='root'][data-size='lg'] {
|
|
56
|
+
--xh-icon-size: var(--xh-text-field-icon-size, var(--xh-glyph-size-lg));
|
|
50
57
|
--xh-_text-field-h: var(--xh-control-h-lg);
|
|
51
58
|
--xh-_text-field-px: var(--xh-control-px-lg);
|
|
52
|
-
--xh-_text-field-
|
|
53
|
-
--xh-_text-field-
|
|
54
|
-
--xh-_text-field-
|
|
59
|
+
--xh-_text-field-gap: var(--xh-control-gap-lg);
|
|
60
|
+
--xh-_text-field-font-size: var(--xh-control-font-lg);
|
|
61
|
+
--xh-_text-field-label-font-size: var(--xh-control-font-lg);
|
|
62
|
+
--xh-_text-field-action-font-size: var(--xh-control-caption-lg);
|
|
55
63
|
}
|
|
56
64
|
|
|
57
65
|
/* —— 形态 —— */
|
|
@@ -61,7 +69,7 @@
|
|
|
61
69
|
--xh-_text-field-bg: var(--xh-bg-canvas);
|
|
62
70
|
--xh-_text-field-border: var(--xh-border-control);
|
|
63
71
|
--xh-_text-field-border-hover: var(--xh-border-control-hover);
|
|
64
|
-
--xh-_text-field-border-focus: var(--xh-text-field-input-border, var(--xh-_tone, var(--xh-border-control)));
|
|
72
|
+
--xh-_text-field-border-focus: var(--xh-text-field-input-border, var(--xh-_tone, var(--xh-border-control-focus)));
|
|
65
73
|
}
|
|
66
74
|
|
|
67
75
|
/* 填充式:底色顶替描边表达边界。描边只退成透明而不去掉,1px 的位置留着,
|
|
@@ -70,15 +78,15 @@
|
|
|
70
78
|
--xh-_text-field-bg: var(--xh-_tone-subtle, var(--xh-bg-subtle));
|
|
71
79
|
--xh-_text-field-border: transparent;
|
|
72
80
|
--xh-_text-field-border-hover: var(--xh-_tone-border, var(--xh-border-control-hover));
|
|
73
|
-
--xh-_text-field-border-focus: var(--xh-_tone, var(--xh-border-control));
|
|
81
|
+
--xh-_text-field-border-focus: var(--xh-_tone, var(--xh-border-control-focus));
|
|
74
82
|
}
|
|
75
83
|
|
|
76
|
-
/*
|
|
84
|
+
/* 无框:底与常态描边透明,悬停与聚焦浮出描边 */
|
|
77
85
|
[data-scope='text-field'][data-part='root'][data-variant='ghost'] {
|
|
78
86
|
--xh-_text-field-bg: transparent;
|
|
79
87
|
--xh-_text-field-border: transparent;
|
|
80
88
|
--xh-_text-field-border-hover: var(--xh-_tone-border, var(--xh-border-control-hover));
|
|
81
|
-
--xh-_text-field-border-focus: var(--xh-_tone, var(--xh-border-control));
|
|
89
|
+
--xh-_text-field-border-focus: var(--xh-_tone, var(--xh-border-control-focus));
|
|
82
90
|
}
|
|
83
91
|
|
|
84
92
|
[data-scope='text-field'][data-part='label'] {
|
|
@@ -92,7 +100,103 @@
|
|
|
92
100
|
color: var(--xh-text-field-label-fg-disabled, var(--xh-fg-subtle));
|
|
93
101
|
}
|
|
94
102
|
|
|
103
|
+
/* —— 一体式 control:输入框与清空按钮同框 —— */
|
|
104
|
+
/* control 是唯一的视觉盒:描边、底色、圆角、聚焦环全画在它身上,框内两件都退成透明分段。
|
|
105
|
+
:focus-within 而不是 :focus——持有焦点的是框里的输入框,被聚焦的"控件"在眼里是整个框 */
|
|
106
|
+
[data-scope='text-field'][data-part='control'] {
|
|
107
|
+
display: inline-flex;
|
|
108
|
+
align-items: center;
|
|
109
|
+
gap: var(--xh-text-field-control-gap, var(--xh-_text-field-gap));
|
|
110
|
+
min-inline-size: var(--xh-text-field-control-min-w, var(--xh-control-min-w));
|
|
111
|
+
block-size: var(--xh-text-field-control-h, var(--xh-_text-field-h));
|
|
112
|
+
padding-inline: var(--xh-text-field-control-px, var(--xh-_text-field-px));
|
|
113
|
+
border: var(--xh-stroke-thin) solid var(--xh-text-field-control-border, var(--xh-_text-field-border));
|
|
114
|
+
border-radius: var(--xh-text-field-control-radius, var(--xh-shape-control));
|
|
115
|
+
background: var(--xh-text-field-control-bg, var(--xh-_text-field-bg));
|
|
116
|
+
color: var(--xh-text-field-control-fg, var(--xh-fg-default));
|
|
117
|
+
transition: border-color var(--xh-motion-duration-micro) var(--xh-motion-ease-enter);
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
[data-scope='text-field'][data-part='control'][hidden] {
|
|
121
|
+
display: none;
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
/* hover 只在中性态换描边:invalid 与 at-limit 正拿边框颜色说事,
|
|
125
|
+
被 hover 盖掉那条信息就没了 */
|
|
126
|
+
[data-scope='text-field'][data-part='control']:hover:not([data-disabled], [data-invalid], [data-at-limit]) {
|
|
127
|
+
border-color: var(--xh-text-field-control-border-hover, var(--xh-_text-field-border-hover));
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
[data-scope='text-field'][data-part='control']:focus-within:not([data-disabled]) {
|
|
131
|
+
border-color: var(--xh-text-field-control-border-focus, var(--xh-_text-field-border-focus));
|
|
132
|
+
outline: var(--xh-ring-width) solid var(--xh-_text-field-ring);
|
|
133
|
+
outline-offset: var(--xh-ring-offset);
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
/* 顶到字数上限:再敲进不去,边框先给个提示。放在 invalid 之前,
|
|
137
|
+
两者同时成立时按源序让 invalid 赢 */
|
|
138
|
+
[data-scope='text-field'][data-part='control'][data-at-limit] {
|
|
139
|
+
border-color: var(--xh-text-field-control-border-at-limit, var(--xh-border-at-limit));
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
[data-scope='text-field'][data-part='control'][data-invalid] {
|
|
143
|
+
border-color: var(--xh-text-field-control-border-invalid, var(--xh-border-invalid));
|
|
144
|
+
|
|
145
|
+
/* 校验失败时环也跟着变红:两圈等宽相邻却一红一蓝,读的人不知道哪个才是当前状态 */
|
|
146
|
+
--xh-_text-field-ring: var(--xh-ring-invalid);
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
/* 只读仍可聚焦、可复制,所以不置灰,只把底色压下去表示"改不动" */
|
|
150
|
+
[data-scope='text-field'][data-part='control'][data-readonly] {
|
|
151
|
+
background: var(--xh-text-field-control-bg-readonly, var(--xh-bg-subtle));
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
[data-scope='text-field'][data-part='control'][data-disabled] {
|
|
155
|
+
background: var(--xh-text-field-control-bg-disabled, var(--xh-bg-subtle));
|
|
156
|
+
color: var(--xh-fg-disabled);
|
|
157
|
+
cursor: not-allowed;
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
/* 盒内 input:无边框无底无圆角,观感全归 control;行内内衬也归 control,
|
|
161
|
+
这里再留一份就是框内套了一圈空白。它占满剩余宽度,把清空按钮顶到最右 */
|
|
162
|
+
[data-scope='text-field'][data-part='control'] [data-part='input'] {
|
|
163
|
+
flex: 1 1 auto;
|
|
164
|
+
min-inline-size: 0;
|
|
165
|
+
block-size: 100%;
|
|
166
|
+
padding-inline: 0;
|
|
167
|
+
border: 0;
|
|
168
|
+
border-radius: 0;
|
|
169
|
+
background: transparent;
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
/* 盒内 input 不再自己画各态,全部交还 control。hover 这条带上与基础规则同样的
|
|
173
|
+
:not 条件:基础 hover 的特异度里有它们,不带就打不过 */
|
|
174
|
+
[data-scope='text-field'][data-part='control'] [data-part='input']:hover:not(:disabled, [data-invalid], [data-at-limit]) {
|
|
175
|
+
border-color: transparent;
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
[data-scope='text-field'][data-part='control'] [data-part='input']:focus-visible {
|
|
179
|
+
border-color: transparent;
|
|
180
|
+
outline: none;
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
[data-scope='text-field'][data-part='control'] [data-part='input'][data-at-limit],
|
|
184
|
+
[data-scope='text-field'][data-part='control'] [data-part='input'][data-invalid] {
|
|
185
|
+
border-color: transparent;
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
[data-scope='text-field'][data-part='control'] [data-part='input']:disabled,
|
|
189
|
+
[data-scope='text-field'][data-part='control'] [data-part='input'][readonly] {
|
|
190
|
+
background: transparent;
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
/* 尾部动作钮不参与分宽,宽度由它自己的方钮尺寸决定 */
|
|
194
|
+
[data-scope='text-field'][data-part='control'] [data-part='clear-trigger'] {
|
|
195
|
+
flex: none;
|
|
196
|
+
}
|
|
197
|
+
|
|
95
198
|
[data-scope='text-field'][data-part='input'] {
|
|
199
|
+
min-inline-size: var(--xh-text-field-input-min-w, var(--xh-control-min-w));
|
|
96
200
|
block-size: var(--xh-text-field-input-h, var(--xh-_text-field-h));
|
|
97
201
|
padding-inline: var(--xh-text-field-input-px, var(--xh-_text-field-px));
|
|
98
202
|
padding-block: 0;
|
|
@@ -141,11 +245,14 @@
|
|
|
141
245
|
/* 顶到字数上限:再敲进不去,边框先给个提示。放在 invalid 之前,
|
|
142
246
|
两者同时成立时按源序让 invalid 赢——真出错比"写满了"要紧 */
|
|
143
247
|
[data-scope='text-field'][data-part='input'][data-at-limit] {
|
|
144
|
-
border-color: var(--xh-text-field-input-border-at-limit, var(--xh-
|
|
248
|
+
border-color: var(--xh-text-field-input-border-at-limit, var(--xh-border-at-limit));
|
|
145
249
|
}
|
|
146
250
|
|
|
147
251
|
[data-scope='text-field'][data-part='input'][data-invalid] {
|
|
148
|
-
border-color: var(--xh-text-field-input-border-invalid, var(--xh-
|
|
252
|
+
border-color: var(--xh-text-field-input-border-invalid, var(--xh-border-invalid));
|
|
253
|
+
|
|
254
|
+
/* 校验失败时环也跟着变红:两圈等宽相邻却一红一蓝,读的人不知道哪个才是当前状态 */
|
|
255
|
+
--xh-_text-field-ring: var(--xh-ring-invalid);
|
|
149
256
|
}
|
|
150
257
|
|
|
151
258
|
/* 只读仍可聚焦、可复制,所以不置灰,只把底色压下去表示"改不动" */
|
|
@@ -160,41 +267,42 @@
|
|
|
160
267
|
cursor: not-allowed;
|
|
161
268
|
}
|
|
162
269
|
|
|
163
|
-
/*
|
|
164
|
-
|
|
270
|
+
/* 清空按钮是 input 的兄弟节点而不是子节点,由作者与 input 排成一行;
|
|
271
|
+
它按行内动作钮的尺寸画,在作者那一行里居中即与框对齐 */
|
|
165
272
|
[data-scope='text-field'][data-part='clear-trigger'] {
|
|
166
273
|
display: inline-flex;
|
|
167
274
|
flex: none;
|
|
168
275
|
align-items: center;
|
|
169
276
|
justify-content: center;
|
|
170
|
-
inline-size: var(--xh-text-field-
|
|
171
|
-
block-size: var(--xh-text-field-
|
|
277
|
+
inline-size: var(--xh-text-field-action-size, var(--xh-control-action-size));
|
|
278
|
+
block-size: var(--xh-text-field-action-size, var(--xh-control-action-size));
|
|
172
279
|
padding: 0;
|
|
173
280
|
border: 0;
|
|
174
|
-
border-radius: var(--xh-text-field-
|
|
175
|
-
background: var(--xh-text-field-
|
|
176
|
-
color: var(--xh-text-field-
|
|
281
|
+
border-radius: var(--xh-text-field-action-radius, var(--xh-shape-control));
|
|
282
|
+
background: var(--xh-text-field-action-bg, transparent);
|
|
283
|
+
color: var(--xh-text-field-action-fg, var(--xh-fg-muted));
|
|
177
284
|
font-family: inherit;
|
|
178
|
-
font-size: var(--xh-text-field-
|
|
285
|
+
font-size: var(--xh-text-field-action-font-size, var(--xh-_text-field-action-font-size));
|
|
179
286
|
line-height: var(--xh-leading-none);
|
|
180
287
|
cursor: pointer;
|
|
181
288
|
user-select: none;
|
|
182
|
-
transition: background var(--xh-motion-duration-micro) var(--xh-motion-ease-enter);
|
|
289
|
+
transition: background var(--xh-motion-duration-micro) var(--xh-motion-ease-enter), scale var(--xh-motion-duration-micro) var(--xh-motion-ease-enter);
|
|
183
290
|
}
|
|
184
291
|
|
|
185
|
-
/* 没开 clearable
|
|
292
|
+
/* 没开 clearable 或清不了时连接层给的是 hidden 属性;上面那条 display 会把 UA 规则盖掉,
|
|
186
293
|
少了这条按钮就一直杵在那儿 */
|
|
187
294
|
[data-scope='text-field'][data-part='clear-trigger'][hidden] {
|
|
188
295
|
display: none;
|
|
189
296
|
}
|
|
190
297
|
|
|
191
|
-
[data-scope='text-field'][data-part='clear-trigger']:hover
|
|
192
|
-
background: var(--xh-text-field-
|
|
193
|
-
color: var(--xh-text-field-
|
|
298
|
+
[data-scope='text-field'][data-part='clear-trigger']:hover {
|
|
299
|
+
background: var(--xh-text-field-action-bg-hover, var(--xh-bg-subtle-hover));
|
|
300
|
+
color: var(--xh-text-field-action-fg-hover, var(--xh-fg-default));
|
|
194
301
|
}
|
|
195
302
|
|
|
196
|
-
[data-scope='text-field'][data-part='clear-trigger']:active
|
|
197
|
-
background: var(--xh-text-field-
|
|
303
|
+
[data-scope='text-field'][data-part='clear-trigger']:active {
|
|
304
|
+
background: var(--xh-text-field-action-bg-active, var(--xh-bg-subtle-active));
|
|
305
|
+
scale: var(--xh-motion-scale-press);
|
|
198
306
|
}
|
|
199
307
|
|
|
200
308
|
/* 按钮不占 Tab 位(tabindex=-1)也不抢焦点,正常操作走不到这里;
|
|
@@ -204,10 +312,15 @@
|
|
|
204
312
|
outline-offset: var(--xh-ring-offset);
|
|
205
313
|
}
|
|
206
314
|
|
|
207
|
-
/*
|
|
208
|
-
[data-scope='text-field'][data-part='clear-trigger']:
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
315
|
+
/* 没写内容就由皮肤画兜底字形;作者往部件里塞了自己的图形,这几条即不命中 */
|
|
316
|
+
[data-scope='text-field'][data-part='clear-trigger']:empty::before {
|
|
317
|
+
content: '';
|
|
318
|
+
display: inline-block;
|
|
319
|
+
inline-size: var(--xh-icon-size, var(--xh-glyph-size-text));
|
|
320
|
+
block-size: var(--xh-icon-size, var(--xh-glyph-size-text));
|
|
321
|
+
vertical-align: var(--xh-glyph-baseline-shift);
|
|
322
|
+
background-color: currentColor;
|
|
323
|
+
-webkit-mask: var(--xh-glyph-mark-close) center / contain no-repeat;
|
|
324
|
+
mask: var(--xh-glyph-mark-close) center / contain no-repeat;
|
|
212
325
|
}
|
|
213
326
|
}
|
package/css/thread.css
CHANGED
|
@@ -7,6 +7,10 @@
|
|
|
7
7
|
/* 自建定位上下文,作为绝对定位的回到底部按钮的参照系;
|
|
8
8
|
block-size: 100% 让高度由外部决定,使滚动发生在内部。 */
|
|
9
9
|
[data-scope='thread'][data-part='root'] {
|
|
10
|
+
/* 组件内那几档层号只在自己人之间排序:建一个层叠上下文把它们关起来,
|
|
11
|
+
既不让页面上的层号插进来,也不让它们漏出去压住别人 */
|
|
12
|
+
isolation: isolate;
|
|
13
|
+
|
|
10
14
|
position: relative;
|
|
11
15
|
display: flex;
|
|
12
16
|
flex-direction: column;
|
|
@@ -20,14 +24,18 @@
|
|
|
20
24
|
|
|
21
25
|
/* 滚动容器,粘底读的是它的 scrollTop / clientHeight / scrollHeight。
|
|
22
26
|
min-block-size: 0 让弹性子项能被压缩从而触发溢出;
|
|
23
|
-
overscroll-behavior: contain
|
|
24
|
-
scrollbar-gutter: stable 避免滚动条出现与消失时推动文字。 */
|
|
27
|
+
overscroll-behavior: contain 阻止滚动量传给页面。 */
|
|
25
28
|
[data-scope='thread'][data-part='viewport'] {
|
|
26
29
|
flex: 1;
|
|
27
30
|
min-block-size: 0;
|
|
28
31
|
/* 逻辑属性 overflow-block 尚无可用实现,写物理轴 */
|
|
29
32
|
overflow-y: auto;
|
|
30
33
|
overscroll-behavior: contain;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
/* 还在用原生滚动条的视口留一条空道,滚动条出现与消失时不推动文字。
|
|
37
|
+
带 data-xh-scrollbar 的容器已经把原生条藏成零宽,这条空道对它没有布局作用,排除掉 */
|
|
38
|
+
[data-scope='thread'][data-part='viewport']:not([data-xh-scrollbar]) {
|
|
31
39
|
scrollbar-gutter: stable;
|
|
32
40
|
}
|
|
33
41
|
|
|
@@ -66,7 +74,7 @@
|
|
|
66
74
|
border-radius: var(--xh-thread-scroll-button-radius, var(--xh-shape-pill));
|
|
67
75
|
background: var(--xh-thread-scroll-button-bg, var(--xh-bg-surface));
|
|
68
76
|
color: var(--xh-thread-scroll-button-fg, var(--xh-fg-default));
|
|
69
|
-
box-shadow: var(--xh-thread-scroll-button-shadow, var(--xh-elevation-
|
|
77
|
+
box-shadow: var(--xh-thread-scroll-button-shadow, var(--xh-elevation-sheet));
|
|
70
78
|
/* 按钮默认不继承页面字族,显式继承 */
|
|
71
79
|
font-family: inherit;
|
|
72
80
|
font-size: var(--xh-thread-scroll-button-font-size, var(--xh-text-label-size));
|
package/css/time-field.css
CHANGED
|
@@ -6,11 +6,15 @@
|
|
|
6
6
|
|
|
7
7
|
/* 与文本框、数字框同一套堆叠:标签一行、控件一行 */
|
|
8
8
|
[data-scope='time-field'][data-part='root'] {
|
|
9
|
+
/* 作者塞进来的图标跟着控件的尺寸档走;它自己写了 size 时仍以作者的为准 */
|
|
10
|
+
--xh-icon-size: var(--xh-time-field-icon-size, var(--xh-glyph-size-md));
|
|
11
|
+
|
|
9
12
|
/* 尺寸档只换这四个私有槽,标题与控件都从 root 继承它们,换档不必给每个部件各写一条选择器 */
|
|
10
13
|
--xh-_time-field-control-h: var(--xh-control-h-md);
|
|
11
14
|
--xh-_time-field-control-px: var(--xh-control-px-md);
|
|
12
|
-
--xh-_time-field-
|
|
13
|
-
--xh-_time-field-
|
|
15
|
+
--xh-_time-field-gap: var(--xh-control-gap-md);
|
|
16
|
+
--xh-_time-field-font-size: var(--xh-control-font-md);
|
|
17
|
+
--xh-_time-field-label-font-size: var(--xh-control-font-md);
|
|
14
18
|
/* 形态档只换这三个私有槽:底色与两档描边 */
|
|
15
19
|
--xh-_time-field-control-bg: var(--xh-bg-canvas);
|
|
16
20
|
--xh-_time-field-control-border: var(--xh-border-control);
|
|
@@ -27,17 +31,21 @@
|
|
|
27
31
|
|
|
28
32
|
/* —— 尺寸 —— */
|
|
29
33
|
[data-scope='time-field'][data-part='root'][data-size='sm'] {
|
|
34
|
+
--xh-icon-size: var(--xh-time-field-icon-size, var(--xh-glyph-size-sm));
|
|
30
35
|
--xh-_time-field-control-h: var(--xh-control-h-sm);
|
|
31
36
|
--xh-_time-field-control-px: var(--xh-control-px-sm);
|
|
32
|
-
--xh-_time-field-
|
|
33
|
-
--xh-_time-field-
|
|
37
|
+
--xh-_time-field-gap: var(--xh-control-gap-sm);
|
|
38
|
+
--xh-_time-field-font-size: var(--xh-control-font-sm);
|
|
39
|
+
--xh-_time-field-label-font-size: var(--xh-control-font-sm);
|
|
34
40
|
}
|
|
35
41
|
|
|
36
42
|
[data-scope='time-field'][data-part='root'][data-size='lg'] {
|
|
43
|
+
--xh-icon-size: var(--xh-time-field-icon-size, var(--xh-glyph-size-lg));
|
|
37
44
|
--xh-_time-field-control-h: var(--xh-control-h-lg);
|
|
38
45
|
--xh-_time-field-control-px: var(--xh-control-px-lg);
|
|
39
|
-
--xh-_time-field-
|
|
40
|
-
--xh-_time-field-
|
|
46
|
+
--xh-_time-field-gap: var(--xh-control-gap-lg);
|
|
47
|
+
--xh-_time-field-font-size: var(--xh-control-font-lg);
|
|
48
|
+
--xh-_time-field-label-font-size: var(--xh-control-font-lg);
|
|
41
49
|
}
|
|
42
50
|
|
|
43
51
|
/* —— 形态 —— */
|
|
@@ -55,11 +63,11 @@
|
|
|
55
63
|
--xh-_time-field-control-border-hover: var(--xh-_tone-border, var(--xh-border-control-hover));
|
|
56
64
|
}
|
|
57
65
|
|
|
58
|
-
/*
|
|
66
|
+
/* 无框:底与常态描边透明,悬停与聚焦浮出描边 */
|
|
59
67
|
[data-scope='time-field'][data-part='root'][data-variant='ghost'] {
|
|
60
68
|
--xh-_time-field-control-bg: transparent;
|
|
61
69
|
--xh-_time-field-control-border: transparent;
|
|
62
|
-
--xh-_time-field-control-border-hover:
|
|
70
|
+
--xh-_time-field-control-border-hover: var(--xh-_tone-border, var(--xh-border-control-hover));
|
|
63
71
|
}
|
|
64
72
|
|
|
65
73
|
/* 声明了 display 就盖掉了 UA 的 [hidden]{display:none},收起态得自己还回去 */
|
|
@@ -72,9 +80,6 @@
|
|
|
72
80
|
font-size: var(--xh-time-field-label-font-size, var(--xh-_time-field-label-font-size));
|
|
73
81
|
font-weight: var(--xh-time-field-label-font-weight, var(--xh-text-label-weight));
|
|
74
82
|
line-height: var(--xh-leading-none);
|
|
75
|
-
/* 点标题会把焦点送到第一段(段不是能被 for 指向的原生控件,这条由连接层接管),
|
|
76
|
-
指针得如实反映它可点 */
|
|
77
|
-
cursor: pointer;
|
|
78
83
|
}
|
|
79
84
|
|
|
80
85
|
[data-scope='time-field'][data-part='label'][data-disabled] {
|
|
@@ -86,7 +91,9 @@
|
|
|
86
91
|
段自己只管一小块可聚焦的高亮区 */
|
|
87
92
|
[data-scope='time-field'][data-part='control'] {
|
|
88
93
|
display: inline-flex;
|
|
94
|
+
min-inline-size: var(--xh-time-field-control-min-w, var(--xh-control-min-w));
|
|
89
95
|
align-items: center;
|
|
96
|
+
gap: var(--xh-time-field-control-gap, var(--xh-_time-field-gap));
|
|
90
97
|
block-size: var(--xh-time-field-control-h, var(--xh-_time-field-control-h));
|
|
91
98
|
padding-inline: var(--xh-time-field-control-px, var(--xh-_time-field-control-px));
|
|
92
99
|
padding-block: 0;
|
|
@@ -115,11 +122,16 @@
|
|
|
115
122
|
/* 焦点真正落在段上,但整块看起来才是一个控件:段内有焦点时整框亮起来。
|
|
116
123
|
control 自己不占 Tab 位,所以这里写的是 focus-within 而不是 focus-visible */
|
|
117
124
|
[data-scope='time-field'][data-part='control']:focus-within:not([data-disabled]) {
|
|
118
|
-
border-color: var(--xh-time-field-control-border-focus, var(--xh-
|
|
125
|
+
border-color: var(--xh-time-field-control-border-focus, var(--xh-_tone, var(--xh-border-control-focus)));
|
|
126
|
+
outline: var(--xh-ring-width) solid var(--xh-_time-field-ring);
|
|
127
|
+
outline-offset: var(--xh-ring-offset);
|
|
119
128
|
}
|
|
120
129
|
|
|
121
130
|
[data-scope='time-field'][data-part='control'][data-invalid] {
|
|
122
|
-
border-color: var(--xh-time-field-control-border-invalid, var(--xh-
|
|
131
|
+
border-color: var(--xh-time-field-control-border-invalid, var(--xh-border-invalid));
|
|
132
|
+
|
|
133
|
+
/* 校验失败时环也跟着变红:两圈等宽相邻却一红一蓝,读的人不知道哪个才是当前状态 */
|
|
134
|
+
--xh-_time-field-ring: var(--xh-ring-invalid);
|
|
123
135
|
}
|
|
124
136
|
|
|
125
137
|
/* 只读仍可聚焦、可换段,所以不置灰,只把底色压下去表示"改不动" */
|
|
@@ -134,13 +146,25 @@
|
|
|
134
146
|
cursor: not-allowed;
|
|
135
147
|
}
|
|
136
148
|
|
|
137
|
-
/*
|
|
138
|
-
|
|
149
|
+
/* 段位与作者写在段间的分隔符都在这一层里:它占满盒里剩下的宽度,
|
|
150
|
+
清空钮因此靠在框内末端 */
|
|
151
|
+
[data-scope='time-field'][data-part='segment-group'] {
|
|
152
|
+
display: inline-flex;
|
|
153
|
+
flex: 1 1 auto;
|
|
154
|
+
align-items: center;
|
|
155
|
+
min-inline-size: 0;
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
[data-scope='time-field'][data-part='segment-group'][hidden] {
|
|
159
|
+
display: none;
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
/* 段是一小块可聚焦区,紧挨着排;间距长在段自己身上 */
|
|
139
163
|
[data-scope='time-field'][data-part='segment'] {
|
|
140
164
|
display: inline-block;
|
|
141
|
-
padding-inline: var(--xh-time-field-segment-px, var(--xh-space-
|
|
165
|
+
padding-inline: var(--xh-time-field-segment-px, var(--xh-space-1));
|
|
142
166
|
padding-block: 0;
|
|
143
|
-
border-radius: var(--xh-time-field-segment-radius, var(--xh-
|
|
167
|
+
border-radius: var(--xh-time-field-segment-radius, var(--xh-shape-inset));
|
|
144
168
|
color: inherit;
|
|
145
169
|
font-variant-numeric: inherit;
|
|
146
170
|
text-align: center;
|
|
@@ -159,7 +183,7 @@
|
|
|
159
183
|
|
|
160
184
|
/* 还没填的段压成弱色:一行里哪几段是占位符,一眼要看得出来 */
|
|
161
185
|
[data-scope='time-field'][data-part='segment'][data-placeholder] {
|
|
162
|
-
color: var(--xh-time-field-
|
|
186
|
+
color: var(--xh-time-field-placeholder-fg, var(--xh-fg-subtle));
|
|
163
187
|
}
|
|
164
188
|
|
|
165
189
|
/* 一行段长得差不多,光有边框亮起来看不出正在改哪一段:当前段必须自己有底色。
|
|
@@ -187,6 +211,63 @@
|
|
|
187
211
|
cursor: not-allowed;
|
|
188
212
|
}
|
|
189
213
|
|
|
214
|
+
/* 清空按钮贴在框内末端:不占宽度也不撑高 control,有值时才显形。
|
|
215
|
+
靠段位外壳的 flex:1 顶到末端,自己不写 margin */
|
|
216
|
+
[data-scope='time-field'][data-part='clear-trigger'] {
|
|
217
|
+
display: inline-flex;
|
|
218
|
+
flex: none;
|
|
219
|
+
align-items: center;
|
|
220
|
+
justify-content: center;
|
|
221
|
+
inline-size: var(--xh-time-field-action-size, var(--xh-control-action-size));
|
|
222
|
+
block-size: var(--xh-time-field-action-size, var(--xh-control-action-size));
|
|
223
|
+
padding: 0;
|
|
224
|
+
border: 0;
|
|
225
|
+
border-radius: var(--xh-time-field-action-radius, var(--xh-shape-control));
|
|
226
|
+
background: var(--xh-time-field-action-bg, transparent);
|
|
227
|
+
color: var(--xh-time-field-action-fg, var(--xh-fg-muted));
|
|
228
|
+
font-family: inherit;
|
|
229
|
+
font-size: var(--xh-time-field-action-font-size, var(--xh-text-secondary-size));
|
|
230
|
+
line-height: var(--xh-leading-none);
|
|
231
|
+
cursor: pointer;
|
|
232
|
+
user-select: none;
|
|
233
|
+
transition:
|
|
234
|
+
background var(--xh-motion-duration-micro) var(--xh-motion-ease-enter),
|
|
235
|
+
scale var(--xh-motion-duration-micro) var(--xh-motion-ease-enter);
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
/* 没值时连接层给的是 hidden 属性;上面那条 display 会把 UA 规则盖掉 */
|
|
239
|
+
[data-scope='time-field'][data-part='clear-trigger'][hidden] {
|
|
240
|
+
display: none;
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
[data-scope='time-field'][data-part='clear-trigger']:hover {
|
|
244
|
+
background: var(--xh-time-field-action-bg-hover, var(--xh-bg-subtle-hover));
|
|
245
|
+
color: var(--xh-time-field-action-fg-hover, var(--xh-fg-default));
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
[data-scope='time-field'][data-part='clear-trigger']:active {
|
|
249
|
+
background: var(--xh-time-field-action-bg-active, var(--xh-bg-subtle-active));
|
|
250
|
+
scale: var(--xh-motion-scale-press);
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
/* 按钮不占 Tab 位(tabindex=-1),这条是给程序化聚焦兜底:落焦时得看得见 */
|
|
254
|
+
[data-scope='time-field'][data-part='clear-trigger']:focus-visible {
|
|
255
|
+
outline: var(--xh-ring-width) solid var(--xh-_time-field-ring);
|
|
256
|
+
outline-offset: var(--xh-ring-offset);
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
/* 没写内容就由皮肤画兜底字形;作者往部件里塞了自己的图形,这条即不命中 */
|
|
260
|
+
[data-scope='time-field'][data-part='clear-trigger']:empty::before {
|
|
261
|
+
content: '';
|
|
262
|
+
display: inline-block;
|
|
263
|
+
inline-size: var(--xh-icon-size, var(--xh-glyph-size-text));
|
|
264
|
+
block-size: var(--xh-icon-size, var(--xh-glyph-size-text));
|
|
265
|
+
vertical-align: var(--xh-glyph-baseline-shift);
|
|
266
|
+
background-color: currentColor;
|
|
267
|
+
-webkit-mask: var(--xh-glyph-mark-close) center / contain no-repeat;
|
|
268
|
+
mask: var(--xh-glyph-mark-close) center / contain no-repeat;
|
|
269
|
+
}
|
|
270
|
+
|
|
190
271
|
/* 连接层把它写成 type=hidden,UA 自己就不渲染;这里的视觉隐藏是给元素升级前那一瞬兜底
|
|
191
272
|
(作者手写的是一个普通 input,升级完成前它是可见的文本框)。
|
|
192
273
|
刻意不写 display:写了反而会盖掉 UA 对 type=hidden 的收起,把它显出来 */
|