@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.
Files changed (122) hide show
  1. package/CHANGELOG.md +2177 -0
  2. package/README.md +1 -1
  3. package/css/accordion.css +80 -6
  4. package/css/alert.css +43 -14
  5. package/css/anchor.css +8 -8
  6. package/css/avatar-group.css +7 -3
  7. package/css/avatar.css +9 -3
  8. package/css/back-top.css +22 -1
  9. package/css/badge.css +104 -32
  10. package/css/breadcrumb.css +25 -5
  11. package/css/button-group.css +18 -13
  12. package/css/button.css +48 -11
  13. package/css/calendar.css +150 -7
  14. package/css/card.css +20 -11
  15. package/css/carousel.css +36 -5
  16. package/css/cascader.css +211 -124
  17. package/css/checkbox-group.css +72 -22
  18. package/css/checkbox.css +70 -13
  19. package/css/clipboard.css +2 -1
  20. package/css/code-block.css +12 -7
  21. package/css/collapsible.css +49 -3
  22. package/css/color-picker.css +132 -46
  23. package/css/combobox.css +132 -60
  24. package/css/composer.css +5 -3
  25. package/css/context-menu.css +113 -74
  26. package/css/date-field.css +93 -16
  27. package/css/date-picker.css +293 -72
  28. package/css/descriptions.css +11 -5
  29. package/css/dialog.css +47 -14
  30. package/css/download-trigger.css +76 -0
  31. package/css/drawer.css +57 -16
  32. package/css/dynamic-input.css +75 -17
  33. package/css/editable.css +12 -10
  34. package/css/ellipsis.css +7 -1
  35. package/css/empty-state.css +22 -12
  36. package/css/field.css +16 -6
  37. package/css/fieldset.css +69 -0
  38. package/css/file-upload.css +46 -8
  39. package/css/flex.css +13 -7
  40. package/css/float-button.css +23 -1
  41. package/css/floating-panel.css +316 -0
  42. package/css/form.css +4 -4
  43. package/css/grid.css +11 -5
  44. package/css/heatmap.css +411 -0
  45. package/css/highlight.css +2 -2
  46. package/css/hotkeys.css +90 -0
  47. package/css/hover-card.css +43 -45
  48. package/css/image-cropper.css +233 -0
  49. package/css/image-viewer.css +155 -17
  50. package/css/image.css +2 -2
  51. package/css/infinite-scroll.css +1 -1
  52. package/css/json-viewer.css +274 -0
  53. package/css/layout.css +19 -15
  54. package/css/list.css +22 -13
  55. package/css/listbox.css +24 -6
  56. package/css/loading-bar.css +12 -5
  57. package/css/log.css +7 -3
  58. package/css/marquee.css +9 -0
  59. package/css/masonry.css +63 -0
  60. package/css/mention.css +100 -36
  61. package/css/menu.css +127 -50
  62. package/css/menubar.css +155 -61
  63. package/css/navigation-menu.css +56 -31
  64. package/css/notification.css +377 -0
  65. package/css/number-animation.css +3 -3
  66. package/css/number-field.css +182 -19
  67. package/css/overlay-arrow.css +51 -0
  68. package/css/page-header.css +12 -5
  69. package/css/pagination.css +171 -14
  70. package/css/password-input.css +356 -0
  71. package/css/pin-input.css +15 -12
  72. package/css/popconfirm.css +55 -12
  73. package/css/popover.css +73 -45
  74. package/css/popselect.css +207 -57
  75. package/css/progress.css +54 -8
  76. package/css/qr-code.css +1 -1
  77. package/css/radio-group.css +27 -10
  78. package/css/rating.css +4 -4
  79. package/css/reset.css +17 -0
  80. package/css/result.css +21 -11
  81. package/css/scroll-area.css +61 -89
  82. package/css/scrollbar.css +170 -0
  83. package/css/segmented.css +215 -0
  84. package/css/select.css +298 -131
  85. package/css/separator.css +2 -2
  86. package/css/side-nav.css +127 -24
  87. package/css/signature-pad.css +144 -0
  88. package/css/skeleton.css +7 -1
  89. package/css/slider.css +14 -12
  90. package/css/space.css +117 -0
  91. package/css/spinner.css +22 -10
  92. package/css/statistic.css +9 -9
  93. package/css/steps.css +29 -12
  94. package/css/switch.css +57 -8
  95. package/css/table.css +146 -44
  96. package/css/tabs.css +13 -5
  97. package/css/tag.css +179 -0
  98. package/css/tags-input.css +80 -42
  99. package/css/text-field.css +151 -38
  100. package/css/thread.css +11 -3
  101. package/css/time-field.css +99 -18
  102. package/css/time-picker.css +261 -71
  103. package/css/timeline.css +15 -15
  104. package/css/timer.css +119 -0
  105. package/css/toast.css +129 -55
  106. package/css/toggle-group.css +30 -4
  107. package/css/toggle.css +12 -6
  108. package/css/tone.css +57 -22
  109. package/css/toolbar.css +1 -1
  110. package/css/tooltip.css +40 -31
  111. package/css/tour.css +112 -61
  112. package/css/transfer.css +98 -21
  113. package/css/tree-select.css +215 -89
  114. package/css/tree.css +131 -5
  115. package/css/typography.css +5 -5
  116. package/css/undefined.css +12 -1
  117. package/css/virtualizer.css +3 -1
  118. package/css/watermark.css +1 -2
  119. package/index.css +18 -1
  120. package/index.unlayered.css +10356 -3255
  121. package/package.json +20 -4
  122. package/css/toaster.css +0 -74
