@xihan-ui/styles 1.0.0 → 2.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (171) hide show
  1. package/CHANGELOG.md +5146 -6
  2. package/README.md +22 -2
  3. package/component-tokens.d.ts +4212 -0
  4. package/component-tokens.js +2 -0
  5. package/components.tokens.json +80116 -0
  6. package/css/accordion.css +131 -75
  7. package/css/affix.css +16 -1
  8. package/css/alert.css +114 -67
  9. package/css/anchor.css +99 -27
  10. package/css/approval.css +461 -0
  11. package/css/avatar-group.css +14 -6
  12. package/css/avatar.css +33 -9
  13. package/css/back-top.css +103 -48
  14. package/css/badge.css +42 -14
  15. package/css/bar-code.css +62 -0
  16. package/css/breadcrumb.css +40 -21
  17. package/css/button-group.css +146 -24
  18. package/css/button.css +116 -99
  19. package/css/calendar-picker.css +448 -0
  20. package/css/calendar-range-picker.css +517 -0
  21. package/css/card.css +54 -77
  22. package/css/carousel.css +412 -68
  23. package/css/cascader.css +429 -246
  24. package/css/checkbox-group.css +225 -77
  25. package/css/checkbox.css +174 -37
  26. package/css/clipboard.css +266 -47
  27. package/css/code-view.css +279 -0
  28. package/css/collapsible.css +108 -63
  29. package/css/color-field.css +158 -0
  30. package/css/color-picker.css +172 -184
  31. package/css/color-slider.css +274 -0
  32. package/css/color-swatch-picker.css +243 -0
  33. package/css/color-swatch.css +35 -0
  34. package/css/combobox.css +267 -273
  35. package/css/command.css +399 -0
  36. package/css/context-menu.css +183 -108
  37. package/css/date-field.css +94 -121
  38. package/css/date-picker.css +486 -249
  39. package/css/date-range-picker.css +559 -0
  40. package/css/description.css +51 -0
  41. package/css/descriptions.css +133 -87
  42. package/css/dialog.css +247 -68
  43. package/css/diff-view.css +428 -0
  44. package/css/download-trigger.css +155 -46
  45. package/css/drawer.css +194 -111
  46. package/css/editable.css +172 -152
  47. package/css/empty-state.css +80 -11
  48. package/css/field-array.css +190 -0
  49. package/css/field.css +84 -31
  50. package/css/fieldset.css +51 -18
  51. package/css/file-upload.css +134 -36
  52. package/css/flex.css +20 -1
  53. package/css/float-button.css +238 -57
  54. package/css/floating-panel.css +173 -92
  55. package/css/focus.css +46 -0
  56. package/css/forced-colors.css +93 -0
  57. package/css/form.css +254 -77
  58. package/css/gradient-text.css +34 -10
  59. package/css/grid.css +516 -5
  60. package/css/heatmap.css +87 -29
  61. package/css/highlight.css +20 -5
  62. package/css/hover-card.css +97 -47
  63. package/css/icon-wrapper.css +15 -3
  64. package/css/icon.css +74 -8
  65. package/css/image-cropper.css +143 -29
  66. package/css/image-viewer.css +150 -89
  67. package/css/image.css +30 -1
  68. package/css/infinite-scroll.css +51 -1
  69. package/css/input-group.css +277 -0
  70. package/css/json-viewer.css +102 -45
  71. package/css/kbd.css +72 -0
  72. package/css/label.css +78 -0
  73. package/css/layers.css +5 -0
  74. package/css/layout.css +175 -31
  75. package/css/list.css +24 -3
  76. package/css/listbox.css +208 -67
  77. package/css/loading-bar.css +52 -3
  78. package/css/log.css +144 -9
  79. package/css/markdown-stream.css +149 -0
  80. package/css/marquee.css +27 -1
  81. package/css/masonry.css +7 -0
  82. package/css/matrix-code.css +67 -0
  83. package/css/mention.css +234 -152
  84. package/css/menu.css +180 -83
  85. package/css/menubar.css +204 -136
  86. package/css/message-feed.css +197 -0
  87. package/css/navigation-menu.css +144 -90
  88. package/css/notification.css +178 -100
  89. package/css/number-animation.css +7 -0
  90. package/css/number-field.css +120 -277
  91. package/css/overlay-arrow.css +12 -7
  92. package/css/page-header.css +99 -14
  93. package/css/pagination.css +175 -135
  94. package/css/password-input.css +222 -219
  95. package/css/pin-input.css +101 -67
  96. package/css/pointer.css +36 -0
  97. package/css/popconfirm.css +185 -94
  98. package/css/popover.css +121 -77
  99. package/css/progress.css +60 -12
  100. package/css/prompt-input.css +224 -0
  101. package/css/question-flow.css +513 -0
  102. package/css/radio-group.css +147 -30
  103. package/css/rating.css +193 -43
  104. package/css/reasoning.css +336 -0
  105. package/css/reset.css +84 -6
  106. package/css/resizable.css +237 -0
  107. package/css/scroll-area.css +68 -7
  108. package/css/scrollbar.css +47 -13
  109. package/css/segmented.css +94 -29
  110. package/css/select.css +288 -274
  111. package/css/separator.css +101 -1
  112. package/css/side-nav.css +133 -75
  113. package/css/signature-pad.css +74 -54
  114. package/css/skeleton.css +84 -11
  115. package/css/slider.css +132 -39
  116. package/css/sortable.css +198 -0
  117. package/css/spinner.css +126 -12
  118. package/css/splitter.css +29 -8
  119. package/css/statistic.css +55 -0
  120. package/css/steps.css +206 -72
  121. package/css/switch.css +268 -36
  122. package/css/table.css +695 -118
  123. package/css/tabs.css +604 -42
  124. package/css/tag-group.css +219 -0
  125. package/css/tag.css +118 -28
  126. package/css/tags-input.css +156 -274
  127. package/css/text-field.css +101 -249
  128. package/css/time-field.css +100 -128
  129. package/css/time-picker.css +323 -252
  130. package/css/time-range-picker.css +719 -0
  131. package/css/timeline.css +202 -68
  132. package/css/timer.css +56 -52
  133. package/css/timestamp.css +34 -0
  134. package/css/toast.css +373 -144
  135. package/css/toggle-group.css +309 -76
  136. package/css/toggle.css +116 -85
  137. package/css/tone.css +47 -0
  138. package/css/tool-call.css +421 -0
  139. package/css/toolbar.css +181 -33
  140. package/css/tooltip.css +107 -36
  141. package/css/tour.css +183 -152
  142. package/css/transfer.css +351 -138
  143. package/css/tree-select.css +323 -216
  144. package/css/tree.css +294 -62
  145. package/css/truncate.css +65 -0
  146. package/css/typography.css +228 -5
  147. package/css/undefined.css +10 -1
  148. package/css/virtualizer.css +9 -10
  149. package/css/visually-hidden.css +7 -0
  150. package/css/watermark.css +7 -0
  151. package/family/action-control.css +487 -0
  152. package/family/collection-item.css +721 -0
  153. package/family/field-chrome.css +298 -0
  154. package/family/motion.css +166 -0
  155. package/family/swatch.css +59 -0
  156. package/index.css +41705 -126
  157. package/index.unlayered.css +33692 -17339
  158. package/package.json +51 -17
  159. package/css/calendar.css +0 -367
  160. package/css/code-block.css +0 -91
  161. package/css/composer.css +0 -134
  162. package/css/countdown.css +0 -26
  163. package/css/dynamic-input.css +0 -220
  164. package/css/ellipsis.css +0 -52
  165. package/css/hotkeys.css +0 -90
  166. package/css/popselect.css +0 -391
  167. package/css/qr-code.css +0 -55
  168. package/css/result.css +0 -119
  169. package/css/space.css +0 -117
  170. package/css/thread.css +0 -120
  171. package/css/time.css +0 -25
@@ -1,3 +1,18 @@
1
+ /*
2
+ * Copyright (c) 2021-Present XiHanFun and contributors.
3
+ * Licensed under the MIT License. See LICENSE in the project root for license information.
4
+ */
5
+
6
+ /* DatePicker 独立皮肤同时传递引入字段视觉盒、字段内动作与浮层集合行;full bundle 递归去重。 */
7
+ @import '../family/field-chrome.css';
8
+ @import '../family/action-control.css';
9
+ @import '../family/collection-item.css';
10
+
11
+ @import './scrollbar.css';
12
+
13
+ /* 共享关键帧由 family/motion.css 提供,本皮肤 @import 它,单独引入仍成立。 */
14
+ @import '../family/motion.css';
15
+
1
16
  @layer xihan.components {
2
17
  /* 皮肤在场的标记:开发模式下按 scope 探一次,取不到就说明这份皮肤没被引入。 */
3
18
  [data-scope='date-picker'] {
@@ -9,12 +24,21 @@
9
24
  /* 落定那一侧的可用高度,由定位引擎经内联自定义属性写进来,内容层继承它限高;
10
25
  引擎没算(尚未落位 / 无引擎 / 贴边归零)时不额外限高 */
11
26
  --xh-_date-picker-available-h: 100vh;
27
+ /* 落定那一侧的可用宽度,同样由定位引擎经内联自定义属性写进来,内容层据此夹住行内轴;
28
+ 引擎没算(尚未落位 / 无引擎 / 贴边归零)时退到视口宽 */
29
+ --xh-_date-picker-available-w: 100vw;
30
+
31
+ /* 每个浮层独立声明方向,避免继承祖先浮层的进场位移。 */
32
+ --xh-_overlay-enter-up: 0;
33
+ --xh-_overlay-enter-down: 0;
34
+ --xh-_overlay-enter-left: 0;
35
+ --xh-_overlay-enter-right: 0;
12
36
 
13
37
  /* 面板的自绘条浮在内容之上:轨道不上底色,实色轨道会在面板右缘糊出一条竖灰带 */
14
38
  --xh-scrollbar-track-bg: transparent;
15
39
 
16
40
  position: fixed;
17
- z-index: var(--xh-date-picker-layer, var(--xh-layer-popover));
41
+ z-index: var(--xh-date-picker-layer, var(--xh-_layer, var(--xh-layer-popover)));
18
42
  /* 空壳不吃指针,交互只发生在 content 里 */
19
43
  pointer-events: none;
20
44
  }
@@ -24,31 +48,39 @@
24
48
  visibility: hidden;
25
49
  }
