@xihan-ui/styles 1.0.0-alpha.1 → 1.0.0-alpha.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (129) hide show
  1. package/CHANGELOG.md +527 -0
  2. package/README.md +1 -1
  3. package/css/accordion.css +61 -5
  4. package/css/affix.css +5 -0
  5. package/css/alert.css +35 -5
  6. package/css/anchor.css +12 -7
  7. package/css/avatar-group.css +8 -3
  8. package/css/avatar.css +8 -3
  9. package/css/back-top.css +21 -1
  10. package/css/badge.css +21 -2
  11. package/css/breadcrumb.css +29 -4
  12. package/css/button-group.css +19 -13
  13. package/css/button.css +57 -11
  14. package/css/calendar.css +124 -2
  15. package/css/card.css +10 -5
  16. package/css/carousel.css +41 -5
  17. package/css/cascader.css +188 -102
  18. package/css/checkbox-group.css +46 -19
  19. package/css/checkbox.css +59 -8
  20. package/css/clipboard.css +7 -1
  21. package/css/code-block.css +17 -7
  22. package/css/collapsible.css +47 -2
  23. package/css/color-picker.css +117 -46
  24. package/css/combobox.css +132 -52
  25. package/css/composer.css +10 -3
  26. package/css/context-menu.css +101 -75
  27. package/css/countdown.css +5 -0
  28. package/css/date-field.css +96 -14
  29. package/css/date-picker.css +281 -65
  30. package/css/descriptions.css +7 -2
  31. package/css/dialog.css +109 -22
  32. package/css/download-trigger.css +76 -0
  33. package/css/drawer.css +75 -23
  34. package/css/dynamic-input.css +73 -17
  35. package/css/editable.css +17 -10
  36. package/css/ellipsis.css +6 -1
  37. package/css/empty-state.css +12 -7
  38. package/css/field.css +14 -6
  39. package/css/fieldset.css +69 -0
  40. package/css/file-upload.css +50 -7
  41. package/css/flex.css +5 -0
  42. package/css/float-button.css +21 -1
  43. package/css/floating-panel.css +310 -0
  44. package/css/form.css +10 -5
  45. package/css/gradient-text.css +5 -0
  46. package/css/grid.css +5 -0
  47. package/css/heatmap.css +410 -0
  48. package/css/highlight.css +6 -1
  49. package/css/hotkeys.css +90 -0
  50. package/css/hover-card.css +58 -50
  51. package/css/icon-wrapper.css +5 -0
  52. package/css/icon.css +5 -0
  53. package/css/image-cropper.css +231 -0
  54. package/css/image-viewer.css +167 -22
  55. package/css/image.css +7 -2
  56. package/css/infinite-scroll.css +6 -1
  57. package/css/json-viewer.css +241 -0
  58. package/css/layout.css +11 -10
  59. package/css/list.css +13 -8
  60. package/css/listbox.css +25 -4
  61. package/css/loading-bar.css +12 -1
  62. package/css/log.css +6 -1
  63. package/css/marquee.css +14 -0
  64. package/css/masonry.css +63 -0
  65. package/css/mention.css +105 -32
  66. package/css/menu.css +131 -46
  67. package/css/menubar.css +150 -66
  68. package/css/navigation-menu.css +59 -29
  69. package/css/number-animation.css +8 -3
  70. package/css/number-field.css +178 -16
  71. package/css/overlay-arrow.css +51 -0
  72. package/css/page-header.css +10 -5
  73. package/css/pagination.css +18 -13
  74. package/css/password-input.css +356 -0
  75. package/css/pin-input.css +18 -10
  76. package/css/popconfirm.css +73 -16
  77. package/css/popover.css +88 -44
  78. package/css/popselect.css +201 -52
  79. package/css/progress.css +52 -7
  80. package/css/qr-code.css +6 -1
  81. package/css/radio-group.css +19 -8
  82. package/css/rating.css +7 -2
  83. package/css/reset.css +17 -0
  84. package/css/result.css +11 -6
  85. package/css/scroll-area.css +65 -94
  86. package/css/scrollbar.css +167 -0
  87. package/css/segmented.css +215 -0
  88. package/css/select.css +292 -124
  89. package/css/separator.css +7 -2
  90. package/css/side-nav.css +116 -19
  91. package/css/signature-pad.css +144 -0
  92. package/css/skeleton.css +12 -1
  93. package/css/slider.css +15 -10
  94. package/css/space.css +117 -0
  95. package/css/spinner.css +31 -11
  96. package/css/splitter.css +5 -0
  97. package/css/statistic.css +14 -9
  98. package/css/steps.css +30 -8
  99. package/css/switch.css +62 -13
  100. package/css/table.css +136 -37
  101. package/css/tabs.css +9 -4
  102. package/css/tag.css +177 -0
  103. package/css/tags-input.css +83 -40
  104. package/css/text-field.css +154 -36
  105. package/css/thread.css +6 -1
  106. package/css/time-field.css +102 -16
  107. package/css/time-picker.css +264 -69
  108. package/css/time.css +5 -0
  109. package/css/timeline.css +15 -10
  110. package/css/timer.css +119 -0
  111. package/css/toast.css +46 -21
  112. package/css/toaster.css +6 -1
  113. package/css/toggle-group.css +5 -0
  114. package/css/toggle.css +11 -6
  115. package/css/tone.css +10 -5
  116. package/css/toolbar.css +6 -1
  117. package/css/tooltip.css +54 -38
  118. package/css/tour.css +128 -63
  119. package/css/transfer.css +73 -17
  120. package/css/tree-select.css +203 -83
  121. package/css/tree.css +90 -1
  122. package/css/typography.css +9 -4
  123. package/css/undefined.css +11 -1
  124. package/css/virtualizer.css +8 -1
  125. package/css/watermark.css +6 -2
  126. package/index.css +17 -1
  127. package/index.unlayered.css +9394 -2883
  128. package/package.json +19 -4
  129. package/css/motion.css +0 -58