package/css/menubar.css CHANGED
@@ -6,27 +6,23 @@
6
6
 
7
7
  /* 一排 trigger。主轴跟着 data-orientation 走:菜单栏本身可以横排也可以竖排 */
8
8
  [data-scope='menubar'][data-part='root'] {
9
- /* 尺寸档只换这五个私有槽,trigger 与菜单里的条目都从 root 继承它们,
10
- 换档不必给每个部件各写一条选择器。菜单浮层在 positioner 里、也是 root 的后代,一并继承 */
11
- --xh-_menubar-trigger-py: var(--xh-space-1);
12
- --xh-_menubar-trigger-px: var(--xh-control-px-sm);
13
- --xh-_menubar-item-py: var(--xh-space-1_5);
14
- --xh-_menubar-item-px: var(--xh-control-px-md);
15
- --xh-_menubar-font-size: var(--xh-text-body-size);
16
-
17
- /* 展开着的那张菜单的 trigger 走品牌淡底强档,随语气换色相;没写 data-tone 时退回品牌淡底。
18
- 悬停与键盘焦点恒中性灰轻档、不接语气槽——两档同色相的话哪张开着就认不出来了。
19
- 聚焦环不在其列,它恒是 --xh-ring-focus */
20
- --xh-_menubar-active-bg: var(--xh-_tone-subtle, var(--xh-bg-brand-subtle));
9
+ /* 作者塞进指示符槽的图标跟着字号走,与皮肤画的兜底字形同一把尺 */
10
+ --xh-icon-size: var(--xh-menubar-icon-size, var(--xh-glyph-size-text));
21
11
 
22
12
  display: flex;
23
13
  align-items: center;
24
- gap: var(--xh-menubar-gap, var(--xh-space-1));
25
- padding-block: var(--xh-menubar-py, var(--xh-space-1));
26
- padding-inline: var(--xh-menubar-px, var(--xh-space-1));
27
- border-radius: var(--xh-menubar-radius, var(--xh-shape-control));
28
- background: var(--xh-menubar-bg, transparent);
29
- color: var(--xh-menubar-fg, var(--xh-fg-default));
14
+ gap: var(--xh-menubar-root-gap, var(--xh-space-1));
15
+ padding-block: var(--xh-menubar-root-py, var(--xh-space-1));
16
+ padding-inline: var(--xh-menubar-root-px, var(--xh-space-1));
17
+ border-radius: var(--xh-menubar-root-radius, var(--xh-shape-control));
18
+ background: var(--xh-menubar-root-bg, transparent);
19
+ color: var(--xh-menubar-root-fg, var(--xh-fg-default));
20
+ }
21
+
22
+ /* 浮层被搬到 portal 落点,继承不到 root 上的槽:这把尺在被搬走的那一侧再声明一次,
23
+ 关闭钮与条目里作者塞的图标才和皮肤画的兜底字形一样大 */
24
+ [data-scope='menubar'][data-part='content'] {
25
+ --xh-icon-size: var(--xh-menubar-icon-size, var(--xh-glyph-size-text));
30
26
  }
31
27
 
32
28
  [data-scope='menubar'][data-part='root'][hidden] {
@@ -38,25 +34,6 @@
38
34
  align-items: stretch;
39
35
  }
40
36
 
41
- /* —— 尺寸 —— */
42
- /* 缺省档写在上面的基础规则里。trigger 的行内内缩缺省落在控件尺 sm 档、再往下取空间尺;
43
- 条目纵向走 space 档、行内内缩走 control-px 档(随密度轴),换档各挪一级 */
44
- [data-scope='menubar'][data-part='root'][data-size='sm'] {
45
- --xh-_menubar-trigger-py: var(--xh-space-0_5);
46
- --xh-_menubar-trigger-px: var(--xh-space-1_5);
47
- --xh-_menubar-item-py: var(--xh-space-1);
48
- --xh-_menubar-item-px: var(--xh-control-px-sm);
49
- --xh-_menubar-font-size: var(--xh-font-size-sm);
50
- }
51
-
52
- [data-scope='menubar'][data-part='root'][data-size='lg'] {
53
- --xh-_menubar-trigger-py: var(--xh-space-2);
54
- --xh-_menubar-trigger-px: var(--xh-control-px-md);
55
- --xh-_menubar-item-py: var(--xh-space-2);
56
- --xh-_menubar-item-px: var(--xh-control-px-lg);
57
- --xh-_menubar-font-size: var(--xh-font-size-lg);
58
- }
59
-
60
37
  /* root 只是 roving tabindex 的兜底落点,焦点转投给 trigger 之后就不再停留,不画环 */