26
50
 
51
+ /* 短位移按实际落位的物理方向给,不随书写方向翻转。 */
52
+ [data-scope='date-picker'][data-part='positioner'][data-placement^='top'] {
53
+ --xh-_overlay-enter-down: 1;
54
+ }
55
+
56
+ [data-scope='date-picker'][data-part='positioner'][data-placement^='bottom'] {
57
+ --xh-_overlay-enter-up: 1;
58
+ }
59
+
60
+ [data-scope='date-picker'][data-part='positioner'][data-placement^='left'] {
61
+ --xh-_overlay-enter-right: 1;
62
+ }
63
+
64
+ [data-scope='date-picker'][data-part='positioner'][data-placement^='right'] {
65
+ --xh-_overlay-enter-left: 1;
66
+ }
67
+
27
68
  /* 私有槽同时声明在根与 positioner 上:浮层被搬到 portal 落点,不是根的后代,继承不过去 */
28
69
  [data-scope='date-picker']:is([data-part='root'], [data-part='positioner']) {
29
- /* 尺寸档只换这几个私有槽,标题、输入行与浮层里的部件都从这两处继承它们,
30
- 换档不必给每个部件各写一条选择器 */
70
+ /* 尺寸档只换这几个私有槽,输入行与浮层里的部件都从这两处继承它们,
71
+ 换档不必给每个部件各写一条选择器;形态三档由家族按 control 上的 data-variant 生成,皮肤不再声明 */
31
72
  --xh-_date-picker-control-h: var(--xh-control-h-md);
32
73
  --xh-_date-picker-control-px: var(--xh-control-px-md);
33
74
  --xh-_date-picker-gap: var(--xh-control-gap-md);
34
75
  --xh-_date-picker-font-size: var(--xh-control-font-md);
35
- --xh-_date-picker-label-font-size: var(--xh-control-font-md);
36
-
37
- /* 形态档只换这三个私有槽:底色与两档描边 */
38
- --xh-_date-picker-control-bg: var(--xh-bg-canvas);
39
- --xh-_date-picker-control-border: var(--xh-border-control);
40
- --xh-_date-picker-control-border-hover: var(--xh-border-control-hover);
41
76
 
42
- /* 聚焦环、时间列选中与确认按钮随语气走。没写 data-tone 时这几个 --xh-_tone* 没被声明,
43
- 退回原来的焦点色与品牌色 */
44
- --xh-_date-picker-ring: var(--xh-ring-focus);
45
- --xh-_date-picker-accent: var(--xh-_tone, var(--xh-bg-brand));
46
- --xh-_date-picker-accent-hover: var(--xh-_tone-hover, var(--xh-bg-brand-hover));
47
- --xh-_date-picker-accent-fg: var(--xh-_tone-on, var(--xh-fg-on-brand));
48
- --xh-_date-picker-accent-subtle: var(--xh-_tone-subtle, var(--xh-bg-brand-subtle));
49
- /* 淡底上的字与实心底上的字是两档:--xh-_tone-fg 是语气层为淡底配的那一档,
50
- 没写 data-tone 时退到 fg-brand-strong——fg-brand(600)压在 brand-100 上只有 4.21 */
51
- --xh-_date-picker-accent-subtle-fg: var(--xh-_tone-fg, var(--xh-fg-brand-strong));
77
+ /* 选中对号随语气走。没写 data-tone 时这几个 --xh-_tone* 没被声明,退回品牌色 */
78
+ /* 内嵌日期段沿用日期输入的轻强调焦点:当前段是「当前项」,淡底 + 淡底前景,不另画一套实心选择态。 */
79
+ --xh-_date-field-segment-bg: var(--xh-_tone-subtle, var(--xh-bg-brand-subtle));
80
+ --xh-_date-field-segment-fg: var(--xh-_tone-fg, var(--xh-fg-on-brand-subtle));
81
+ /* 对号画在普通面上,取语气前景角色,不能拿确认按钮的实心背景色充当前景。 */
82
+ --xh-_date-picker-check-fg: var(--xh-_tone, var(--xh-fg-brand));
83
+ --xh-_date-picker-time-item-check-size: var(--xh-glyph-size-sm);
52
84
  }
53
85
 
54
86
  /* 与文本框、分段日期同一套堆叠:标签一行、输入行一行 */
@@ -59,6 +91,12 @@
59
91
  display: inline-flex;
60
92
  flex-direction: column;
61
93
  gap: var(--xh-date-picker-gap, var(--xh-space-1));
94
+
95
+ /* 不传尺寸时一律这么宽,宽度不随内容走;父容器给不出这么宽时整件跟着收,地板同步让步,不越出父容器。
96
+ 地板不高过缺省宽:使用者把缺省宽钉到底线以下时不必再放开底线 */
97
+ inline-size: var(--xh-date-picker-control-w, var(--xh-control-w));
98
+ min-inline-size: min(var(--xh-date-picker-control-w, var(--xh-control-w)), var(--xh-date-picker-control-min-w, var(--xh-control-min-w)), 100%);
99
+ max-inline-size: 100%;
62
100
  }
63
101
 
64
102
  /* —— 尺寸 —— */
@@ -69,7 +107,6 @@
69
107
  --xh-_date-picker-control-px: var(--xh-control-px-sm);
70
108
  --xh-_date-picker-gap: var(--xh-control-gap-sm);
71
109
  --xh-_date-picker-font-size: var(--xh-control-font-sm);
72
- --xh-_date-picker-label-font-size: var(--xh-control-font-sm);
73
110
  }
74
111
 
75
112
  [data-scope='date-picker']:is([data-part='root'], [data-part='positioner'])[data-size='lg'] {
@@ -78,31 +115,13 @@
78
115
  --xh-_date-picker-control-px: var(--xh-control-px-lg);
79
116
  --xh-_date-picker-gap: var(--xh-control-gap-lg);
80
117
  --xh-_date-picker-font-size: var(--xh-control-font-lg);
81
- --xh-_date-picker-label-font-size: var(--xh-control-font-lg);
82
118
  }
83
119
 