@@ -1,11 +1,102 @@
1
1
  @layer xihan.components {
2
+ /* 皮肤在场的标记:开发模式下按 scope 探一次,取不到就说明这份皮肤没被引入。 */
3
+ [data-scope='time-picker'] {
4
+ --xh-time-picker-skin: 1;
5
+ }
6
+
7
+ /* 坐标由定位引擎写进 style(inset-inline-start / inset-block-start),这里只定位模式与层级 */
8
+ [data-scope='time-picker'][data-part='positioner'] {
9
+ position: fixed;
10
+ z-index: var(--xh-time-picker-layer, var(--xh-layer-popover));
11
+ /* 空壳不吃指针,交互只发生在 content 里 */
12
+ pointer-events: none;
13
+ }
14
+
15
+ /* 锚点被滚出可视区:整个浮层随之收起 */
16
+ [data-scope='time-picker'][data-part='positioner'][data-hidden] {
17
+ visibility: hidden;
18
+ }
19
+
20
+ /* 私有槽同时声明在根与 positioner 上:浮层被搬到 portal 落点,不是根的后代,继承不过去 */
21
+ [data-scope='time-picker']:is([data-part='root'], [data-part='positioner']) {
22
+ /* 尺寸档只换这几个私有槽,标题、输入行与浮层里的格子都从这两处继承它们,
23
+ 换档不必给每个部件各写一条选择器 */
24
+ --xh-_time-picker-control-h: var(--xh-control-h-md);
25
+ --xh-_time-picker-control-px: var(--xh-control-px-md);
26
+ --xh-_time-picker-gap: var(--xh-control-gap-md);
27
+ --xh-_time-picker-font-size: var(--xh-text-body-size);
28
+ --xh-_time-picker-label-font-size: var(--xh-text-label-size);
29
+ --xh-_time-picker-item-px: var(--xh-control-px-md);
30
+
31
+ /* 形态档只换这三个私有槽:底色与两档描边 */
32
+ --xh-_time-picker-control-bg: var(--xh-bg-canvas);
33
+ --xh-_time-picker-control-border: var(--xh-border-control);
34
+ --xh-_time-picker-control-border-hover: var(--xh-border-control-hover);
35
+
36
+ /* 聚焦环、段位反白与列里的选中随语气走。没写 data-tone 时这几个 --xh-_tone* 没被声明,
37
+ 退回原来的焦点色与品牌色 */
38
+ --xh-_time-picker-ring: var(--xh-ring-focus);
39
+ --xh-_time-picker-accent: var(--xh-_tone, var(--xh-bg-brand));
40
+ --xh-_time-picker-accent-hover: var(--xh-_tone-hover, var(--xh-bg-brand-hover));
41
+ --xh-_time-picker-accent-fg: var(--xh-_tone-on, var(--xh-fg-on-brand));
42
+ }
43
+
2
44
  /* 与文本框、时间输入同一套堆叠:标签一行、控件一行 */
3
45
  [data-scope='time-picker'][data-part='root'] {
46
+ /* 作者塞进指示符槽的图标跟着字号走,与皮肤画的兜底字形同一把尺 */
47
+ --xh-icon-size: var(--xh-time-picker-icon-size, var(--xh-glyph-size-md));
48
+
4
49
  display: inline-flex;
5
50
  flex-direction: column;
6
51
  gap: var(--xh-time-picker-gap, var(--xh-space-1));
7
52
  }
8
53
 
54
+ /* —— 尺寸 —— */
55
+ /* 缺省档写在上面的基础规则里 */
56
+ [data-scope='time-picker']:is([data-part='root'], [data-part='positioner'])[data-size='sm'] {
57
+ --xh-icon-size: var(--xh-time-picker-icon-size, var(--xh-glyph-size-sm));
58
+ --xh-_time-picker-control-h: var(--xh-control-h-sm);
59
+ --xh-_time-picker-control-px: var(--xh-control-px-sm);
60
+ --xh-_time-picker-gap: var(--xh-control-gap-sm);
61
+ --xh-_time-picker-font-size: var(--xh-control-font-sm);
62
+ --xh-_time-picker-label-font-size: var(--xh-control-font-sm);
63
+ --xh-_time-picker-item-px: var(--xh-control-px-sm);
64
+ }
65
+
66
+ [data-scope='time-picker']:is([data-part='root'], [data-part='positioner'])[data-size='lg'] {
67
+ --xh-icon-size: var(--xh-time-picker-icon-size, var(--xh-glyph-size-lg));
68
+ --xh-_time-picker-control-h: var(--xh-control-h-lg);
69
+ --xh-_time-picker-control-px: var(--xh-control-px-lg);
70
+ --xh-_time-picker-gap: var(--xh-control-gap-lg);
71
+ --xh-_time-picker-font-size: var(--xh-control-font-lg);
72
+ --xh-_time-picker-label-font-size: var(--xh-control-font-lg);
73
+ --xh-_time-picker-item-px: var(--xh-control-px-lg);
74
+ }
75
+
76
+ /* —— 形态 —— */
77
+ /* 输入类不做实心档:填满一个要往里打字的框,字与底就没法同时读。
78
+ 形态只决定底与描边怎么画,用哪族颜色由 data-tone 决定 */
79
+ [data-scope='time-picker']:is([data-part='root'], [data-part='positioner'])[data-variant='outline'] {
80
+ --xh-_time-picker-control-bg: var(--xh-bg-canvas);
81
+ --xh-_time-picker-control-border: var(--xh-border-control);
82
+ --xh-_time-picker-control-border-hover: var(--xh-border-control-hover);
83
+ }
84
+
85
+ /* 填充式:底色顶替描边表达边界。描边只退成透明而不去掉,1px 的位置留着,
86
+ 与 outline 档并排时基线对得上、聚焦画描边也不引起跳动 */
87
+ [data-scope='time-picker']:is([data-part='root'], [data-part='positioner'])[data-variant='subtle'] {
88
+ --xh-_time-picker-control-bg: var(--xh-_tone-subtle, var(--xh-bg-subtle));
89
+ --xh-_time-picker-control-border: transparent;
90
+ --xh-_time-picker-control-border-hover: var(--xh-_tone-border, var(--xh-border-control-hover));
91
+ }
92
+
93
+ /* 无框:底与常态描边透明,悬停与聚焦浮出描边 */
94
+ [data-scope='time-picker']:is([data-part='root'], [data-part='positioner'])[data-variant='ghost'] {
95
+ --xh-_time-picker-control-bg: transparent;
96
+ --xh-_time-picker-control-border: transparent;
97
+ --xh-_time-picker-control-border-hover: var(--xh-_tone-border, var(--xh-border-control-hover));
98
+ }
99
+
9
100
  /* 声明了 display 就盖掉了 UA 的 [hidden]{display:none},收起态得自己还回去 */
10
101
  [data-scope='time-picker'][data-part='root'][hidden] {
11
102
  display: none;
@@ -13,12 +104,9 @@
13
104
 
14
105
  [data-scope='time-picker'][data-part='label'] {
15
106
  color: var(--xh-time-picker-label-fg, var(--xh-fg-default));
16
- font-size: var(--xh-time-picker-label-font-size, var(--xh-text-label-size));
107
+ font-size: var(--xh-time-picker-label-font-size, var(--xh-_time-picker-label-font-size));
17
108
  font-weight: var(--xh-time-picker-label-font-weight, var(--xh-text-label-weight));
18
109
  line-height: var(--xh-leading-none);
19
- /* 点标题会把焦点送到第一段(段不是能被 for 指向的原生控件,这条由连接层接管),
20
- 指针得如实反映它可点 */
21
- cursor: pointer;
22
110
  }
23
111
 
24
112
  [data-scope='time-picker'][data-part='label'][data-disabled] {
@@ -29,19 +117,20 @@
29
117
  /* 画成一个框的是 control:几段文字、展开按钮、清空按钮要看起来是一体的,
30
118
  边框长在其中任何一个身上都会把另外几个割在框外 */
31
119
  [data-scope='time-picker'][data-part='control'] {
120
+ min-inline-size: var(--xh-time-picker-control-min-w, var(--xh-control-min-w));
32
121
  display: inline-flex;
33
122
  align-items: center;
34
- gap: var(--xh-time-picker-control-gap, var(--xh-control-gap-md));
35
- block-size: var(--xh-time-picker-control-h, var(--xh-control-h-md));
36
- padding-inline: var(--xh-time-picker-control-px, var(--xh-control-px-md));
123
+ gap: var(--xh-time-picker-control-gap, var(--xh-_time-picker-gap));
124
+ block-size: var(--xh-time-picker-control-h, var(--xh-_time-picker-control-h));
125
+ padding-inline: var(--xh-time-picker-control-px, var(--xh-_time-picker-control-px));
37
126
  padding-block: 0;
38
- border: var(--xh-stroke-thin) solid var(--xh-time-picker-control-border, var(--xh-border-control));
127
+ border: var(--xh-stroke-thin) solid var(--xh-time-picker-control-border, var(--xh-_time-picker-control-border));
39
128
  border-radius: var(--xh-time-picker-control-radius, var(--xh-shape-control));
40
- background: var(--xh-time-picker-control-bg, var(--xh-bg-canvas));
129
+ background: var(--xh-time-picker-control-bg, var(--xh-_time-picker-control-bg));
41
130
  color: var(--xh-time-picker-control-fg, var(--xh-fg-default));
42
131
  /* 表单控件不继承页面字体,只给字号会让它用 UA 默认字族,与周围文本对不上 */
43
132
  font-family: inherit;
44
- font-size: var(--xh-time-picker-font-size, var(--xh-text-body-size));
133
+ font-size: var(--xh-time-picker-font-size, var(--xh-_time-picker-font-size));
45
134
  /* 等宽数字:各位字宽不一时逐段填入会让整行左右跳 */
46
135
  font-variant-numeric: tabular-nums;
47
136
  line-height: var(--xh-leading-normal);
@@ -54,17 +143,22 @@
54
143
 
55
144
  /* hover 只在中性态换描边:invalid 正拿边框颜色说事,被 hover 盖掉那条信息就没了 */
56
145
  [data-scope='time-picker'][data-part='control']:hover:not([data-disabled], [data-invalid]) {
57
- border-color: var(--xh-time-picker-control-border-hover, var(--xh-border-control-hover));
146
+ border-color: var(--xh-time-picker-control-border-hover, var(--xh-_time-picker-control-border-hover));
58
147
  }
59
148
 
60
149
  /* 焦点真正落在段或按钮上,但整块看起来才是一个控件:内部有焦点时整框亮起来。
61
150
  control 自己不占 Tab 位,所以这里写的是 focus-within 而不是 focus-visible */
62
151
  [data-scope='time-picker'][data-part='control']:focus-within:not([data-disabled]) {
63
- border-color: var(--xh-time-picker-control-border-focus, var(--xh-ring-focus));
152
+ border-color: var(--xh-time-picker-control-border-focus, var(--xh-_tone, var(--xh-border-control-focus)));
153
+ outline: var(--xh-ring-width) solid var(--xh-_time-picker-ring);
154
+ outline-offset: var(--xh-ring-offset);
64
155
  }
65
156
 
66
157
  [data-scope='time-picker'][data-part='control'][data-invalid] {
67
- border-color: var(--xh-time-picker-control-border-invalid, var(--xh-color-danger-500));
158
+ border-color: var(--xh-time-picker-control-border-invalid, var(--xh-border-invalid));
159
+
160
+ /* 校验失败时环也跟着变红:两圈等宽相邻却一红一蓝,读的人不知道哪个才是当前状态 */
161
+ --xh-_time-picker-ring: var(--xh-ring-invalid);
68
162
  }
69
163
 
70
164
  /* 只读仍可聚焦、可换段,所以不置灰,只把底色压下去表示"改不动" */
@@ -79,13 +173,25 @@
79
173
  cursor: not-allowed;
80
174
  }
81
175
 
82
- /* 每一段是一小块可聚焦区,紧挨着排;分隔符由作者写在段与段之间的普通节点里,
83
- 不在角色表内,所以间距只能长在段自己身上 */
176
+ /* 段位与作者写在段间的分隔符都在这一层里:它占满盒里剩下的宽度,
177
+ 尾部按钮因此靠在框内末端 */
178
+ [data-scope='time-picker'][data-part='segment-group'] {
179
+ display: inline-flex;
180
+ flex: 1 1 auto;
181
+ align-items: center;
182
+ min-inline-size: 0;
183
+ }
184
+
185
+ [data-scope='time-picker'][data-part='segment-group'][hidden] {
186
+ display: none;
187
+ }
188
+
189
+ /* 每一段是一小块可聚焦区,紧挨着排;间距长在段自己身上 */
84
190
  [data-scope='time-picker'][data-part='input'] {
85
191
  display: inline-block;
86
- padding-inline: var(--xh-time-picker-segment-px, var(--xh-space-0_5));
192
+ padding-inline: var(--xh-time-picker-segment-px, var(--xh-space-1));
87
193
  padding-block: 0;
88
- border-radius: var(--xh-time-picker-segment-radius, var(--xh-radius-sm));
194
+ border-radius: var(--xh-time-picker-segment-radius, var(--xh-shape-inset));
89
195
  color: inherit;
90
196
  font-variant-numeric: inherit;
91
197
  text-align: center;
@@ -104,21 +210,21 @@
104
210
 
105
211
  /* 还没填的段压成弱色:一行里哪几段是占位符,一眼要看得出来 */
106
212
  [data-scope='time-picker'][data-part='input'][data-placeholder] {
107
- color: var(--xh-time-picker-segment-fg-placeholder, var(--xh-fg-subtle));
213
+ color: var(--xh-time-picker-placeholder-fg, var(--xh-fg-subtle));
108
214
  }
109
215
 
110
216
  /* 一行段长得差不多,光有边框亮起来看不出正在改哪一段:当前段必须自己有底色。
111
217
  data-focus 由机器给(它知道谁是当前段),:focus-visible 兜住机器状态还没回流的那一帧 */
112
218
  [data-scope='time-picker'][data-part='input'][data-focus]:not([data-disabled]),
113
219
  [data-scope='time-picker'][data-part='input']:focus-visible {
114
- background: var(--xh-time-picker-segment-bg-focus, var(--xh-bg-brand));
115
- color: var(--xh-time-picker-segment-fg-focus, var(--xh-fg-on-brand));
220
+ background: var(--xh-time-picker-segment-bg-focus, var(--xh-_time-picker-accent));
221
+ color: var(--xh-time-picker-segment-fg-focus, var(--xh-_time-picker-accent-fg));
116
222
  outline: none;
117
223
  }
118
224
 
119
225
  /* 焦点态用了品牌底色之后,占位符那条弱色会被它盖住,这里明确让位给焦点态 */
120
226
  [data-scope='time-picker'][data-part='input'][data-focus][data-placeholder]:not([data-disabled]) {
121
- color: var(--xh-time-picker-segment-fg-focus, var(--xh-fg-on-brand));
227
+ color: var(--xh-time-picker-segment-fg-focus, var(--xh-_time-picker-accent-fg));
122
228
  }
123
229
 
124
230
  [data-scope='time-picker'][data-part='input']:hover:not([data-focus], [data-disabled]) {
@@ -146,82 +252,75 @@
146
252
  background: var(--xh-time-picker-action-bg, transparent);
147
253
  color: var(--xh-time-picker-action-fg, var(--xh-fg-muted));
148
254
  font-family: inherit;
149
- font-size: var(--xh-time-picker-action-font-size, var(--xh-font-size-sm));
255
+ font-size: var(--xh-time-picker-action-font-size, var(--xh-text-secondary-size));
150
256
  line-height: var(--xh-leading-none);
151
257
  cursor: pointer;
152
258
  user-select: none;
153
- transition: background var(--xh-motion-duration-micro) var(--xh-motion-ease-enter);
259
+ transition:
260
+ background var(--xh-motion-duration-micro) var(--xh-motion-ease-enter),
261
+ scale var(--xh-motion-duration-micro) var(--xh-motion-ease-enter);
154
262
  }
155
263
 
264
+
156
265
  [data-scope='time-picker'][data-part='trigger'][hidden],
157
266
  [data-scope='time-picker'][data-part='clear-trigger'][hidden] {
158
267
  display: none;
159
268
  }
160
269
 
161
- /* 触发器把整行推到最右:它与清空按钮之间不留缝,两者一起靠框内末端 */
162
- [data-scope='time-picker'][data-part='trigger'] {
163
- margin-inline-start: auto;
164
- }
165
-
166
270
  [data-scope='time-picker'][data-part='trigger']:hover:not(:disabled),
167
- [data-scope='time-picker'][data-part='clear-trigger']:hover:not(:disabled) {
271
+ [data-scope='time-picker'][data-part='clear-trigger']:hover {
168
272
  background: var(--xh-time-picker-action-bg-hover, var(--xh-bg-subtle-hover));
169
273
  color: var(--xh-time-picker-action-fg-hover, var(--xh-fg-default));
170
274
  }
171
275
 
172
- [data-scope='time-picker'][data-part='trigger']:active:not(:disabled),
173
- [data-scope='time-picker'][data-part='clear-trigger']:active:not(:disabled) {
276
+ [data-scope='time-picker'][data-part='trigger']:active:not(:disabled) {
174
277
  background: var(--xh-time-picker-action-bg-active, var(--xh-bg-subtle-active));
175
278
  }
176
279
 
177
- /* 触发器是常规 Tab 停靠点,落焦必须看得见;清空按钮退出了 Tab 序列,
178
- 这条是给程序化聚焦兜底 */
179
- [data-scope='time-picker'][data-part='trigger']:focus-visible,
280
+ /* 清空钮按下时换底并微缩,给指针一个按到了的反馈 */
281
+ [data-scope='time-picker'][data-part='clear-trigger']:active {
282
+ background: var(--xh-time-picker-action-bg-active, var(--xh-bg-subtle-active));
283
+ scale: var(--xh-motion-scale-press);
284
+ }
285
+
286
+ /* 清空按钮退出了 Tab 序列,这条是给程序化聚焦兜底;
287
+ 展开钮是常规 Tab 停靠点,它落焦时环由盒的 :focus-within 画,这里不再套一圈 */
180
288
  [data-scope='time-picker'][data-part='clear-trigger']:focus-visible {
181
- outline: var(--xh-ring-width) solid var(--xh-ring-focus);
289
+ outline: var(--xh-ring-width) solid var(--xh-_time-picker-ring);
182
290
  outline-offset: var(--xh-ring-offset);
183
291
  }
184
292
 
185
- /* 两个按钮都是单体控件,禁用走原生 :disabled(列里的格一律 data-disabled) */
186
- [data-scope='time-picker'][data-part='trigger']:disabled,
187
- [data-scope='time-picker'][data-part='clear-trigger']:disabled {
293
+ /* 下拉钮是单体控件,禁用走原生 :disabled(列里的格一律 data-disabled);
294
+ 清空钮没值即收起,不做灰态 */
295
+ [data-scope='time-picker'][data-part='trigger']:disabled {
188
296
  background: var(--xh-time-picker-action-bg, transparent);
189
297
  color: var(--xh-fg-disabled);
190
298
  cursor: not-allowed;
191
299
  }
192
300
 
193
- /* 坐标由定位引擎写进 style(inset-inline-start / inset-block-start),这里只定位模式与层级 */
194
- [data-scope='time-picker'][data-part='positioner'] {
195
- position: fixed;
196
- z-index: var(--xh-layer-popover);
197
- /* 空壳不吃指针,交互只发生在 content 里 */
198
- pointer-events: none;
199
- }
200
-
201
- /* 锚点被滚出可视区:整个浮层随之收起 */
202
- [data-scope='time-picker'][data-part='positioner'][data-hidden] {
203
- visibility: hidden;
204
- }
205
-
206
301
  /* 几列并排:整体高度由列自己撑,滚动发生在列里而不是整个面板上——
207
302
  整面板滚会让时列与分列一起走,挑分的时候时就看不见了 */
208
303
  [data-scope='time-picker'][data-part='content'] {
209
304
  display: flex;
210
305
  align-items: stretch;
211
- padding: var(--xh-time-picker-content-p, var(--xh-space-1));
306
+ padding-block: var(--xh-time-picker-content-py, var(--xh-space-1));
307
+ padding-inline: var(--xh-time-picker-content-px, var(--xh-space-1));
308
+ /* 列自己定高,面板整体不该再长过页内滚动面那一档 */
309
+ max-block-size: var(--xh-time-picker-content-max-h, var(--xh-viewport-h-lg));
212
310
  border: var(--xh-stroke-thin) solid var(--xh-time-picker-content-border, var(--xh-border-default));
213
311
  border-radius: var(--xh-time-picker-content-radius, var(--xh-shape-surface));
214
312
  background: var(--xh-time-picker-content-bg, var(--xh-bg-surface));
215
313
  color: var(--xh-time-picker-content-fg, var(--xh-fg-default));
216
314
  font-variant-numeric: tabular-nums;
217
- box-shadow: var(--xh-time-picker-content-shadow, var(--xh-elevation-2));
315
+ box-shadow: var(--xh-time-picker-content-shadow, var(--xh-elevation-floating));
218
316
  pointer-events: auto;
219
317
  }
220
318
 
221
- /* display 会盖掉 hidden 属性的 UA 规则,收起态显式让位 */
222
- [data-scope='time-picker'][data-part='content'][hidden] {
223
- display: none;
224
- }
319
+ /* 这里刻意没有 [data-part='content'][hidden] { display: none },与 dialog 一致:
320
+ 收起态连接层会给 content 打 hidden,而上面那条 display 正是要盖掉 UA 的
321
+ [hidden]{display:none}——退场动画得先能播。presence 读的是 content 的 animationName,
322
+ 真正的收起由宿主在退场结束后落成内联 display:none(Vue 那边直接不渲染)。
323
+ 其余声明了 display 的角色节点仍补 [hidden],那几处没有退场动画。 */
225
324
 
226
325
  /* 面板本身不承载焦点(焦点在某一列的某一格上),落焦时不画环 */
227
326
  [data-scope='time-picker'][data-part='content']:focus-visible {
@@ -229,7 +328,68 @@
229
328
  }
230
329
 
231
330
  [data-scope='time-picker'][data-part='content'][data-state='open'] {
232
- animation: xh-time-picker-panel-in var(--xh-motion-duration-enter) var(--xh-motion-ease-enter);
331
+ animation: xh-pop-in var(--xh-motion-duration-enter) var(--xh-motion-ease-enter);
332
+ }
333
+
334
+ /* 退场:收起那一帧 hidden 由退场闸门押后,这里才播得出来。forwards 把末态钉住,
335
+ 免得动画结束到真收起之间闪一下原样 */
336
+ [data-scope='time-picker'][data-part='content'][data-state='closed'] {
337
+ animation: xh-pop-out var(--xh-motion-duration-exit) var(--xh-motion-ease-exit) forwards;
338
+ }
339
+
340
+ /* 快捷选项也是一列,与时分秒那几列并排,排在行内起始一侧 */
341
+ [data-scope='time-picker'][data-part='presets'] {
342
+ display: flex;
343
+ flex: none;
344
+ flex-direction: column;
345
+ gap: var(--xh-time-picker-presets-gap, var(--xh-space-0_5));
346
+ max-block-size: var(--xh-time-picker-presets-h, var(--xh-viewport-h-sm));
347
+ padding-inline: var(--xh-time-picker-presets-px, var(--xh-space-1));
348
+ overflow-y: auto;
349
+ border-inline-end: var(--xh-stroke-thin) solid var(--xh-time-picker-column-divider, var(--xh-border-subtle));
350
+ scrollbar-width: thin;
351
+ }
352
+
353
+ [data-scope='time-picker'][data-part='presets'][hidden] {
354
+ display: none;
355
+ }
356
+
357
+ [data-scope='time-picker'][data-part='preset'] {
358
+ padding-block: var(--xh-time-picker-preset-py, var(--xh-space-1));
359
+ padding-inline: var(--xh-time-picker-preset-px, var(--xh-space-3));
360
+ border-radius: var(--xh-shape-control);
361
+ font-size: var(--xh-text-secondary-size);
362
+ line-height: var(--xh-leading-normal);
363
+ white-space: nowrap;
364
+ cursor: pointer;
365
+ user-select: none;
366
+ }
367
+
368
+ /* 悬停与键盘锚点共用中性轻档,命中那一条才走品牌底;禁用的不响应悬停 */
369
+ [data-scope='time-picker'][data-part='preset']:hover:not([data-disabled]) {
370
+ background: var(--xh-time-picker-preset-bg-hover, var(--xh-bg-subtle));
371
+ }
372
+
373
+ [data-scope='time-picker'][data-part='preset']:focus-visible,
374
+ [data-scope='time-picker'][data-part='presets']:focus-visible {
375
+ outline: var(--xh-ring-width) solid var(--xh-ring-focus);
376
+ outline-offset: calc(-1 * var(--xh-ring-width));
377
+ }
378
+
379
+ /* 命中的那一条与选中的格子同一副实心底:同一份浮层里两种「选中」不该长成两个样 */
380
+ [data-scope='time-picker'][data-part='preset'][data-state='checked'] {
381
+ background: var(--xh-time-picker-preset-bg-checked, var(--xh-_time-picker-accent));
382
+ color: var(--xh-time-picker-preset-fg-checked, var(--xh-_time-picker-accent-fg));
383
+ font-weight: var(--xh-font-weight-medium);
384
+ }
385
+
386
+ [data-scope='time-picker'][data-part='preset'][data-state='checked']:hover:not([data-disabled]) {
387
+ background: var(--xh-time-picker-preset-bg-checked-hover, var(--xh-_time-picker-accent-hover));
388
+ }
389
+
390
+ [data-scope='time-picker'][data-part='preset'][data-disabled] {
391
+ color: var(--xh-time-picker-preset-fg-disabled, var(--xh-fg-disabled));
392
+ cursor: not-allowed;
233
393
  }
234
394
 
235
395
  /* 一列一个滚动区:列与列之间用细分隔线,视觉上"时 | 分 | 秒"三栏分明 */
@@ -239,7 +399,8 @@
239
399
  flex-direction: column;
240
400
  gap: var(--xh-time-picker-column-gap, var(--xh-space-0_5));
241
401
  min-inline-size: var(--xh-time-picker-column-min-w, 3.5rem);
242
- max-block-size: var(--xh-time-picker-column-max-h, 12rem);
402
+ /* 几列并排:定高而不是随内容收,否则时列与分列的可选值一多一少就错位 */
403
+ block-size: var(--xh-time-picker-column-h, var(--xh-viewport-h-sm));
243
404
  padding-inline: var(--xh-time-picker-column-px, var(--xh-space-1));
244
405
  overflow-y: auto;
245
406
  /* 滚动容器在某些浏览器里会被自动塞进 Tab 序列,是否画环见下方按 tabindex 分档的两条 */
@@ -258,7 +419,7 @@
258
419
  /* 焦点落在列上有两种情形:指针打开、这一段还空着、还没有任何格当锚点,或整列被界裁空。
259
420
  那一刻它认领着 Tab 位,环画在列内沿;有锚点时环长在格上,列不再画 */
260
421
  [data-scope='time-picker'][data-part='column'][tabindex='0']:focus-visible {
261
- outline: var(--xh-ring-width) solid var(--xh-ring-focus);
422
+ outline: var(--xh-ring-width) solid var(--xh-_time-picker-ring);
262
423
  outline-offset: calc(-1 * var(--xh-ring-width));
263
424
  }
264
425
 
@@ -272,10 +433,10 @@
272
433
  align-items: center;
273
434
  justify-content: center;
274
435
  padding-block: var(--xh-time-picker-item-py, var(--xh-space-1_5));
275
- padding-inline: var(--xh-time-picker-item-px, var(--xh-control-px-md));
436
+ padding-inline: var(--xh-time-picker-item-px, var(--xh-_time-picker-item-px));
276
437
  border-radius: var(--xh-time-picker-item-radius, var(--xh-shape-control));
277
438
  color: var(--xh-time-picker-item-fg, var(--xh-fg-default));
278
- font-size: var(--xh-time-picker-item-font-size, var(--xh-text-body-size));
439
+ font-size: var(--xh-time-picker-item-font-size, var(--xh-_time-picker-font-size));
279
440
  /* 居中的单个数字格没有截断层,行高保持紧排,列内多露几格 */
280
441
  line-height: var(--xh-leading-none);
281
442
  white-space: nowrap;
@@ -298,8 +459,8 @@
298
459
  }
299
460
 
300
461
  [data-scope='time-picker'][data-part='item'][data-state='checked'] {
301
- background: var(--xh-time-picker-item-bg-checked, var(--xh-bg-brand));
302
- color: var(--xh-time-picker-item-fg-checked, var(--xh-fg-on-brand));
462
+ background: var(--xh-time-picker-item-bg-checked, var(--xh-_time-picker-accent));
463
+ color: var(--xh-time-picker-item-fg-checked, var(--xh-_time-picker-accent-fg));
303
464
  font-weight: var(--xh-time-picker-item-weight-checked, var(--xh-font-weight-medium));
304
465
  }
305
466
 
@@ -307,11 +468,11 @@
307
468
  不写这条就只有底色被换走、文字仍是品牌底上的反白色 */
308
469
  [data-scope='time-picker'][data-part='item'][data-state='checked'][data-highlighted]:not([data-disabled]),
309
470
  [data-scope='time-picker'][data-part='item'][data-state='checked']:hover:not([data-disabled]) {
310
- background: var(--xh-time-picker-item-bg-checked-hover, var(--xh-bg-brand-hover));
471
+ background: var(--xh-time-picker-item-bg-checked-hover, var(--xh-_time-picker-accent-hover));
311
472
  }
312
473
 
313
474
  [data-scope='time-picker'][data-part='item']:focus-visible {
314
- outline: var(--xh-ring-width) solid var(--xh-ring-focus);
475
+ outline: var(--xh-ring-width) solid var(--xh-_time-picker-ring);
315
476
  /* 往内收:选项在滚动列里挨着排,环画在外沿会被列的溢出裁掉 */
316
477
  outline-offset: calc(-1 * var(--xh-ring-offset));
317
478
  }
@@ -338,20 +499,54 @@
338
499
  white-space: nowrap;
339
500
  pointer-events: none;
340
501
  }
502
+
503
+ /* 没写内容就由皮肤画兜底字形;作者往部件里塞了自己的图形,这几条即不命中 */
504
+ [data-scope='time-picker'][data-part='clear-trigger']:empty::before {
505
+ content: '';
506
+ display: inline-block;
507
+ inline-size: var(--xh-icon-size, var(--xh-glyph-size-text));
508
+ block-size: var(--xh-icon-size, var(--xh-glyph-size-text));
509
+ vertical-align: var(--xh-glyph-baseline-shift);
510
+ background-color: currentColor;
511
+ -webkit-mask: var(--xh-glyph-mark-close) center / contain no-repeat;
512
+ mask: var(--xh-glyph-mark-close) center / contain no-repeat;
513
+ }
514
+
515
+ [data-scope='time-picker'][data-part='trigger']:empty::before {
516
+ content: '';
517
+ display: inline-block;
518
+ inline-size: var(--xh-icon-size, var(--xh-glyph-size-text));
519
+ block-size: var(--xh-icon-size, var(--xh-glyph-size-text));
520
+ vertical-align: var(--xh-glyph-baseline-shift);
521
+ background-color: currentColor;
522
+ -webkit-mask: var(--xh-glyph-mark-chevron-down) center / contain no-repeat;
523
+ mask: var(--xh-glyph-mark-chevron-down) center / contain no-repeat;
524
+ }
341
525
  }
342
526
 
343
527
  @layer xihan.motion {
344
528
  /* 浮层进场:淡入 + 轻微上浮,方向与它从输入行下方展开一致。
345
529
  关键帧写在自己文件里并带组件前缀,不去动共享的 motion.css */
346
- @keyframes xh-time-picker-panel-in {
530
+ @keyframes xh-pop-in {
347
531
  from {
348
532
  opacity: 0;
349
- translate: 0 calc(-1 * var(--xh-space-1));
533
+ scale: var(--xh-motion-scale-enter);
350
534
  }
351
535
 
352
536
  to {
353
537
  opacity: 1;
354
- translate: 0 0;
538
+ scale: 1;
539
+ }
540
+ }
541
+ @keyframes xh-pop-out {
542
+ from {
543
+ opacity: 1;
544
+ scale: 1;
545
+ }
546
+
547
+ to {
548
+ opacity: 0;
549
+ scale: var(--xh-motion-scale-enter);
355
550
  }
356
551
  }
357
552
  }
package/css/time.css CHANGED
@@ -1,4 +1,9 @@
1
1
  @layer xihan.components {
2
+ /* 皮肤在场的标记:开发模式下按 scope 探一次,取不到就说明这份皮肤没被引入。 */
3
+ [data-scope='time'] {
4
+ --xh-time-skin: 1;
5
+ }
6
+
2
7
  [data-scope='time'][data-part='root'] {
3
8
  color: var(--xh-time-fg, var(--xh-fg-default));
4
9
  /* 等宽数字:秒数跳动时后面的字符不会左右挪 */
package/css/timeline.css CHANGED
@@ -1,12 +1,17 @@
1
1
  @layer xihan.components {
2
+ /* 皮肤在场的标记:开发模式下按 scope 探一次,取不到就说明这份皮肤没被引入。 */
3
+ [data-scope='timeline'] {
4
+ --xh-timeline-skin: 1;
5
+ }
6
+
2
7
  [data-scope='timeline'][data-part='root'] {
3
8
  /* 尺寸档只换这几个私有槽,条目、圆点与文字都从 root 继承它们,
4
9
  换档不必给每个部件各写一条选择器 */
5
- --xh-_timeline-dot-size: 10px;
10
+ --xh-_timeline-dot-size: var(--xh-space-2_5);
6
11
  --xh-_timeline-gutter: var(--xh-space-3);
7
12
  --xh-_timeline-item-gap: var(--xh-space-5);
8
13
  --xh-_timeline-title-font-size: var(--xh-text-label-size);
9
- --xh-_timeline-caption-font-size: var(--xh-font-size-xs);
14
+ --xh-_timeline-caption-font-size: var(--xh-text-caption-size);
10
15
  /* 标题首行占多高。圆点按它居中下移,圆心才落在标题这一行的中线上 */
11
16
  --xh-_timeline-line-h: calc(
12
17
  var(--xh-timeline-title-font-size, var(--xh-_timeline-title-font-size)) * var(--xh-leading-tight)
@@ -34,21 +39,21 @@
34
39
  }
35
40
 
36
41
  /* —— 尺寸 —— */
37
- /* 缺省档写在上面的基础规则里。圆点直径不在控件高度那把尺上,两侧直接给像素 */
42
+ /* 缺省档写在上面的基础规则里。圆点直径不在控件高度那把尺上,三档走空间尺相邻的三格 */
38
43
  [data-scope='timeline'][data-part='root'][data-size='sm'] {
39
- --xh-_timeline-dot-size: 8px;
44
+ --xh-_timeline-dot-size: var(--xh-space-2);
40
45
  --xh-_timeline-gutter: var(--xh-space-2);
41
46
  --xh-_timeline-item-gap: var(--xh-space-4);
42
- --xh-_timeline-title-font-size: var(--xh-font-size-sm);
47
+ --xh-_timeline-title-font-size: var(--xh-control-font-sm);
43
48
  /* 字号档最小就是 xs,时刻文本不再往下走,故不重声明 caption */
44
49
  }
45
50
 
46
51
  [data-scope='timeline'][data-part='root'][data-size='lg'] {
47
- --xh-_timeline-dot-size: 12px;
52
+ --xh-_timeline-dot-size: var(--xh-space-3);
48
53
  --xh-_timeline-gutter: var(--xh-space-4);
49
54
  --xh-_timeline-item-gap: var(--xh-space-6);
50
- --xh-_timeline-title-font-size: var(--xh-font-size-lg);
51
- --xh-_timeline-caption-font-size: var(--xh-font-size-sm);
55
+ --xh-_timeline-title-font-size: var(--xh-control-font-lg);
56
+ --xh-_timeline-caption-font-size: var(--xh-text-secondary-size);
52
57
  }
53
58
 
54
59
  /* —— 条目 —— */
@@ -87,7 +92,7 @@
87
92
  justify-content: center;
88
93
  inline-size: var(--xh-timeline-indicator-size, var(--xh-_timeline-dot-size));
89
94
  block-size: var(--xh-timeline-indicator-size, var(--xh-_timeline-dot-size));
90
- border-radius: var(--xh-radius-full);
95
+ border-radius: var(--xh-shape-pill);
91
96
  /* 使用者令牌排在语气之前;两者都没有时退回一个中性的实心点 */
92
97
  background: var(--xh-timeline-indicator-bg, var(--xh-_tone-soft, var(--xh-fg-muted)));
93
98
  color: var(--xh-timeline-indicator-fg, var(--xh-_tone-on, var(--xh-fg-on-brand)));
@@ -115,7 +120,7 @@
115
120
 
116
121
  /* —— 连线 —— */
117
122
  [data-scope='timeline'][data-part='connector'] {
118
- border-radius: var(--xh-radius-full);
123
+ border-radius: var(--xh-shape-pill);
119
124
  background: var(--xh-timeline-connector-bg, var(--xh-border-default));
120
125
  }
121
126