61
38
  [data-scope='menubar'][data-part='root']:focus-visible {
62
39
  outline: none;
@@ -117,8 +94,12 @@
117
94
 
118
95
  /* 坐标由定位引擎写进 style(inset-inline-start / inset-block-start),这里只定位模式与层级 */
119
96
  [data-scope='menubar'][data-part='positioner'] {
97
+ /* 落定那一侧的可用高度,由定位引擎经内联自定义属性写进来,content 继承它限高;
98
+ 引擎没算(尚未落位 / 无引擎)时不额外限高 */
99
+ --xh-_menubar-available-h: 100vh;
100
+
120
101
  position: fixed;
121
- z-index: var(--xh-layer-popover);
102
+ z-index: var(--xh-menubar-layer, var(--xh-layer-popover));
122
103
  /* 空壳不吃指针,交互只发生在 content 上 */
123
104
  pointer-events: none;
124
105
  }
@@ -128,26 +109,72 @@
128
109
  visibility: hidden;
129
110
  }
130
111
 
112
+ /* —— 尺寸 —— */
113
+ /* 尺寸档只换这六个私有槽,换档不必给每个部件各写一条选择器。
114
+ root 与 positioner 各起一头:trigger 从 root 继承,菜单里的条目从 positioner 继承——
115
+ 浮层搬去了 portal 落点,不再是 root 的后代。
116
+ 缺省档写在第一条:trigger 与条目的行内内缩都走 control-px 档(随密度轴)、纵向走 space 档,换档各挪一级 */
117
+ [data-scope='menubar']:is([data-part='root'], [data-part='positioner']) {
118
+ --xh-_menubar-trigger-py: var(--xh-space-1);
119
+ --xh-_menubar-trigger-px: var(--xh-control-px-md);
120
+ --xh-_menubar-item-py: var(--xh-list-option-py-md);
121
+ --xh-_menubar-item-px: var(--xh-control-px-md);
122
+ --xh-_menubar-item-gap: var(--xh-control-gap-md);
123
+ --xh-_menubar-font-size: var(--xh-control-font-md);
124
+
125
+ /* 展开着的那张菜单的 trigger 走品牌淡底强档,随语气换色相;没写 data-tone 时退回品牌淡底。
126
+ 悬停与键盘焦点恒中性灰轻档、不接语气槽——两档同色相的话哪张开着就认不出来了。
127
+ 聚焦环不在其列,它恒是 --xh-ring-focus */
128
+ --xh-_menubar-active-bg: var(--xh-_tone-subtle, var(--xh-bg-brand-subtle));
129
+
130
+ /* 打开子菜单的触发条目走品牌淡底强档,随语气换色相;没写 data-tone 时退回品牌淡底 */
131
+ --xh-_menubar-item-active-bg: var(--xh-_tone-subtle, var(--xh-bg-brand-subtle));
132
+ }
133
+
134
+ [data-scope='menubar'][data-size='sm']:is([data-part='root'], [data-part='positioner']) {
135
+ --xh-_menubar-trigger-py: var(--xh-space-0_5);
136
+ --xh-_menubar-trigger-px: var(--xh-control-px-sm);
137
+ --xh-_menubar-item-py: var(--xh-list-option-py-sm);
138
+ --xh-_menubar-item-px: var(--xh-control-px-sm);
139
+ --xh-_menubar-item-gap: var(--xh-control-gap-sm);
140
+ --xh-_menubar-font-size: var(--xh-control-font-sm);
141
+ }
142
+
143
+ [data-scope='menubar'][data-size='lg']:is([data-part='root'], [data-part='positioner']) {
144
+ --xh-_menubar-trigger-py: var(--xh-space-2);
145
+ --xh-_menubar-trigger-px: var(--xh-control-px-lg);
146
+ --xh-_menubar-item-py: var(--xh-list-option-py-lg);
147
+ --xh-_menubar-item-px: var(--xh-control-px-lg);
148
+ --xh-_menubar-item-gap: var(--xh-control-gap-lg);
149
+ --xh-_menubar-font-size: var(--xh-control-font-lg);
150
+ }
151
+
131
152
  [data-scope='menubar'][data-part='content'] {
132
153
  display: flex;
133
154
  flex-direction: column;
134
- min-inline-size: var(--xh-menubar-menu-min-w, var(--xh-overlay-menu-min-w));
135
- max-inline-size: var(--xh-menubar-menu-max-w, 20rem);
136
- padding-block: var(--xh-menubar-menu-py, var(--xh-space-1));
137
- padding-inline: var(--xh-menubar-menu-px, var(--xh-space-1));
138
- border: var(--xh-stroke-thin) solid var(--xh-menubar-menu-border, var(--xh-border-default));
139
- border-radius: var(--xh-menubar-menu-radius, var(--xh-shape-surface));
140
- background: var(--xh-menubar-menu-bg, var(--xh-bg-surface));
141
- color: var(--xh-menubar-menu-fg, var(--xh-fg-default));
142
- box-shadow: var(--xh-menubar-menu-shadow, var(--xh-elevation-2));
155
+ gap: var(--xh-menubar-content-gap, var(--xh-list-option-gap));
156
+ min-inline-size: var(--xh-menubar-min-w, var(--xh-overlay-menu-min-w));
157
+ max-inline-size: var(--xh-menubar-max-w, var(--xh-overlay-max-w));
158
+ /* 两道上限取更小的那道:自己的高度上限,以及落定那一侧真正剩下的空间。
159
+ 列表族的 16rem 对命令菜单偏矮,这里另给一档 */
160
+ max-block-size: min(var(--xh-menubar-max-h, var(--xh-overlay-menu-max-h)), var(--xh-_menubar-available-h));
161
+ padding-block: var(--xh-menubar-py, var(--xh-space-1));
162
+ padding-inline: var(--xh-menubar-px, var(--xh-space-1));
163
+ border: var(--xh-stroke-thin) solid var(--xh-menubar-border, var(--xh-border-default));
164
+ border-radius: var(--xh-menubar-radius, var(--xh-shape-surface));
165
+ background: var(--xh-menubar-bg, var(--xh-bg-surface));
166
+ color: var(--xh-menubar-fg, var(--xh-fg-default));
167
+ box-shadow: var(--xh-menubar-shadow, var(--xh-elevation-floating));
168
+ /* 条目超过上限就在菜单内部滚。条目的焦点环是内收的,滚动容器裁在内边距缘上,环切不着 */
169
+ overflow-y: auto;
143
170
  pointer-events: auto;
144
171
  }