84
- /* —— 形态 —— */
85
- /* 输入类不做实心档:填满一个要往里打字的框,字与底就没法同时读。
86
- 形态只决定底与描边怎么画,用哪族颜色由 data-tone 决定 */
87
- [data-scope='date-picker']:is([data-part='root'], [data-part='positioner'])[data-variant='outline'] {
88
- --xh-_date-picker-control-bg: var(--xh-bg-canvas);
89
- --xh-_date-picker-control-border: var(--xh-border-control);
90
- --xh-_date-picker-control-border-hover: var(--xh-border-control-hover);
91
- }
92
-
93
- /* 填充式:底色顶替描边表达边界。描边只退成透明而不去掉,1px 的位置留着,
94
- 与 outline 档并排时基线对得上、聚焦画描边也不引起跳动 */
95
- [data-scope='date-picker']:is([data-part='root'], [data-part='positioner'])[data-variant='subtle'] {
96
- --xh-_date-picker-control-bg: var(--xh-_tone-subtle, var(--xh-bg-subtle));
97
- --xh-_date-picker-control-border: transparent;
98
- --xh-_date-picker-control-border-hover: var(--xh-_tone-border, var(--xh-border-control-hover));
99
- }
100
-
101
- /* 无框:底与常态描边透明,悬停与聚焦浮出描边 */
102
- [data-scope='date-picker']:is([data-part='root'], [data-part='positioner'])[data-variant='ghost'] {
103
- --xh-_date-picker-control-bg: transparent;
104
- --xh-_date-picker-control-border: transparent;
105
- --xh-_date-picker-control-border-hover: var(--xh-_tone-border, var(--xh-border-control-hover));
120
+ /* 375px 复合面板要同时容下日历与时/分两列;手机档用正式小指示符,平板起恢复16px。 */
121
+ @media (width < 768px) {
122
+ [data-scope='date-picker']:is([data-part='root'], [data-part='positioner']) {
123
+ --xh-_date-picker-time-item-check-size: var(--xh-control-indicator-sm);
124
+ }
106
125
  }
107
126
 
108
127
  /* 只要声明了 display 就盖掉了 UA 的 [hidden]{display:none},收起态得自己还回去 */
@@ -112,7 +131,7 @@
112
131
 
113
132
  [data-scope='date-picker'][data-part='label'] {
114
133
  color: var(--xh-date-picker-label-fg, var(--xh-fg-default));
115
- font-size: var(--xh-date-picker-label-font-size, var(--xh-_date-picker-label-font-size));
134
+ font-size: var(--xh-date-picker-label-font-size, var(--xh-text-label-size));
116
135
  font-weight: var(--xh-date-picker-label-font-weight, var(--xh-text-label-weight));
117
136
  line-height: var(--xh-leading-none);
118
137
  }
@@ -123,61 +142,40 @@
123
142
 
124
143
  [data-scope='date-picker'][data-part='label'][data-disabled] {
125
144
  color: var(--xh-date-picker-label-fg-disabled, var(--xh-fg-subtle));
126
- cursor: not-allowed;
127
145
  }
128
146
 
129
147
  /* 画成一个框的是 control 而不是 input:段位、清空按钮、日历按钮三者要看起来是一体的,
130
- 边框长在里面任何一个身上都会把另外两个割在框外 */
148
+ 边框长在里面任何一个身上都会把另外两个割在框外。描边、底色、圆角、聚焦环、五态与悬停由
149
+ Field Chrome 家族画在 control 上(焦点落在段或按钮上,家族 :focus-within 让整框亮起来);
150
+ 组件只映射既有公开槽(shadow 缺省 none:字段静息描边式、无影)。打开中不另画环,由浮层本身承担 */
131
151
  [data-scope='date-picker'][data-part='control'] {
132
- display: inline-flex;
133
- align-items: center;
134
- gap: var(--xh-date-picker-control-gap, var(--xh-_date-picker-gap));
135
- min-inline-size: var(--xh-date-picker-control-min-w, var(--xh-control-min-w));
136
- block-size: var(--xh-date-picker-control-h, var(--xh-_date-picker-control-h));
137
- padding-inline: var(--xh-date-picker-control-px, var(--xh-_date-picker-control-px));
138
- padding-block: 0;
139
- border: var(--xh-stroke-thin) solid var(--xh-date-picker-control-border, var(--xh-_date-picker-control-border));
140
- border-radius: var(--xh-date-picker-control-radius, var(--xh-shape-control));
141
- background: var(--xh-date-picker-control-bg, var(--xh-_date-picker-control-bg));
142
- color: var(--xh-date-picker-control-fg, var(--xh-fg-default));
143
- transition: border-color var(--xh-motion-duration-micro) var(--xh-motion-ease-enter);
152
+ --xh-field-control-height: var(--xh-date-picker-control-h, var(--xh-_date-picker-control-h));
153
+ --xh-field-control-padding-inline: var(--xh-date-picker-control-px, var(--xh-_date-picker-control-px));
154
+ --xh-field-control-gap: var(--xh-date-picker-control-gap, var(--xh-_date-picker-gap));
155
+ --xh-field-control-min-inline-size: var(--xh-date-picker-control-min-w, var(--xh-control-min-w));
156
+ --xh-field-control-radius: var(--xh-date-picker-control-radius, var(--xh-shape-control));
157
+ --xh-field-bg-rest: var(--xh-date-picker-control-bg, var(--xh-_field-variant-bg-rest));
158
+ --xh-field-bg-hover: var(--xh-date-picker-control-bg-hover, var(--xh-_field-variant-bg-hover));
159
+ --xh-field-bg-read-only: var(--xh-date-picker-control-bg-readonly, var(--xh-_field-variant-bg-read-only));
160
+ --xh-field-bg-disabled: var(--xh-date-picker-control-bg-disabled, var(--xh-_field-variant-bg-disabled));
161
+ --xh-field-fg-rest: var(--xh-date-picker-control-fg, var(--xh-fg-default));
162
+ --xh-field-border-rest: var(--xh-date-picker-control-border, var(--xh-_field-variant-border-rest));
163
+ --xh-field-border-hover: var(--xh-date-picker-control-border-hover, var(--xh-_field-variant-border-hover));
164
+ --xh-field-border-focus: var(--xh-date-picker-control-border-focus, var(--xh-_field-variant-border-focus));
165
+ --xh-field-border-invalid: var(--xh-date-picker-control-border-invalid, var(--xh-_field-variant-border-invalid));
166
+ --xh-field-ring-focus: var(--xh-ring-focus);
167
+ --xh-field-ring-invalid: var(--xh-ring-invalid);
168
+ --xh-field-shadow-rest: var(--xh-date-picker-control-shadow, none);
169
+ /* 段位靠键盘编辑,盒上不是文本光标 */
170
+ --xh-field-cursor-rest: default;
171
+ /* 家族 chrome 会重写 --xh-icon-size,使用者图标槽必须经桥接槽下发才能在盒内生效 */
172
+ --xh-field-glyph-size: var(--xh-date-picker-icon-size, var(--xh-_field-size-glyph-size));
144
173
  }
145
174
 
146
175
  [data-scope='date-picker'][data-part='control'][hidden] {
147
176
  display: none;
148
177
  }
149
178
 
150
- /* hover 只在中性态换描边:invalid 正拿边框颜色说事,被 hover 盖掉那条信息就没了 */
151
- [data-scope='date-picker'][data-part='control']:hover:not([data-disabled], [data-invalid]) {
152
- border-color: var(--xh-date-picker-control-border-hover, var(--xh-_date-picker-control-border-hover));
153
- }
154
-
155
- /* 焦点落在某一段或某个按钮上,而边框长在 control 上:焦点环得由内向外借一层。
156
- control 自己不占 Tab 位,:focus-within 是它唯一能感知组内焦点的方式 */
157
- [data-scope='date-picker'][data-part='control']:focus-within:not([data-disabled]) {
158
- border-color: var(--xh-date-picker-control-border-focus, var(--xh-_tone, var(--xh-border-control-focus)));
159
- outline: var(--xh-ring-width) solid var(--xh-_date-picker-ring);
160
- outline-offset: var(--xh-ring-offset);
161
- }
162
-
163
- [data-scope='date-picker'][data-part='control'][data-invalid] {
164
- border-color: var(--xh-date-picker-control-border-invalid, var(--xh-border-invalid));
165
-
166
- /* 校验失败时环也跟着变红:两圈等宽相邻却一红一蓝,读的人不知道哪个才是当前状态 */
167
- --xh-_date-picker-ring: var(--xh-ring-invalid);
168
- }
169
-
170
- /* 只读仍可聚焦、日历仍能展开来看,不置灰,只把底色压下去表示"改不动" */
171
- [data-scope='date-picker'][data-part='control'][data-readonly] {
172
- background: var(--xh-date-picker-control-bg-readonly, var(--xh-bg-subtle));
173
- }
174
-
175
- [data-scope='date-picker'][data-part='control'][data-disabled] {
176
- background: var(--xh-date-picker-control-bg-disabled, var(--xh-bg-subtle));
177
- color: var(--xh-fg-disabled);
178
- cursor: not-allowed;
179
- }
180
-
181
179
  /* 段位与作者写在段间的分隔符都在这一层里:段位自己那身皮由 date-field 那份样式负责
182
180
  (它们戴的是那一份解剖的标记),这里只管把一排段位横过来、占满输入行剩下的宽度 */
183
181
  [data-scope='date-picker'][data-part='segment-group'] {
@@ -197,87 +195,88 @@
197
195
  display: none;
198
196
  }
199
197
 
198
+ [data-scope='date-picker'][data-part='segment-group'] > :not([data-scope]) {
199
+ color: var(--xh-date-picker-literal-fg, var(--xh-fg-subtle));
200
+ }
201
+
200
202
  /* 容器自己不占 Tab 位、也不承载焦点,环由 control 画,这里不再套一圈 */
201
203
  [data-scope='date-picker'][data-part='segment-group']:focus-visible {
202
204
  outline: none;
203
205
  }
204
206
 
205
- /* 两个按钮同一副长相:贴在框内末端的小方钮,不占宽度也不撑高 control */
207
+ /* 两个按钮同一副长相:贴在框内末端的小方钮,不占宽度也不撑高 control。正方视觉盒、inset 圆角、
208
+ 悬停 100 / 按下 200 与 0.97 按压、粗指针热区、禁用面与 :focus-visible 关环(盒的 :focus-within
209
+ 已画了一圈)全由 Action Control 的 field-inset ghost 档给,组件只映射既有覆盖槽。
210
+ 打开中与悬停同档:日历钮不另上底,方向由浮层本身承担 */
206
211
  [data-scope='date-picker'][data-part='trigger'],
207
212
  [data-scope='date-picker'][data-part='clear-trigger'] {
208
- display: inline-flex;
209
- flex: none;
210
- align-items: center;
211
- justify-content: center;
212
- inline-size: var(--xh-date-picker-action-size, var(--xh-control-action-size));
213
- block-size: var(--xh-date-picker-action-size, var(--xh-control-action-size));
214
- padding: 0;
215
- border: 0;
216
- border-radius: var(--xh-date-picker-action-radius, var(--xh-shape-control));
217
- background: var(--xh-date-picker-action-bg, transparent);
218
- color: var(--xh-date-picker-action-fg, var(--xh-fg-muted));
219
- font-family: inherit;
220
- font-size: var(--xh-date-picker-action-font-size, var(--xh-text-secondary-size));
221
- line-height: var(--xh-leading-none);
222
- cursor: pointer;
223
- user-select: none;
224
- transition: background var(--xh-motion-duration-micro) var(--xh-motion-ease-enter), scale var(--xh-motion-duration-micro) var(--xh-motion-ease-enter);
225
- }
226
-
227
-
213
+ --xh-action-visual-size: var(--xh-date-picker-action-size, var(--xh-_action-profile-visual-size));
214
+ --xh-action-min-inline-size: var(--xh-date-picker-action-size, var(--xh-_action-profile-visual-size));
215
+ --xh-action-radius: var(--xh-date-picker-action-radius, var(--xh-shape-inset));
216
+ /* 底色阶梯由 ghost 档给(透明 → 100 → 200),使用者槽只作覆盖入口 */
217
+ --xh-action-bg-rest: var(--xh-date-picker-action-bg, var(--xh-_action-variant-bg-rest));
218
+ --xh-action-bg-hover: var(--xh-date-picker-action-bg-hover, var(--xh-_action-variant-bg-hover));
219
+ --xh-action-bg-pressed: var(--xh-date-picker-action-bg-active, var(--xh-_action-variant-bg-pressed));
220
+ --xh-action-fg-rest: var(--xh-date-picker-action-fg, var(--xh-fg-muted));
221
+ --xh-action-fg-hover: var(--xh-date-picker-action-fg-hover, var(--xh-fg-default));
222
+ --xh-action-border-rest: transparent;
223
+ --xh-action-highlight-rest: transparent;
224
+ --xh-action-shadow-rest: none;
225
+ --xh-action-shadow-hover: none;
226
+ --xh-action-shadow-pressed: none;
227
+ --xh-action-font-size: var(--xh-date-picker-action-font-size, var(--xh-text-secondary-size));
228
+ /* 配方尚未把 profile 字形档灌进 --xh-icon-size,钮内字形先按 field-inset 档逐钮取值 */
229
+ --xh-icon-size: var(--xh-_action-profile-glyph-size);
230
+
231
+ border-width: 0;
232
+ }
233
+
234
+ /* 没值时连接层给的是 hidden 属性;家族那条 display 会把 UA 规则盖掉 */
228
235
  [data-scope='date-picker'][data-part='trigger'][hidden],
229
236
  [data-scope='date-picker'][data-part='clear-trigger'][hidden] {
230
237
  display: none;
231
238
  }
232
239
 
233
- [data-scope='date-picker'][data-part='trigger']:hover:not(:disabled),
234
- [data-scope='date-picker'][data-part='clear-trigger']:hover {
235
- background: var(--xh-date-picker-action-bg-hover, var(--xh-bg-subtle-hover));
236
- color: var(--xh-date-picker-action-fg-hover, var(--xh-fg-default));
237
- }
238
-
239
- [data-scope='date-picker'][data-part='trigger']:active:not(:disabled) {
240
- background: var(--xh-date-picker-action-bg-active, var(--xh-bg-subtle-active));
241
- }
242
-
243
- [data-scope='date-picker'][data-part='clear-trigger']:active {
244
- background: var(--xh-date-picker-action-bg-active, var(--xh-bg-subtle-active));
245
- scale: var(--xh-motion-scale-press);
246
- }
247
-
248
- /* 展开时按钮压一层底色,与浮层的存在互相印证 */
240
+ /* 打开中与悬停同档:日历钮的静息底换到悬停那一支中性面,不用品牌色、不另画环;方向由浮层本身承担 */
249
241
  [data-scope='date-picker'][data-part='trigger'][data-state='open'] {
250
- background: var(--xh-date-picker-action-bg-active, var(--xh-bg-subtle-active));
251
- color: var(--xh-date-picker-action-fg-hover, var(--xh-fg-default));
242
+ --xh-action-bg-rest: var(--xh-date-picker-action-bg-hover, var(--xh-_action-variant-bg-hover));
243
+ --xh-action-fg-rest: var(--xh-date-picker-action-fg-hover, var(--xh-fg-default));
252
244
  }
253
245
 
254
- /* 清空按钮不占 Tab 位(tabindex=-1),这条是给程序化聚焦兜底:落焦时得看得见。
255
- 展开钮是常规 Tab 停靠点,它落焦时环由盒的 :focus-within 画,这里不再套一圈 */
256
- [data-scope='date-picker'][data-part='clear-trigger']:focus-visible {
257
- outline: var(--xh-ring-width) solid var(--xh-_date-picker-ring);
258
- outline-offset: var(--xh-ring-offset);
259
- }
260
-
261
- [data-scope='date-picker'][data-part='trigger']:disabled {
262
- background: var(--xh-date-picker-action-bg, transparent);
263
- color: var(--xh-fg-disabled);
264
- cursor: not-allowed;
246
+ /* 有值时清空钮顶上来,日历钮让位:两颗并排堆着用户分不清点哪个 */
247
+ [data-scope='date-picker'][data-part='control']:has(
248
+ > [data-scope='date-picker'][data-part='clear-trigger']:not([hidden])
249
+ )
250
+ > [data-scope='date-picker'][data-part='trigger'] {
251
+ display: none;
265
252
  }
266
253
 
254
+ /* 浮层:含日历网格与时间列的锚定面板,走 floating 材质——实体底 + --xh-border-default 描边 +
255
+ --xh-elevation-floating 落影,不透景、不画顶光 */
267
256
  [data-scope='date-picker'][data-part='content'] {
257
+ position: relative;
268
258
  display: block;
269
- padding-block: var(--xh-date-picker-content-py, var(--xh-space-3));
270
- padding-inline: var(--xh-date-picker-content-px, var(--xh-space-3));
259
+ /* 行内轴只有落位后的可用宽度这一个上限:不夹住,浮层就会被定位层的包含块压窄,
260
+ 网格轨道跟着缩到比日期钮还窄,相邻两颗日期钮互相盖住 */
261
+ max-inline-size: var(--xh-_date-picker-available-w);
262
+ padding-block: var(--xh-date-picker-content-py, var(--xh-space-2));
263
+ padding-inline: var(--xh-date-picker-content-px, var(--xh-space-2));
271
264
  border: var(--xh-stroke-thin) solid var(--xh-date-picker-content-border, var(--xh-border-default));
272
- border-radius: var(--xh-date-picker-content-radius, var(--xh-shape-surface));
265
+ border-radius: var(--xh-date-picker-content-radius, var(--xh-shape-overlay));
273
266
  background: var(--xh-date-picker-content-bg, var(--xh-bg-surface));
274
267
  color: var(--xh-date-picker-content-fg, var(--xh-fg-default));
275
268
  /* 日历是定高结构:六行日期加表头本来就有固定高度,上限走页内滚动面那一档;
276
269
  可用高度是定位引擎算出的视口余量,视口真放不下时再收一截 */
277
270
  max-block-size: min(var(--xh-date-picker-max-h, var(--xh-viewport-h-lg)), var(--xh-_date-picker-available-h));
278
- overflow-y: auto;
271
+ /* 两轴都滚:块轴放不下时面板内自己竖滚,行内轴放不下时面板内自己横滚,
272
+ 日历那几块保持各自的天然宽度,不被压 */
273
+ overflow: auto;
274
+ /* 浮层滚动面:滚到头不把页面一起带走 */
275
+ overscroll-behavior: contain;
279
276
  box-shadow: var(--xh-date-picker-content-shadow, var(--xh-elevation-floating));
280
277
  pointer-events: auto;
278
+ /* 快捷选项列与时间列的条子贴在各自的盒子上、挂在这一层里(它已是定位盒):轨道不画底 */
279
+ --xh-scrollbar-track-bg: transparent;
281
280
  }
282
281
 
283
282
  /* 这里刻意没有 [data-part='content'][hidden] { display: none },与 dialog 一致:
@@ -293,179 +292,414 @@
293
292
  }
294
293
 
295
294
  [data-scope='date-picker'][data-part='content'][data-state='open'] {
296
- animation: xh-pop-in var(--xh-motion-duration-enter) var(--xh-motion-ease-enter);
295
+ /* 只在展开态挂着:随状态属性一起消失,不长期占着合成层 */
296
+ will-change: opacity, translate;
297
+ animation: xh-overlay-slide-in var(--xh-motion-duration-enter) var(--xh-motion-ease-enter-strong);
297
298
  }
298
299
 
299
300
  /* 退场:收起那一帧 hidden 由退场闸门押后,这里才播得出来。forwards 把末态钉住,
300
301
  免得动画结束到真收起之间闪一下原样 */
301
302
  [data-scope='date-picker'][data-part='content'][data-state='closed'] {
302
- animation: xh-pop-out var(--xh-motion-duration-exit) var(--xh-motion-ease-exit) forwards;
303
+ animation: xh-overlay-slide-out var(--xh-motion-duration-exit) var(--xh-motion-ease-exit) forwards;
303
304
  }