145
172
 
146
173
  /* display 会盖掉 hidden 属性的 UA 规则,收起态显式让位。
147
174
  连接层给 content 发 hidden,这一条漏了整张菜单就永远收不起来 */
148
- [data-scope='menubar'][data-part='content'][hidden] {
149
- display: none;
150
- }
175
+ /* 这里刻意没有 [data-part='content'][hidden] { display: none },与 dialog 一致:
176
+ 收起态连接层会给 content 打 hidden,而上面那条 display 正是要盖掉 UA 的
177
+ [hidden]{display:none}——退场动画得先能播。真正的收起由宿主在退场结束后落成内联 display。 */
151
178
 
152
179
  /* 容器只是"没有条目锚点时"的 Tab 兜底落点,落焦不画环:高亮永远长在条目上 */
153
180
  [data-scope='menubar'][data-part='content']:focus-visible {
@@ -157,12 +184,25 @@
157
184
  /* 展开时轻微涨开。只在切换到别张菜单时不重播——那由 data-state 的翻转天然保证:
158
185
  一张关一张开,动画各跑各的 */
159
186
  [data-scope='menubar'][data-part='content'][data-state='open'] {
160
- animation: xh-menubar-in var(--xh-motion-duration-enter) var(--xh-motion-ease-enter);
187
+ animation: xh-pop-in var(--xh-motion-duration-enter) var(--xh-motion-ease-enter);
188
+ }
189
+
190
+ /* 退场:收起那一帧 hidden 由退场闸门押后,这里才播得出来 */
191
+ [data-scope='menubar'][data-part='content'][data-state='closed'] {
192
+ animation: xh-pop-out var(--xh-motion-duration-exit) var(--xh-motion-ease-exit) forwards;
193
+ }
194
+
195
+ /* 在一排入口间换张时两侧都瞬时:交叉淡变读起来就是闪烁,且退场关键帧从不透明度 1
196
+ 起跳,打断未播完的进场还会亮一下。原生菜单栏的成规——首开有进场、末收有退场、
197
+ 换张不播。没有动画时退场闸门当场落定,收起即藏 */
198
+ [data-scope='menubar'][data-part='content'][data-instant] {
199
+ animation: none;
161
200
  }
162
201
 
163
202
  [data-scope='menubar'][data-part='group'] {
164
203
  display: flex;
165
204
  flex-direction: column;
205
+ gap: var(--xh-menubar-group-gap, var(--xh-list-option-gap));
166
206
  }
167
207
 
168
208
  [data-scope='menubar'][data-part='group'][hidden] {
@@ -176,7 +216,7 @@
176
216
  padding-block: var(--xh-menubar-group-label-py, var(--xh-space-1));
177
217
  padding-inline: var(--xh-menubar-group-label-px, var(--xh-_menubar-item-px));
178
218
  color: var(--xh-menubar-group-label-fg, var(--xh-fg-subtle));
179
- font-size: var(--xh-menubar-group-label-font-size, var(--xh-font-size-xs));
219
+ font-size: var(--xh-menubar-group-label-font-size, var(--xh-text-caption-size));
180
220
  font-weight: var(--xh-menubar-group-label-font-weight, var(--xh-font-weight-medium));
181
221
  line-height: var(--xh-leading-none);
182
222
  user-select: none;
@@ -189,7 +229,7 @@
189
229
  [data-scope='menubar'][data-part='item'] {
190
230
  display: flex;
191
231
  align-items: center;
192
- gap: var(--xh-menubar-item-gap, var(--xh-control-gap-md));
232
+ gap: var(--xh-menubar-item-gap, var(--xh-_menubar-item-gap));
193
233
  padding-block: var(--xh-menubar-item-py, var(--xh-_menubar-item-py));
194
234
  padding-inline: var(--xh-menubar-item-px, var(--xh-_menubar-item-px));
195
235
  border-radius: var(--xh-menubar-item-radius, var(--xh-shape-control));
@@ -209,14 +249,44 @@
209
249
  display: none;
210
250
  }
211
251
 
212
- /* 悬停与键盘焦点共用中性灰轻档:条目本身承载焦点,不另画描边。
213
- data-highlighted 跟的是连接层记的焦点条目,与 :focus 说的是同一件事,
214
- 子部件够不着那个伪类,只能读这个标记 */
215
- [data-scope='menubar'][data-part='item']:not([data-disabled]):is(:hover, :focus, [data-highlighted]) {
252
+ /* 悬停与键盘锚点共用中性灰轻档:锚点只认连接层打的 data-highlighted,不读 :focus */
253
+ [data-scope='menubar'][data-part='item']:not([data-disabled]):is(:hover, [data-highlighted]) {
216
254
  background: var(--xh-menubar-item-bg-hover, var(--xh-bg-subtle));
217
255
  }
218
256
 
219
- [data-scope='menubar'][data-part='item']:focus {
257
+ /* 打开子菜单的触发条目是展开路径,走品牌淡底加粗强档。
258
+ 必须排在轻档之后:悬停或焦点回到它身上时同特指度靠书写顺序压过轻档 */
259
+ [data-scope='menubar'][data-part='item']:not([data-disabled])[data-state='open'] {
260
+ background: var(--xh-menubar-item-bg-active, var(--xh-_menubar-item-active-bg));
261
+ font-weight: var(--xh-menubar-item-active-font-weight, var(--xh-font-weight-semibold));
262
+ }
263
+
264
+ /* 带子菜单的条目行尾画右向小箭头:不点开也看得出还有下一级。
265
+ 位置靠 margin 顶到行尾,图形取兜底字形令牌 */
266
+ [data-scope='menubar'][data-part='item'][aria-haspopup='menu']::after {
267
+ content: '';
268
+ flex: none;
269
+ margin-inline-start: auto;
270
+ inline-size: var(--xh-icon-size, var(--xh-glyph-size-text));
271
+ block-size: var(--xh-icon-size, var(--xh-glyph-size-text));
272
+ background-color: currentColor;
273
+ -webkit-mask: var(--xh-glyph-mark-chevron-right) center / contain no-repeat;
274
+ mask: var(--xh-glyph-mark-chevron-right) center / contain no-repeat;
275
+ }
276
+
277
+ /* rtl 下子菜单开在左侧,箭头跟着指向行进方向 */
278
+ [dir='rtl'] [data-scope='menubar'][data-part='item'][aria-haspopup='menu']::after {
279
+ -webkit-mask-image: var(--xh-glyph-mark-chevron-left);
280
+ mask-image: var(--xh-glyph-mark-chevron-left);
281
+ }
282
+
283
+ /* 键盘落焦的条目画内收环;指针触发的聚焦不画 */
284
+ [data-scope='menubar'][data-part='item']:focus-visible {
285
+ outline: var(--xh-ring-width) solid var(--xh-ring-focus);
286
+ outline-offset: calc(-1 * var(--xh-ring-width));
287
+ }
288
+
289
+ [data-scope='menubar'][data-part='item']:focus:not(:focus-visible) {
220
290
  outline: none;
221
291
  }
222
292
 
@@ -244,7 +314,7 @@
244
314
  align-items: center;
245
315
  justify-content: center;
246
316
  inline-size: var(--xh-menubar-item-indicator-size, var(--xh-control-indicator-size));
247
- color: var(--xh-menubar-item-indicator-fg, var(--xh-fg-subtle));
317
+ color: var(--xh-menubar-item-indicator-fg, var(--xh-_tone, var(--xh-fg-brand)));
248
318
  }
249
319
 
250
320
  [data-scope='menubar'][data-part='item-indicator'][hidden] {
@@ -259,14 +329,26 @@
259
329
  不给 display,因此 UA 的 [hidden]{display:none} 自己就压得住 */
260
330
  [data-scope='menubar'][data-part='separator'] {
261
331
  block-size: var(--xh-menubar-separator-thickness, var(--xh-stroke-thin));
262
- margin-block: var(--xh-menubar-separator-my, var(--xh-space-1));
332
+ margin-block: var(--xh-menubar-separator-my, var(--xh-space-0_5));
263
333
  background: var(--xh-menubar-separator-color, var(--xh-border-default));
264
334
  }
335
+
336
+ /* 没写内容就由皮肤画兜底字形;作者往部件里塞了自己的图形,这几条即不命中 */
337
+ [data-scope='menubar'][data-part='item-indicator']:empty::before {
338
+ content: '';
339
+ display: inline-block;
340
+ inline-size: var(--xh-icon-size, var(--xh-glyph-size-text));
341
+ block-size: var(--xh-icon-size, var(--xh-glyph-size-text));
342
+ vertical-align: var(--xh-glyph-baseline-shift);
343
+ background-color: currentColor;
344
+ -webkit-mask: var(--xh-glyph-mark-check) center / contain no-repeat;
345
+ mask: var(--xh-glyph-mark-check) center / contain no-repeat;
346
+ }
265
347
  }
266
348
 
267
349
  @layer xihan.motion {
268
350
  /* 自带前缀独占一个名字,不动公共的那份关键帧 */
269
- @keyframes xh-menubar-in {
351
+ @keyframes xh-pop-in {
270
352
  from {
271
353
  opacity: 0;
272
354
  scale: var(--xh-motion-scale-enter);
@@ -277,4 +359,16 @@
277
359
  scale: 1;
278
360
  }
279
361
  }
362
+
363
+ @keyframes xh-pop-out {
364
+ from {
365
+ opacity: 1;
366
+ scale: 1;
367
+ }
368
+
369
+ to {
370
+ opacity: 0;
371
+ scale: var(--xh-motion-scale-enter);
372
+ }
373
+ }
280
374
  }
@@ -1,14 +1,26 @@
1
1
  @layer xihan.motion {
2
2
  /* 面板往下探一小截再落位:纯淡入看不出它是从哪条 trigger 长出来的 */
3
- @keyframes xh-navigation-menu-in {
3
+ @keyframes xh-pop-in {
4
4
  from {
5
5
  opacity: 0;
6
- translate: 0 calc(-1 * var(--xh-motion-distance-sm));
6
+ scale: var(--xh-motion-scale-enter);
7
7
  }
8
8
 
9
9
  to {
10
10
  opacity: 1;
11
- translate: 0 0;
11
+ scale: 1;
12
+ }
13
+ }
14
+
15
+ @keyframes xh-pop-out {
16
+ from {
17
+ opacity: 1;
18
+ scale: 1;
19
+ }
20
+
21
+ to {
22
+ opacity: 0;
23
+ scale: var(--xh-motion-scale-enter);
12
24
  }
13
25
  }
14
26
  }
@@ -25,18 +37,21 @@
25
37
  /* 尺寸档只换这五个私有槽,trigger 与面板里的链接都从 root 继承它们,
26
38
  换档不必给每个部件各写一条选择器。面板与共享外壳都是 root 的后代,一并继承。
27
39
  trigger 写的是 font: inherit,字号跟着 root 这一档走,不另立槽 */
28
- --xh-_navigation-menu-font-size: var(--xh-text-label-size);
40
+ --xh-_navigation-menu-font-size: var(--xh-control-font-md);
29
41
  --xh-_navigation-menu-trigger-h: var(--xh-control-h-md);
30
42
  --xh-_navigation-menu-trigger-px: var(--xh-control-px-md);
31
43
  --xh-_navigation-menu-trigger-gap: var(--xh-control-gap-md);
32
- --xh-_navigation-menu-link-p: var(--xh-space-2);
33
- --xh-_navigation-menu-link-font-size: var(--xh-text-body-size);
44
+ --xh-_navigation-menu-link-py: var(--xh-space-1_5);
45
+ --xh-_navigation-menu-link-px: var(--xh-control-px-md);
46
+ --xh-_navigation-menu-link-font-size: var(--xh-control-font-md);
47
+
48
+ /* 悬停与键盘锚点恒中性灰轻档、不接语气槽——两档同色相的话打开路径就认不出来了 */
49
+ --xh-_navigation-menu-highlight-bg: var(--xh-bg-subtle);
34
50
 
35
- /* 语气落在三处:条目的高亮底、展开着的 trigger 与当前链接的文字色、指示条。
36
- 没写 data-tone 时这几个 --xh-_tone-* 都没被声明,各自退回原来的取值。
51
+ /* 语气落在三处:展开着的 trigger 的底色、当前链接的文字色、指示条。
52
+ 没写 data-tone 时这几个 --xh-_tone-* 都没被声明,各自退回品牌色。
37
53
  聚焦环不在其列,它恒是 --xh-ring-focus */
38
- --xh-_navigation-menu-highlight-bg: var(--xh-_tone-subtle-hover, var(--xh-bg-subtle-hover));
39
- --xh-_navigation-menu-open-fg: var(--xh-_tone-fg, var(--xh-fg-default));
54
+ --xh-_navigation-menu-active-bg: var(--xh-_tone-subtle, var(--xh-bg-brand-subtle));
40
55
  --xh-_navigation-menu-current-fg: var(--xh-_tone-fg, var(--xh-fg-brand));
41
56
  --xh-_navigation-menu-accent: var(--xh-_tone, var(--xh-fg-brand));
42
57
 
@@ -49,21 +64,23 @@
49
64
  /* 缺省档写在上面的基础规则里。链接的内边距不在控件内边距那把尺上(它比控件矮一档),
50
65
  三档一律取空间尺,缺省档的取值原样保留 */
51
66
  [data-scope='navigation-menu'][data-part='root'][data-size='sm'] {
52
- --xh-_navigation-menu-font-size: var(--xh-font-size-sm);
67
+ --xh-_navigation-menu-font-size: var(--xh-control-font-sm);
53
68
  --xh-_navigation-menu-trigger-h: var(--xh-control-h-sm);
54
69
  --xh-_navigation-menu-trigger-px: var(--xh-control-px-sm);
55
70
  --xh-_navigation-menu-trigger-gap: var(--xh-control-gap-sm);
56
- --xh-_navigation-menu-link-p: var(--xh-space-1_5);
57
- --xh-_navigation-menu-link-font-size: var(--xh-font-size-sm);
71
+ --xh-_navigation-menu-link-py: var(--xh-space-1);
72
+ --xh-_navigation-menu-link-px: var(--xh-control-px-sm);
73
+ --xh-_navigation-menu-link-font-size: var(--xh-control-font-sm);
58
74
  }
59
75
 
60
76
  [data-scope='navigation-menu'][data-part='root'][data-size='lg'] {
61
- --xh-_navigation-menu-font-size: var(--xh-font-size-lg);
77
+ --xh-_navigation-menu-font-size: var(--xh-control-font-lg);
62
78
  --xh-_navigation-menu-trigger-h: var(--xh-control-h-lg);
63
79
  --xh-_navigation-menu-trigger-px: var(--xh-control-px-lg);
64
80
  --xh-_navigation-menu-trigger-gap: var(--xh-control-gap-lg);
65
- --xh-_navigation-menu-link-p: var(--xh-space-3);
66
- --xh-_navigation-menu-link-font-size: var(--xh-font-size-lg);
81
+ --xh-_navigation-menu-link-py: var(--xh-space-2);
82
+ --xh-_navigation-menu-link-px: var(--xh-control-px-lg);
83
+ --xh-_navigation-menu-link-font-size: var(--xh-control-font-lg);
67
84
  }
68
85
 
69
86
  /* 指示条的定位参照系(它是 absolute,量出来的偏移就是相对这里的)。
@@ -114,7 +131,7 @@
114
131
  line-height: var(--xh-leading-none);
115
132
  white-space: nowrap;
116
133
  cursor: pointer;
117
- transition: color var(--xh-motion-duration-micro) var(--xh-motion-ease-enter);
134
+ transition: background var(--xh-motion-duration-micro) var(--xh-motion-ease-enter);
118
135
  }
119
136
 
120
137
  [data-scope='navigation-menu'][data-part='trigger'][hidden] {
@@ -130,8 +147,11 @@
130
147
  outline-offset: var(--xh-ring-offset);
131
148
  }
132
149
 
150
+ /* 展开着的那一张是打开路径,走品牌淡底强档:哪一张开着必须一眼看得出来。
151
+ 不加粗:横排的栏加粗会推挤相邻触发器。
152
+ 必须排在轻档之后:指针回到它身上时同特指度靠书写顺序压过轻档 */
133
153
  [data-scope='navigation-menu'][data-part='trigger'][data-state='open'] {
134
- color: var(--xh-navigation-menu-trigger-fg-open, var(--xh-_navigation-menu-open-fg));
154
+ background: var(--xh-navigation-menu-trigger-bg-active, var(--xh-_navigation-menu-active-bg));
135
155
  }
136
156
 
137
157
  /* 集合条目用 data-disabled,不用 :disabled:它带的是 aria-disabled,
@@ -149,24 +169,24 @@
149
169
  /* 面板贴着自己那一项落位:横排从 trigger 底下长出来 */
150
170
  [data-scope='navigation-menu'][data-part='content'] {
151
171
  position: absolute;
152
- z-index: var(--xh-layer-popover);
172
+ z-index: var(--xh-navigation-menu-layer, var(--xh-layer-popover));
153
173
  inset-block-start: calc(100% + var(--xh-navigation-menu-content-offset, var(--xh-space-1)));
154
174
  inset-inline-start: 0;
155
175
  display: flex;
156
176
  flex-direction: column;
157
177
  gap: var(--xh-navigation-menu-content-gap, var(--xh-space-1));
158
- min-inline-size: var(--xh-navigation-menu-content-min-w, var(--xh-overlay-min-w));
159
- padding: var(--xh-navigation-menu-content-p, var(--xh-space-2));
178
+ min-inline-size: var(--xh-navigation-menu-content-min-w, var(--xh-overlay-menu-min-w));
179
+ padding: var(--xh-navigation-menu-content-p, var(--xh-space-1));
160
180
  border: var(--xh-stroke-thin) solid var(--xh-navigation-menu-content-border, var(--xh-border-default));
161
181
  border-radius: var(--xh-navigation-menu-content-radius, var(--xh-shape-surface));
162
182
  background: var(--xh-navigation-menu-content-bg, var(--xh-bg-surface));
163
- box-shadow: var(--xh-navigation-menu-content-shadow, var(--xh-elevation-2));
183
+ box-shadow: var(--xh-navigation-menu-content-shadow, var(--xh-elevation-floating));
164
184
  }
165
185
 
166
186
  /* display 会盖掉 hidden 属性的 UA 规则,收起态显式让位 */
167
- [data-scope='navigation-menu'][data-part='content'][hidden] {
168
- display: none;
169
- }
187
+ /* 这里刻意没有 [data-part='content'][hidden] { display: none },与 dialog 一致:
188
+ 收起态连接层会给 content 打 hidden,而上面那条 display 正是要盖掉 UA 的
189
+ [hidden]{display:none}——退场动画得先能播。真正的收起由宿主在退场结束后落成内联 display。 */
170
190
 
171
191
  /* 竖排导航:面板改从侧边长出来 */
172
192
  [data-scope='navigation-menu'][data-part='content'][data-orientation='vertical'] {
@@ -175,7 +195,12 @@
175
195
  }
176
196
 
177
197
  [data-scope='navigation-menu'][data-part='content'][data-state='open'] {
178
- animation: xh-navigation-menu-in var(--xh-motion-duration-enter) var(--xh-motion-ease-enter);
198
+ animation: xh-pop-in var(--xh-motion-duration-enter) var(--xh-motion-ease-enter);
199
+ }
200
+
201
+ /* 退场:收起那一帧 hidden 由退场闸门押后,这里才播得出来 */
202
+ [data-scope='navigation-menu'][data-part='content'][data-state='closed'] {
203
+ animation: xh-pop-out var(--xh-motion-duration-exit) var(--xh-motion-ease-exit) forwards;
179
204
  }
180
205
 
181
206
  /* 面板整批塞进共享外壳时,落位归外壳管,面板自己回到静态流里——
@@ -191,8 +216,8 @@
191
216
  [data-scope='navigation-menu'][data-part='link'] {
192
217
  display: flex;
193
218
  align-items: center;
194
- padding-block: var(--xh-navigation-menu-link-py, var(--xh-_navigation-menu-link-p));
195
- padding-inline: var(--xh-navigation-menu-link-px, var(--xh-_navigation-menu-link-p));
219
+ padding-block: var(--xh-navigation-menu-link-py, var(--xh-_navigation-menu-link-py));
220
+ padding-inline: var(--xh-navigation-menu-link-px, var(--xh-_navigation-menu-link-px));
196
221
  border-radius: var(--xh-navigation-menu-link-radius, var(--xh-shape-control));
197
222
  color: var(--xh-navigation-menu-link-fg, var(--xh-fg-default));
198
223
  font-size: var(--xh-navigation-menu-link-font-size, var(--xh-_navigation-menu-link-font-size));
@@ -227,7 +252,7 @@
227
252
  margin: 0;
228
253
  inset-block-end: calc(var(--xh-navigation-menu-indicator-thickness, var(--xh-stroke-thick)) * -1);
229
254
  block-size: var(--xh-navigation-menu-indicator-thickness, var(--xh-stroke-thick));
230
- border-radius: var(--xh-navigation-menu-indicator-radius, var(--xh-radius-full));
255
+ border-radius: var(--xh-navigation-menu-indicator-radius, var(--xh-shape-pill));
231
256
  background: var(--xh-navigation-menu-indicator-color, var(--xh-_navigation-menu-accent));
232
257
  transition:
233
258
  inset-inline-start var(--xh-motion-duration-enter) var(--xh-motion-ease-enter),
@@ -252,7 +277,7 @@
252
277
  /* 共享面板外壳:只管落位与统一的面板外观,里面装哪一份内容归 content */
253
278
  [data-scope='navigation-menu'][data-part='viewport'] {
254
279
  position: absolute;
255
- z-index: var(--xh-layer-popover);
280
+ z-index: var(--xh-navigation-menu-layer, var(--xh-layer-popover));
256
281
  inset-block-start: calc(100% + var(--xh-navigation-menu-content-offset, var(--xh-space-1)));
257
282
  inset-inline-start: 0;
258
283
  display: block;
@@ -260,7 +285,7 @@
260
285
  border: var(--xh-stroke-thin) solid var(--xh-navigation-menu-content-border, var(--xh-border-default));
261
286
  border-radius: var(--xh-navigation-menu-content-radius, var(--xh-shape-surface));
262
287
  background: var(--xh-navigation-menu-content-bg, var(--xh-bg-surface));
263
- box-shadow: var(--xh-navigation-menu-content-shadow, var(--xh-elevation-2));
288
+ box-shadow: var(--xh-navigation-menu-content-shadow, var(--xh-elevation-floating));
264
289
  }
265
290
 
266
291
  [data-scope='navigation-menu'][data-part='viewport'][hidden] {