304
305
 
305
306
  /* 内嵌日历的挂载点同时充当日历的根节点:日历那份样式的 root 规则落在
306
- [data-scope='calendar'][data-part='root'] 上,而这里没有那个节点,
307
- 所以网格外层该有的排布得在这儿补齐(网格内部的皮仍归 calendar 那一份) */
307
+ [data-scope='calendar-picker'][data-part='root'] 上,而这里没有那个节点,
308
+ 所以网格外层该有的排布得在这儿补齐(网格内部的皮仍归 calendar-picker 那一份) */
308
309
  /* 真的摆了两张日历才横过来。写成 :has 而不是无条件 flex 行:
309
310
  showTime 那套结构里 content 直属子节点是作者自己的包裹块与确认行,
310
311
  无条件横排会把它们并到日历旁边去。
311
312
  不加 :not([hidden]):content 收起态带 hidden 但仍在播退场动画,
312
- 排除掉会让它在那几帧退回 block、两张日历竖着堆一下 */
313
+ 排除掉会让它在那几帧退回 block、两张日历竖着堆一下。
314
+ 并排放不下就折行,第二张月历落到第一张下面:视口窄与面板被夹窄都命中这一条 */
313
315
  [data-scope='date-picker'][data-part='content']:has(> [data-part='calendar'] + [data-part='calendar']) {
314
316
  display: flex;
317
+ flex-wrap: wrap;
315
318
  align-items: flex-start;
316
319
  }
317
320
 
318
321
  /* 快捷选项列摆在日历的行内起始一侧,同样只在它真在场时才横过来。
319
- 与上一条同理:不加 :not([hidden]),退场那几帧塌回 block 会让两块竖着堆一下 */
320
- [data-scope='date-picker'][data-part='content']:has(> [data-part='presets']) {
322
+ 与上一条同理:不加 :not([hidden]),退场那几帧塌回 block 会让两块竖着堆一下。
323
+ 一并折行:选项条在手机档占满一行,日历落到它下面 */
324
+ [data-scope='date-picker'][data-part='content']:has(> [data-part='preset-group']) {
321
325
  display: flex;
326
+ flex-wrap: wrap;
322
327
  align-items: stretch;
323
328
  }
324
329
 
325
- /* 第二个起的面板画一道左分隔线:两张网格挨着排时要有条界,
326
- 否则 8 月末与 9 月初那两列看着像同一张表 */
330
+ /* showTime 的时间列与日历同处一条可折行的行内流:放得下就并排贴在日历旁边,
331
+ 放不下时整组时间列折到日历下面,几列彼此仍横着排。
332
+ 不写这一条时 content 是 block,时列与分列会各占满一行竖着摞成一长条 */
333
+ [data-scope='date-picker'][data-part='content']:has(> [data-part='time-column']) {
334
+ display: flex;
335
+ flex-wrap: wrap;
336
+ align-items: flex-start;
337
+ }
338
+
339
+ /* 确认按钮沉到所在那一行的底边:它是整块面板的出口,不跟日历顶边对齐 */
340
+ [data-scope='date-picker'][data-part='content']:has(> [data-part='time-column']) > [data-part='confirm-trigger'] {
341
+ align-self: flex-end;
342
+ }
343
+
344
+ /* 第二个起的面板画一道分隔线:两张网格挨着排时要有条界,
345
+ 否则 8 月末与 9 月初那两列看着像同一张表。
346
+ 手机档两张月历折行堆叠,线画在块起始边 */
327
347
  [data-scope='date-picker'][data-part='calendar'] + [data-scope='date-picker'][data-part='calendar'] {
328
- padding-inline-start: var(--xh-date-picker-panel-gap, var(--xh-space-3));
329
- border-inline-start: var(--xh-stroke-thin) solid var(--xh-date-picker-panel-divider, var(--xh-border-subtle));
348
+ padding-block-start: var(--xh-date-picker-panel-gap, var(--xh-space-3));
349
+ border-block-start: var(--xh-stroke-thin) solid var(--xh-date-picker-panel-divider, var(--xh-material-frosted-separator));
330
350
  }
331
351
 
332
- /* 快捷选项列与它旁边那张日历之间留出同样的空当,两道分隔线左右对称 */
333
- [data-scope='date-picker'][data-part='presets'] + [data-scope='date-picker'][data-part='calendar'] {
334
- padding-inline-start: var(--xh-date-picker-panel-gap, var(--xh-space-3));
352
+ /* 平板起两张月历并排放得下,线改画在行内起始边 */
353
+ @media (min-width: 768px) {
354
+ [data-scope='date-picker'][data-part='calendar'] + [data-scope='date-picker'][data-part='calendar'] {
355
+ padding-block-start: 0;
356
+ padding-inline-start: var(--xh-date-picker-panel-gap, var(--xh-space-3));
357
+ border-block-start: none;
358
+ border-inline-start: var(--xh-stroke-thin) solid var(--xh-date-picker-panel-divider, var(--xh-material-frosted-separator));
359
+ }
360
+ }
361
+
362
+ /* 快捷选项与它旁边那张日历之间留出同样的空当。
363
+ 手机档选项条在上、日历在下,空当留在块轴。
364
+ 选项列后面紧跟着它自己的两条条子节点,相邻选择器接不到日历,按「前面有过选项列」取日历 */
365
+ [data-scope='date-picker'][data-part='preset-group'] ~ [data-scope='date-picker'][data-part='calendar'] {
366
+ padding-block-start: var(--xh-date-picker-panel-gap, var(--xh-space-3));
367
+ }
368
+
369
+ /* 平板起选项列回到日历一侧,空当跟着回到行内轴,两道分隔线左右对称 */
370
+ @media (min-width: 768px) {
371
+ [data-scope='date-picker'][data-part='preset-group'] ~ [data-scope='date-picker'][data-part='calendar'] {
372
+ padding-block-start: 0;
373
+ padding-inline-start: var(--xh-date-picker-panel-gap, var(--xh-space-3));
374
+ }
335
375
  }
336
376
 
337
377
  [data-scope='date-picker'][data-part='calendar'] {
338
378
  display: flex;
379
+ /* 面板被夹窄时不跟着缩:日期钮的宽度是定死的,网格轨道再窄下去就会与右邻的钮叠在一起。
380
+ 撑出去的那截交给面板自己横滚 */
381
+ min-inline-size: max-content;
339
382
  flex-direction: column;
340
- gap: var(--xh-date-picker-calendar-gap, var(--xh-space-3));
383
+ gap: var(--xh-date-picker-calendar-gap, var(--xh-space-2));
341
384
  /* 数字等宽:1 与 7 的字形宽度在比例字体里并不相同,不定住会让整张网格随月份抖动 */
342
385
  font-variant-numeric: tabular-nums;
343
386
  }
344
387
 
388
+ [data-scope='date-picker'][data-part='calendar']:has(+ [data-part='time-column']) {
389
+ position: relative;
390
+ }
391
+
392
+ [data-scope='date-picker'][data-part='calendar']:has(+ [data-part='time-column'])::after {
393
+ content: '';
394
+ position: absolute;
395
+ inset-block: 0;
396
+ inset-inline-end: calc(-1 * var(--xh-stroke-thin));
397
+ inline-size: var(--xh-stroke-thin);
398
+ background: var(--xh-date-picker-column-divider, var(--xh-material-frosted-separator));
399
+ pointer-events: none;
400
+ }
401
+
345
402
  [data-scope='date-picker'][data-part='calendar'][hidden] {
346
403
  display: none;
347
404
  }
348
405
 
349
- /* —— 快捷选项:一列按钮式条目,贴在日历的行内起始一侧 —— */
350
- [data-scope='date-picker'][data-part='presets'] {
406
+ /* —— 快捷选项:一条按钮式条目 —— */
407
+ /* 手机档:整条压在面板顶部占满一行,条目横着排,放不下就这一条自己横滚 */
408
+ [data-scope='date-picker'][data-part='preset-group'] {
351
409
  display: flex;
352
- flex: none;
353
- /* 这一列的高度由并排的日历给:不写就按内容收,右侧那道分隔线只画到最后一条选项 */
410
+ /* 独占面板的一整行,后面的日历折到它下面 */
411
+ flex: 0 0 100%;
412
+ /* 这一条的另一轴由并排的那块给:不写就按内容收,分隔线只画到最后一条选项 */
354
413
  align-self: stretch;
355
- flex-direction: column;
356
- gap: var(--xh-date-picker-presets-gap, var(--xh-list-option-gap));
357
- /* 选项多起来时这一列自己滚,不把整张面板撑高 */
358
- max-block-size: var(--xh-date-picker-presets-h, var(--xh-viewport-h-lg));
359
- padding: var(--xh-date-picker-presets-padding, var(--xh-space-1));
360
- overflow-y: auto;
361
- border-inline-end: var(--xh-stroke-thin) solid var(--xh-date-picker-column-divider, var(--xh-border-subtle));
414
+ flex-direction: row;
415
+ gap: var(--xh-date-picker-preset-group-gap, var(--xh-list-option-gap));
416
+ /* 选项多起来时这一条自己滚,不把整张面板撑大 */
417
+ max-block-size: var(--xh-date-picker-preset-group-h, var(--xh-viewport-h-lg));
418
+ padding: var(--xh-date-picker-preset-group-padding, var(--xh-space-1));
419
+ overflow-x: auto;
420
+ overflow-y: hidden;
421
+ /* 浮层滚动面:滚到头不把页面一起带走 */
422
+ overscroll-behavior: contain;
423
+ border-block-end: var(--xh-stroke-thin) solid var(--xh-date-picker-column-divider, var(--xh-material-frosted-separator));
424
+ }
425
+
426
+ /* 平板起:换成贴在日历行内起始一侧的竖列,滚动轴与分隔线一起转过来 */
427
+ @media (min-width: 768px) {
428
+ [data-scope='date-picker'][data-part='preset-group'] {
429
+ flex: none;
430
+ flex-direction: column;
431
+ overflow: auto;
432
+ border-block-end: none;
433
+ border-inline-end: var(--xh-stroke-thin) solid var(--xh-date-picker-column-divider, var(--xh-material-frosted-separator));
434
+ }
362
435
  }
363
436
 
364
- [data-scope='date-picker'][data-part='presets'][hidden] {
437
+ [data-scope='date-picker'][data-part='preset-group'][hidden] {
365
438
  display: none;
366
439
  }
367
440
 
441
+ /* 快捷选项:悬停 / 高亮 100、按下 200、禁用面由 Collection Item 家族按 overlay 语境给(选中 = 透明底 +
442
+ 行尾对号,正文保持 rest 色与常规字重)。选项没有正文部件,匿名文本进不了家族网格的 text 列,
443
+ 行保持块级排版,末端为对号预留固定轨 */
368
444
  [data-scope='date-picker'][data-part='preset'] {
369
- padding-block: var(--xh-date-picker-preset-py, var(--xh-space-1));
370
- padding-inline: var(--xh-date-picker-preset-px, var(--xh-space-3));
371
- border-radius: var(--xh-date-picker-preset-radius, var(--xh-shape-control));
372
- font-size: var(--xh-text-secondary-size);
373
- line-height: var(--xh-leading-normal);
445
+ --xh-collection-block-padding: var(--xh-date-picker-preset-py, var(--xh-space-1));
446
+ --xh-collection-inline-padding: var(--xh-date-picker-preset-px, var(--xh-space-3));
447
+ --xh-collection-font-size: var(--xh-text-secondary-size);
448
+ --xh-collection-radius: var(--xh-date-picker-preset-radius, var(--xh-shape-control));
449
+ /* 面板是实体面(floating),正文取页面前景 */
450
+ --xh-collection-fg-rest: var(--xh-fg-default);
451
+ --xh-collection-fg-hover: var(--xh-fg-default);
452
+ --xh-collection-fg-keyboard-highlight: var(--xh-fg-default);
453
+ --xh-collection-fg-pressed: var(--xh-fg-default);
454
+ --xh-collection-fg-selected: var(--xh-date-picker-preset-fg-selected, var(--xh-fg-default));
455
+ --xh-collection-fg-selected-highlight: var(--xh-date-picker-preset-fg-selected, var(--xh-fg-default));
456
+ --xh-collection-fg-selected-hover: var(--xh-date-picker-preset-fg-selected, var(--xh-fg-default));
457
+ --xh-collection-fg-selected-pressed: var(--xh-date-picker-preset-fg-selected, var(--xh-fg-default));
458
+ --xh-collection-fg-disabled: var(--xh-date-picker-preset-fg-disabled, var(--xh-fg-disabled));
459
+ --xh-collection-bg-hover: var(--xh-date-picker-preset-bg-hover, var(--xh-bg-subtle));
460
+ --xh-collection-bg-keyboard-highlight: var(--xh-date-picker-preset-bg-hover, var(--xh-bg-subtle));
461
+ --xh-collection-bg-selected-highlight: var(--xh-date-picker-preset-bg-hover, var(--xh-bg-subtle));
462
+ --xh-collection-bg-selected-hover: var(--xh-date-picker-preset-bg-hover, var(--xh-bg-subtle));
463
+ --xh-collection-bg-pressed: var(--xh-date-picker-preset-bg-pressed, var(--xh-bg-subtle-hover));
464
+ --xh-collection-bg-selected-pressed: var(--xh-date-picker-preset-bg-pressed, var(--xh-bg-subtle-hover));
465
+ --xh-collection-outline-keyboard-highlight: transparent;
466
+ --xh-collection-outline-selected-highlight: transparent;
467
+
468
+ /* 横着排那一档不许被压扁:条目文本本来就不折行 */
469
+ position: relative;
470
+ display: block;
471
+ flex: none;
472
+ /* 对号的末端轨始终留着,切换选中时文字与整列宽度都不移动。 */
473
+ padding-inline-end: calc(
474
+ var(--xh-date-picker-preset-px, var(--xh-space-3)) +
475
+ var(--xh-date-picker-preset-check-size, var(--xh-glyph-size-sm)) +
476
+ var(--xh-space-1)
477
+ );
374
478
  white-space: nowrap;
375
- cursor: pointer;
376
479
  user-select: none;
377
480
  }
378
481
 
379
- /* 悬停与键盘锚点共用中性轻档,命中那一条才走品牌淡底——两档靠色相分家;禁用的不响应悬停 */
380
- [data-scope='date-picker'][data-part='preset']:hover:not([data-disabled]) {
381
- background: var(--xh-date-picker-preset-bg-hover, var(--xh-bg-subtle));
482
+ /* 键盘焦点出现时环才接回并立即到位,不压在背景过渡的中间帧上 */
483
+ [data-scope='date-picker'][data-part='preset']:focus-visible:not(:hover) {
484
+ --xh-collection-outline-keyboard-highlight: var(--xh-ring-focus);
485
+ --xh-collection-outline-selected-highlight: var(--xh-ring-focus);
486
+
487
+ transition: none;
382
488
  }
383
489
 
384
- [data-scope='date-picker'][data-part='preset']:focus-visible,
385
- [data-scope='date-picker'][data-part='presets']:focus-visible {
386
- outline: var(--xh-ring-width) solid var(--xh-ring-focus);
387
- outline-offset: calc(-1 * var(--xh-ring-width));
490
+ /* 上面给了 display,UA 的 [hidden]{display:none} 已被盖掉,这里补回来 */
491
+ [data-scope='date-picker'][data-part='preset'][hidden] {
492
+ display: none;
388
493
  }
389
494
 
390
- [data-scope='date-picker'][data-part='preset'][data-state='checked'] {
391
- background: var(--xh-date-picker-preset-bg-selected, var(--xh-_date-picker-accent-subtle));
392
- color: var(--xh-date-picker-preset-fg-selected, var(--xh-_date-picker-accent-subtle-fg));
393
- font-weight: var(--xh-font-weight-medium);
495
+ [data-scope='date-picker'][data-part='preset']::after {
496
+ content: '';
497
+ position: absolute;
498
+ inset-block-start: 50%;
499
+ inset-inline-end: var(--xh-date-picker-preset-px, var(--xh-space-3));
500
+ inline-size: var(--xh-date-picker-preset-check-size, var(--xh-glyph-size-sm));
501
+ block-size: var(--xh-date-picker-preset-check-size, var(--xh-glyph-size-sm));
502
+ translate: 0 -50%;
503
+ background-color: var(--xh-date-picker-preset-check-fg, var(--xh-_date-picker-check-fg));
504
+ opacity: 0;
505
+ pointer-events: none;
506
+ transition: opacity var(--xh-motion-duration-micro) var(--xh-motion-ease-enter);
507
+ -webkit-mask: var(--xh-glyph-mark-check) center / contain no-repeat;
508
+ mask: var(--xh-glyph-mark-check) center / contain no-repeat;
394
509
  }
395
510
 
396
- [data-scope='date-picker'][data-part='preset'][data-disabled] {
397
- color: var(--xh-date-picker-preset-fg-disabled, var(--xh-fg-disabled));
398
- cursor: not-allowed;
511
+ [data-scope='date-picker'][data-part='preset'][data-state='checked']::after {
512
+ opacity: 1;
513
+ }
514
+
515
+ [data-scope='date-picker'][data-part='preset'][data-disabled]::after {
516
+ background-color: var(--xh-date-picker-preset-fg-disabled, var(--xh-fg-disabled));
399
517
  }
400
518
 
401
519
  /* —— showTime:时间列贴在日历右侧、逐列滚动,确认按钮收口 ——
402
520
  content 是 block,作者把日历与时间列包进一行排布;列自身只管滚与选项画法 */
403
521
  [data-scope='date-picker'][data-part='time-column'] {
404
522
  display: flex;
523
+ flex: none;
405
524
  flex-direction: column;
406
- gap: var(--xh-date-picker-time-column-gap, var(--xh-list-option-gap));
525
+ gap: var(--xh-date-picker-time-column-gap, 0);
526
+ min-inline-size: var(--xh-date-picker-time-column-min-w, var(--xh-overlay-column-min-w));
407
527
  /* 几列并排:定高而不是随内容收,否则时列与分列的可选值一多一少就错位 */
408
- block-size: var(--xh-date-picker-time-column-h, var(--xh-viewport-h-sm));
409
- padding: var(--xh-date-picker-time-column-padding, var(--xh-space-1));
528
+ block-size: var(
529
+ --xh-date-picker-time-column-h,
530
+ min(var(--xh-viewport-h-md), calc(var(--xh-control-h-sm) * 7 + var(--xh-space-7)))
531
+ );
532
+ margin-block-start: var(
533
+ --xh-date-picker-time-column-offset,
534
+ calc(var(--xh-control-h-sm) + var(--xh-date-picker-calendar-gap, var(--xh-space-2)))
535
+ );
536
+ padding-block: var(--xh-date-picker-time-column-padding, var(--xh-space-1));
537
+ padding-inline: var(--xh-date-picker-time-column-px, 0);
538
+ overflow-x: hidden;
410
539
  overflow-y: auto;
411
- border-inline-start: var(--xh-stroke-thin) solid var(--xh-date-picker-column-divider, var(--xh-border-subtle));
540
+ /* 浮层滚动面:滚到头不把页面一起带走 */
541
+ overscroll-behavior: contain;
542
+ border-inline-start: var(--xh-stroke-thin) solid var(--xh-date-picker-column-divider, var(--xh-material-frosted-separator));
412
543
  }
413
544
 
414
545
  [data-scope='date-picker'][data-part='time-column'][hidden] {
415
546
  display: none;
416
547
  }
417
548
 
549
+ /* 时间格:悬停 / 高亮 100、按下 200 由 Collection Item 家族按 overlay 语境给,选中只留末端对号——
550
+ 浮层瞬态集合的选中不上品牌淡底、不加粗、不变字色。格里只有数字、没有正文部件,保持自己的
551
+ 居中排版与等宽标记轨,家族只给状态面。行的字色与字重按值选择族的同一套映射写(--xh-date-picker-time-item-fg
552
+ / -fg-selected / -font-weight-selected 使用者槽,缺省落家族配方的行字色 --xh-material-frosted-fg:
553
+ 它在各主题与 forced-colors 下都等于 --xh-fg-default,floating 面板上的面色仍由 content 自己给) */
418
554
  [data-scope='date-picker'][data-part='time-item'] {
419
- padding-block: var(--xh-date-picker-time-item-py, var(--xh-space-1));
420
- padding-inline: var(--xh-date-picker-time-item-px, var(--xh-space-3));
421
- border-radius: var(--xh-date-picker-time-item-radius, var(--xh-shape-control));
422
- font-size: var(--xh-text-secondary-size);
423
- line-height: var(--xh-leading-normal);
555
+ --xh-_date-picker-time-item-rail: max(
556
+ var(--xh-date-picker-time-item-px, var(--xh-space-0_5)),
557
+ calc(var(--xh-date-picker-time-item-check-size, var(--xh-_date-picker-time-item-check-size)) + var(--xh-space-0_5))
558
+ );
559
+ --xh-collection-block-padding: var(--xh-date-picker-time-item-py, 0);
560
+ --xh-collection-inline-padding: var(--xh-_date-picker-time-item-rail);
561
+ --xh-collection-font-size: var(--xh-text-secondary-size);
562
+ --xh-collection-radius: var(--xh-date-picker-time-item-radius, var(--xh-shape-control));
563
+ --xh-collection-fg-rest: var(--xh-date-picker-time-item-fg, var(--xh-material-frosted-fg));
564
+ --xh-collection-fg-hover: var(--xh-date-picker-time-item-fg, var(--xh-material-frosted-fg));
565
+ --xh-collection-fg-keyboard-highlight: var(--xh-date-picker-time-item-fg, var(--xh-material-frosted-fg));
566
+ --xh-collection-fg-pressed: var(--xh-date-picker-time-item-fg, var(--xh-material-frosted-fg));
567
+ --xh-collection-fg-selected: var(--xh-date-picker-time-item-fg-selected, var(--xh-date-picker-time-item-fg, var(--xh-material-frosted-fg)));
568
+ --xh-collection-fg-selected-highlight: var(--xh-date-picker-time-item-fg-selected, var(--xh-date-picker-time-item-fg, var(--xh-material-frosted-fg)));
569
+ --xh-collection-fg-selected-hover: var(--xh-date-picker-time-item-fg-selected, var(--xh-date-picker-time-item-fg, var(--xh-material-frosted-fg)));
570
+ --xh-collection-fg-selected-pressed: var(--xh-date-picker-time-item-fg-selected, var(--xh-date-picker-time-item-fg, var(--xh-material-frosted-fg)));
571
+ --xh-collection-font-weight-selected: var(--xh-date-picker-time-item-font-weight-selected, var(--xh-font-weight-regular));
572
+ --xh-collection-font-weight-selected-highlight: var(--xh-date-picker-time-item-font-weight-selected, var(--xh-font-weight-regular));
573
+ --xh-collection-font-weight-selected-hover: var(--xh-date-picker-time-item-font-weight-selected, var(--xh-font-weight-regular));
574
+ --xh-collection-font-weight-selected-pressed: var(--xh-date-picker-time-item-font-weight-selected, var(--xh-font-weight-regular));
575
+ --xh-collection-bg-hover: var(--xh-date-picker-time-item-bg-hover, var(--xh-bg-subtle));
576
+ --xh-collection-bg-keyboard-highlight: var(--xh-date-picker-time-item-bg-hover, var(--xh-bg-subtle));
577
+ --xh-collection-bg-selected-highlight: var(--xh-date-picker-time-item-bg-hover, var(--xh-bg-subtle));
578
+ --xh-collection-bg-selected-hover: var(--xh-date-picker-time-item-bg-hover, var(--xh-bg-subtle));
579
+ --xh-collection-bg-pressed: var(--xh-date-picker-time-item-bg-pressed, var(--xh-bg-subtle-hover));
580
+ --xh-collection-bg-selected-pressed: var(--xh-date-picker-time-item-bg-pressed, var(--xh-bg-subtle-hover));
581
+ --xh-collection-outline-keyboard-highlight: transparent;
582
+ --xh-collection-outline-selected-highlight: transparent;
583
+
584
+ position: relative;
585
+ display: flex;
586
+ flex: none;
587
+ align-items: center;
588
+ justify-content: center;
589
+ block-size: var(--xh-date-picker-time-item-h, calc(var(--xh-control-h-sm) - var(--xh-space-1)));
590
+ font-variant-numeric: tabular-nums;
424
591
  text-align: center;
425
- cursor: pointer;
592
+ white-space: nowrap;
426
593
  user-select: none;
427
594
  }
428
595
 
429
- [data-scope='date-picker'][data-part='time-item']:hover {
430
- background: var(--xh-date-picker-time-item-bg-hover, var(--xh-bg-subtle));
596
+ [data-scope='date-picker'][data-part='time-item'][hidden] {
597
+ display: none;
431
598
  }
432
599
 
433
- /* 键盘走到哪一格要看得见:这几列靠方向键逐格走,没有这一条就等于闭着眼挑 */
434
- [data-scope='date-picker'][data-part='time-item']:focus-visible,
435
- [data-scope='date-picker'][data-part='time-column']:focus-visible {
436
- outline: var(--xh-ring-width) solid var(--xh-ring-focus);
437
- outline-offset: calc(-1 * var(--xh-ring-width));
438
- }
600
+ /* 键盘焦点出现时环才接回并立即到位,不压在背景过渡的中间帧上 */
601
+ [data-scope='date-picker'][data-part='time-item']:focus-visible:not(:hover) {
602
+ --xh-collection-outline-keyboard-highlight: var(--xh-ring-focus);
603
+ --xh-collection-outline-selected-highlight: var(--xh-ring-focus);
439
604
 
440
- [data-scope='date-picker'][data-part='time-item'][data-state='checked'] {
441
- background: var(--xh-date-picker-time-item-bg-selected, var(--xh-_date-picker-accent-subtle));
442
- color: var(--xh-date-picker-time-item-fg-selected, var(--xh-_date-picker-accent-subtle-fg));
443
- font-weight: var(--xh-font-weight-medium);
605
+ transition: none;
444
606
  }
445
607
 
446
- [data-scope='date-picker'][data-part='confirm-trigger'] {
447
- display: inline-flex;
448
- align-items: center;
449
- justify-content: center;
450
- block-size: var(--xh-control-h-sm);
451
- padding-inline: var(--xh-date-picker-confirm-trigger-px, var(--xh-control-px-sm));
452
- border: none;
453
- border-radius: var(--xh-date-picker-confirm-trigger-radius, var(--xh-shape-control));
454
- background: var(--xh-date-picker-confirm-bg, var(--xh-_date-picker-accent));
455
- color: var(--xh-date-picker-confirm-fg, var(--xh-_date-picker-accent-fg));
456
- font-size: var(--xh-text-secondary-size);
457
- cursor: pointer;
608
+ [data-scope='date-picker'][data-part='time-item']::after {
609
+ content: '';
610
+ position: absolute;
611
+ inset-block-start: 50%;
612
+ /* 标记占轨道末端,内缘与正文之间恒留一档间隙;与 padding 读同一个 rail,避免重叠。 */
613
+ inset-inline-end: calc(
614
+ var(--xh-_date-picker-time-item-rail) -
615
+ var(--xh-date-picker-time-item-check-size, var(--xh-_date-picker-time-item-check-size)) -
616
+ var(--xh-space-1)
617
+ );
618
+ inline-size: var(--xh-date-picker-time-item-check-size, var(--xh-_date-picker-time-item-check-size));
619
+ block-size: var(--xh-date-picker-time-item-check-size, var(--xh-_date-picker-time-item-check-size));
620
+ translate: 0 -50%;
621
+ background-color: var(--xh-date-picker-time-item-check-fg, var(--xh-_date-picker-check-fg));
622
+ opacity: 0;
623
+ pointer-events: none;
624
+ transition: opacity var(--xh-motion-duration-micro) var(--xh-motion-ease-enter);
625
+ -webkit-mask: var(--xh-glyph-mark-check) center / contain no-repeat;
626
+ mask: var(--xh-glyph-mark-check) center / contain no-repeat;
458
627
  }
459
628
 
460
- [data-scope='date-picker'][data-part='confirm-trigger']:hover {
461
- background: var(--xh-date-picker-confirm-bg-hover, var(--xh-_date-picker-accent-hover));
629
+ [data-scope='date-picker'][data-part='time-item'][data-state='checked']::after {
630
+ opacity: 1;
462
631
  }
463
632
 
464
- [data-scope='date-picker'][data-part='confirm-trigger']:focus-visible {
465
- outline: var(--xh-ring-width) solid var(--xh-_date-picker-ring);
466
- outline-offset: var(--xh-ring-offset);
633
+ @media (width < 768px) {
634
+ [data-scope='date-picker'][data-part='content'] {
635
+ padding-inline: var(--xh-date-picker-content-px, var(--xh-space-2));
636
+ }
637
+
638
+ [data-scope='date-picker'][data-part='time-column'] {
639
+ min-inline-size: var(--xh-date-picker-time-column-min-w-mobile, 2.75rem);
640
+ padding-inline: var(--xh-date-picker-time-column-px-mobile, 0);
641
+ }
642
+
643
+ [data-scope='date-picker'][data-part='time-item'] {
644
+ --xh-_date-picker-time-item-rail: var(
645
+ --xh-date-picker-time-item-check-size,
646
+ var(--xh-_date-picker-time-item-check-size)
647
+ );
648
+ }
649
+
650
+ [data-scope='date-picker'][data-part='time-item']::after {
651
+ inset-inline-end: 0;
652
+ }
467
653
  }
468
654
 
655
+ /* 列整体禁用时格没有自己的 aria-disabled,禁用面按列的 aria-disabled 映射到家族槽:
656
+ 字色降级、悬停 / 高亮 / 按下不换面、光标 not-allowed */
657
+ [data-scope='date-picker'][data-part='time-column'][aria-disabled='true'] [data-part='time-item'] {
658
+ --xh-collection-fg-rest: var(--xh-fg-disabled);
659
+ --xh-collection-fg-hover: var(--xh-fg-disabled);
660
+ --xh-collection-fg-keyboard-highlight: var(--xh-fg-disabled);
661
+ --xh-collection-fg-pressed: var(--xh-fg-disabled);
662
+ --xh-collection-fg-selected: var(--xh-fg-disabled);
663
+ --xh-collection-bg-hover: transparent;
664
+ --xh-collection-bg-keyboard-highlight: transparent;
665
+ --xh-collection-bg-pressed: transparent;
666
+ --xh-collection-bg-selected-hover: transparent;
667
+ --xh-collection-bg-selected-highlight: transparent;
668
+ --xh-collection-bg-selected-pressed: transparent;
669
+ --xh-collection-cursor-rest: not-allowed;
670
+ --xh-collection-cursor-hover: not-allowed;
671
+ --xh-collection-cursor-keyboard-highlight: not-allowed;
672
+ --xh-collection-cursor-pressed: not-allowed;
673
+ --xh-collection-cursor-selected: not-allowed;
674
+ }
675
+
676
+ [data-scope='date-picker'][data-part='time-column'][aria-disabled='true'] [data-part='time-item']::after {
677
+ background-color: var(--xh-fg-disabled);
678
+ }
679
+
680
+ /* 确认钮是面板里唯一的主要动作:品牌实心、悬停 / 按下与 0.97 按压、焦点环全由 Action Control 的
681
+ text solid 档给;槽名统一按部件取 --xh-date-picker-confirm-trigger-*,只映射到家族桥接槽 */
682
+ [data-scope='date-picker'][data-part='confirm-trigger'] {
683
+ --xh-action-visual-size: var(--xh-date-picker-confirm-trigger-h, var(--xh-_action-profile-visual-size));
684
+ --xh-action-padding-inline: var(--xh-date-picker-confirm-trigger-px, var(--xh-_action-profile-padding-inline));
685
+ --xh-action-radius: var(--xh-date-picker-confirm-trigger-radius, var(--xh-shape-control));
686
+ --xh-action-bg-rest: var(--xh-date-picker-confirm-trigger-bg, var(--xh-_action-variant-bg-rest));
687
+ --xh-action-bg-hover: var(--xh-date-picker-confirm-trigger-bg-hover, var(--xh-_action-variant-bg-hover));
688
+ --xh-action-bg-pressed: var(--xh-date-picker-confirm-trigger-bg-active, var(--xh-_action-variant-bg-pressed));
689
+ --xh-action-fg-rest: var(--xh-date-picker-confirm-trigger-fg, var(--xh-_action-variant-fg-rest));
690
+ --xh-action-fg-hover: var(--xh-date-picker-confirm-trigger-fg, var(--xh-_action-variant-fg-hover));
691
+ --xh-action-fg-pressed: var(--xh-date-picker-confirm-trigger-fg, var(--xh-_action-variant-fg-pressed));
692
+ --xh-action-border-rest: transparent;
693
+ --xh-action-highlight-rest: transparent;
694
+ --xh-action-shadow-rest: var(--xh-date-picker-confirm-trigger-shadow, none);
695
+ --xh-action-shadow-hover: var(--xh-date-picker-confirm-trigger-shadow, none);
696
+ --xh-action-shadow-pressed: var(--xh-date-picker-confirm-trigger-shadow, none);
697
+ --xh-action-font-size: var(--xh-text-secondary-size);
698
+
699
+ border-width: 0;
700
+ }
701
+
702
+ /* 收起时连接层给的是 hidden 属性;家族那条 display 会把 UA 规则盖掉 */
469
703
  [data-scope='date-picker'][data-part='confirm-trigger'][hidden] {
470
704
  display: none;
471
705
  }
@@ -489,33 +723,36 @@
489
723
  block-size: var(--xh-icon-size, var(--xh-glyph-size-text));
490
724
  vertical-align: var(--xh-glyph-baseline-shift);
491
725
  background-color: currentColor;
492
- -webkit-mask: var(--xh-glyph-mark-chevron-down) center / contain no-repeat;
493
- mask: var(--xh-glyph-mark-chevron-down) center / contain no-repeat;
726
+ -webkit-mask: var(--xh-glyph-mark-calendar) center / contain no-repeat;
727
+ mask: var(--xh-glyph-mark-calendar) center / contain no-repeat;
494
728
  }
495
- }
496
729
 
497
- @layer xihan.motion {
498
- /* 浮层进场:淡入 + 轻微上浮。名字带组件前缀,不与公共关键帧抢名 */
499
- @keyframes xh-pop-in {
500
- from {
501
- opacity: 0;
502
- scale: var(--xh-motion-scale-enter);
730
+ @media (forced-colors: active) {
731
+ /* 系统接管底色后仍保住末端对号;禁用标记改用系统失效色。 */
732
+ [data-scope='date-picker'][data-part='preset']::after,
733
+ [data-scope='date-picker'][data-part='time-item']::after {
734
+ forced-color-adjust: none;
735
+ background-color: CanvasText;
503
736
  }
504
737
 
505
- to {
506
- opacity: 1;
507
- scale: 1;
738
+ [data-scope='date-picker'][data-part='preset'][data-disabled]::after,
739
+ [data-scope='date-picker'][data-part='time-column'][aria-disabled='true'] [data-part='time-item']::after {
740
+ background-color: GrayText;
508
741
  }
509
- }
510
- @keyframes xh-pop-out {
511
- from {
512
- opacity: 1;
513
- scale: 1;
742
+
743
+ [data-scope='date-picker'][data-part='preset'][data-disabled],
744
+ [data-scope='date-picker'][data-part='time-column'][aria-disabled='true'] [data-part='time-item'] {
745
+ color: GrayText;
514
746
  }
747
+ }
748
+ }
515
749
 
516
- to {
517
- opacity: 0;
518
- scale: var(--xh-motion-scale-enter);
750
+ @layer xihan.motion {
751
+ @media print {
752
+ /* 打印:定位层与遮罩是交互期才存在的东西,落到纸上只会盖住底下的正文。
753
+ 收起写在这份皮肤里而不是 reset:reset 层排在组件层之前,组件层里任何一条 display 都压得住它。 */
754
+ [data-scope='date-picker'][data-part='positioner'] {
755
+ display: none;
519
756
  }
520
757
  }
521
758
  }