@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
package/css/menubar.css CHANGED
@@ -1,27 +1,22 @@
1
1
  @layer xihan.components {
2
+ /* 皮肤在场的标记:开发模式下按 scope 探一次,取不到就说明这份皮肤没被引入。 */
3
+ [data-scope='menubar'] {
4
+ --xh-menubar-skin: 1;
5
+ }
6
+
2
7
  /* 一排 trigger。主轴跟着 data-orientation 走:菜单栏本身可以横排也可以竖排 */
3
8
  [data-scope='menubar'][data-part='root'] {
4
- /* 尺寸档只换这五个私有槽,trigger 与菜单里的条目都从 root 继承它们,
5
- 换档不必给每个部件各写一条选择器。菜单浮层在 positioner 里、也是 root 的后代,一并继承 */
6
- --xh-_menubar-trigger-py: var(--xh-space-1);
7
- --xh-_menubar-trigger-px: var(--xh-control-px-sm);
8
- --xh-_menubar-item-py: var(--xh-space-1_5);
9
- --xh-_menubar-item-px: var(--xh-control-px-md);
10
- --xh-_menubar-font-size: var(--xh-text-body-size);
11
-
12
- /* 展开着的那张菜单的 trigger 走品牌淡底强档,随语气换色相;没写 data-tone 时退回品牌淡底。
13
- 悬停与键盘焦点恒中性灰轻档、不接语气槽——两档同色相的话哪张开着就认不出来了。
14
- 聚焦环不在其列,它恒是 --xh-ring-focus */
15
- --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));
16
11
 
17
12
  display: flex;
18
13
  align-items: center;
19
- gap: var(--xh-menubar-gap, var(--xh-space-1));
20
- padding-block: var(--xh-menubar-py, var(--xh-space-1));
21
- padding-inline: var(--xh-menubar-px, var(--xh-space-1));
22
- border-radius: var(--xh-menubar-radius, var(--xh-shape-control));
23
- background: var(--xh-menubar-bg, transparent);
24
- 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));
25
20
  }
26
21
 
27
22
  [data-scope='menubar'][data-part='root'][hidden] {
@@ -33,25 +28,6 @@
33
28
  align-items: stretch;
34
29
  }
35
30
 
36
- /* —— 尺寸 —— */
37
- /* 缺省档写在上面的基础规则里。trigger 的行内内缩缺省落在控件尺 sm 档、再往下取空间尺;
38
- 条目纵向走 space 档、行内内缩走 control-px 档(随密度轴),换档各挪一级 */
39
- [data-scope='menubar'][data-part='root'][data-size='sm'] {
40
- --xh-_menubar-trigger-py: var(--xh-space-0_5);
41
- --xh-_menubar-trigger-px: var(--xh-space-1_5);
42
- --xh-_menubar-item-py: var(--xh-space-1);
43
- --xh-_menubar-item-px: var(--xh-control-px-sm);
44
- --xh-_menubar-font-size: var(--xh-font-size-sm);
45
- }
46
-
47
- [data-scope='menubar'][data-part='root'][data-size='lg'] {
48
- --xh-_menubar-trigger-py: var(--xh-space-2);
49
- --xh-_menubar-trigger-px: var(--xh-control-px-md);
50
- --xh-_menubar-item-py: var(--xh-space-2);
51
- --xh-_menubar-item-px: var(--xh-control-px-lg);
52
- --xh-_menubar-font-size: var(--xh-font-size-lg);
53
- }
54
-
55
31
  /* root 只是 roving tabindex 的兜底落点,焦点转投给 trigger 之后就不再停留,不画环 */
56
32
  [data-scope='menubar'][data-part='root']:focus-visible {
57
33
  outline: none;
@@ -112,8 +88,12 @@
112
88
 
113
89
  /* 坐标由定位引擎写进 style(inset-inline-start / inset-block-start),这里只定位模式与层级 */
114
90
  [data-scope='menubar'][data-part='positioner'] {
91
+ /* 落定那一侧的可用高度,由定位引擎经内联自定义属性写进来,content 继承它限高;
92
+ 引擎没算(尚未落位 / 无引擎)时不额外限高 */
93
+ --xh-_menubar-available-h: 100vh;
94
+
115
95
  position: fixed;
116
- z-index: var(--xh-layer-popover);
96
+ z-index: var(--xh-menubar-layer, var(--xh-layer-popover));
117
97
  /* 空壳不吃指针,交互只发生在 content 上 */
118
98
  pointer-events: none;
119
99
  }
@@ -123,26 +103,71 @@
123
103
  visibility: hidden;
124
104
  }
125
105
 
106
+ /* —— 尺寸 —— */
107
+ /* 尺寸档只换这六个私有槽,换档不必给每个部件各写一条选择器。
108
+ root 与 positioner 各起一头:trigger 从 root 继承,菜单里的条目从 positioner 继承——
109
+ 浮层搬去了 portal 落点,不再是 root 的后代。
110
+ 缺省档写在第一条:trigger 与条目的行内内缩都走 control-px 档(随密度轴)、纵向走 space 档,换档各挪一级 */
111
+ [data-scope='menubar']:is([data-part='root'], [data-part='positioner']) {
112
+ --xh-_menubar-trigger-py: var(--xh-space-1);
113
+ --xh-_menubar-trigger-px: var(--xh-control-px-md);
114
+ --xh-_menubar-item-py: var(--xh-space-1_5);
115
+ --xh-_menubar-item-px: var(--xh-control-px-md);
116
+ --xh-_menubar-item-gap: var(--xh-control-gap-md);
117
+ --xh-_menubar-font-size: var(--xh-text-body-size);
118
+
119
+ /* 展开着的那张菜单的 trigger 走品牌淡底强档,随语气换色相;没写 data-tone 时退回品牌淡底。
120
+ 悬停与键盘焦点恒中性灰轻档、不接语气槽——两档同色相的话哪张开着就认不出来了。
121
+ 聚焦环不在其列,它恒是 --xh-ring-focus */
122
+ --xh-_menubar-active-bg: var(--xh-_tone-subtle, var(--xh-bg-brand-subtle));
123
+
124
+ /* 打开子菜单的触发条目走品牌淡底强档,随语气换色相;没写 data-tone 时退回品牌淡底 */
125
+ --xh-_menubar-item-active-bg: var(--xh-_tone-subtle, var(--xh-bg-brand-subtle));
126
+ }
127
+
128
+ [data-scope='menubar'][data-size='sm']:is([data-part='root'], [data-part='positioner']) {
129
+ --xh-_menubar-trigger-py: var(--xh-space-0_5);
130
+ --xh-_menubar-trigger-px: var(--xh-control-px-sm);
131
+ --xh-_menubar-item-py: var(--xh-space-1);
132
+ --xh-_menubar-item-px: var(--xh-control-px-sm);
133
+ --xh-_menubar-item-gap: var(--xh-control-gap-sm);
134
+ --xh-_menubar-font-size: var(--xh-control-font-sm);
135
+ }
136
+
137
+ [data-scope='menubar'][data-size='lg']:is([data-part='root'], [data-part='positioner']) {
138
+ --xh-_menubar-trigger-py: var(--xh-space-2);
139
+ --xh-_menubar-trigger-px: var(--xh-control-px-lg);
140
+ --xh-_menubar-item-py: var(--xh-space-2);
141
+ --xh-_menubar-item-px: var(--xh-control-px-lg);
142
+ --xh-_menubar-item-gap: var(--xh-control-gap-lg);
143
+ --xh-_menubar-font-size: var(--xh-control-font-lg);
144
+ }
145
+
126
146
  [data-scope='menubar'][data-part='content'] {
127
147
  display: flex;
128
148
  flex-direction: column;
129
- min-inline-size: var(--xh-menubar-menu-min-w, var(--xh-overlay-menu-min-w));
130
- max-inline-size: var(--xh-menubar-menu-max-w, 20rem);
131
- padding-block: var(--xh-menubar-menu-py, var(--xh-space-1));
132
- padding-inline: var(--xh-menubar-menu-px, var(--xh-space-1));
133
- border: var(--xh-stroke-thin) solid var(--xh-menubar-menu-border, var(--xh-border-default));
134
- border-radius: var(--xh-menubar-menu-radius, var(--xh-shape-surface));
135
- background: var(--xh-menubar-menu-bg, var(--xh-bg-surface));
136
- color: var(--xh-menubar-menu-fg, var(--xh-fg-default));
137
- box-shadow: var(--xh-menubar-menu-shadow, var(--xh-elevation-2));
149
+ min-inline-size: var(--xh-menubar-min-w, var(--xh-overlay-menu-min-w));
150
+ max-inline-size: var(--xh-menubar-max-w, var(--xh-overlay-max-w));
151
+ /* 两道上限取更小的那道:自己的高度上限,以及落定那一侧真正剩下的空间。
152
+ 列表族的 16rem 对命令菜单偏矮,这里另给一档 */
153
+ max-block-size: min(var(--xh-menubar-max-h, var(--xh-overlay-menu-max-h)), var(--xh-_menubar-available-h));
154
+ padding-block: var(--xh-menubar-py, var(--xh-space-1));
155
+ padding-inline: var(--xh-menubar-px, var(--xh-space-1));
156
+ border: var(--xh-stroke-thin) solid var(--xh-menubar-border, var(--xh-border-default));
157
+ border-radius: var(--xh-menubar-radius, var(--xh-shape-surface));
158
+ background: var(--xh-menubar-bg, var(--xh-bg-surface));
159
+ color: var(--xh-menubar-fg, var(--xh-fg-default));
160
+ box-shadow: var(--xh-menubar-shadow, var(--xh-elevation-floating));
161
+ /* 条目超过上限就在菜单内部滚。条目的焦点环是内收的,滚动容器裁在内边距缘上,环切不着 */
162
+ overflow-y: auto;
138
163
  pointer-events: auto;
139
164
  }
140
165
 
141
166
  /* display 会盖掉 hidden 属性的 UA 规则,收起态显式让位。
142
167
  连接层给 content 发 hidden,这一条漏了整张菜单就永远收不起来 */
143
- [data-scope='menubar'][data-part='content'][hidden] {
144
- display: none;
145
- }
168
+ /* 这里刻意没有 [data-part='content'][hidden] { display: none },与 dialog 一致:
169
+ 收起态连接层会给 content 打 hidden,而上面那条 display 正是要盖掉 UA 的
170
+ [hidden]{display:none}——退场动画得先能播。真正的收起由宿主在退场结束后落成内联 display。 */
146
171
 
147
172
  /* 容器只是"没有条目锚点时"的 Tab 兜底落点,落焦不画环:高亮永远长在条目上 */
148
173
  [data-scope='menubar'][data-part='content']:focus-visible {
@@ -152,14 +177,19 @@
152
177
  /* 展开时轻微涨开。只在切换到别张菜单时不重播——那由 data-state 的翻转天然保证:
153
178
  一张关一张开,动画各跑各的 */
154
179
  [data-scope='menubar'][data-part='content'][data-state='open'] {
155
- animation: xh-menubar-in var(--xh-motion-duration-enter) var(--xh-motion-ease-enter);
180
+ animation: xh-pop-in var(--xh-motion-duration-enter) var(--xh-motion-ease-enter);
156
181
  }
157
182
 
158
- /* 关掉动效的用户不该被涨开动画晃一下;这里只管本组件,公共那份不动 */
159
- @media (prefers-reduced-motion: reduce) {
160
- [data-scope='menubar'][data-part='content'][data-state='open'] {
161
- animation-duration: 0.01ms;
162
- }
183
+ /* 退场:收起那一帧 hidden 由退场闸门押后,这里才播得出来 */
184
+ [data-scope='menubar'][data-part='content'][data-state='closed'] {
185
+ animation: xh-pop-out var(--xh-motion-duration-exit) var(--xh-motion-ease-exit) forwards;
186
+ }
187
+
188
+ /* 在一排入口间换张时两侧都瞬时:交叉淡变读起来就是闪烁,且退场关键帧从不透明度 1
189
+ 起跳,打断未播完的进场还会亮一下。原生菜单栏的成规——首开有进场、末收有退场、
190
+ 换张不播。没有动画时退场闸门当场落定,收起即藏 */
191
+ [data-scope='menubar'][data-part='content'][data-instant] {
192
+ animation: none;
163
193
  }
164
194
 
165
195
  [data-scope='menubar'][data-part='group'] {
@@ -178,7 +208,7 @@
178
208
  padding-block: var(--xh-menubar-group-label-py, var(--xh-space-1));
179
209
  padding-inline: var(--xh-menubar-group-label-px, var(--xh-_menubar-item-px));
180
210
  color: var(--xh-menubar-group-label-fg, var(--xh-fg-subtle));
181
- font-size: var(--xh-menubar-group-label-font-size, var(--xh-font-size-xs));
211
+ font-size: var(--xh-menubar-group-label-font-size, var(--xh-text-caption-size));
182
212
  font-weight: var(--xh-menubar-group-label-font-weight, var(--xh-font-weight-medium));
183
213
  line-height: var(--xh-leading-none);
184
214
  user-select: none;
@@ -191,7 +221,7 @@
191
221
  [data-scope='menubar'][data-part='item'] {
192
222
  display: flex;
193
223
  align-items: center;
194
- gap: var(--xh-menubar-item-gap, var(--xh-control-gap-md));
224
+ gap: var(--xh-menubar-item-gap, var(--xh-_menubar-item-gap));
195
225
  padding-block: var(--xh-menubar-item-py, var(--xh-_menubar-item-py));
196
226
  padding-inline: var(--xh-menubar-item-px, var(--xh-_menubar-item-px));
197
227
  border-radius: var(--xh-menubar-item-radius, var(--xh-shape-control));
@@ -211,14 +241,44 @@
211
241
  display: none;
212
242
  }
213
243
 
214
- /* 悬停与键盘焦点共用中性灰轻档:条目本身承载焦点,不另画描边。
215
- data-highlighted 跟的是连接层记的焦点条目,与 :focus 说的是同一件事,
216
- 子部件够不着那个伪类,只能读这个标记 */
217
- [data-scope='menubar'][data-part='item']:not([data-disabled]):is(:hover, :focus, [data-highlighted]) {
244
+ /* 悬停与键盘锚点共用中性灰轻档:锚点只认连接层打的 data-highlighted,不读 :focus */
245
+ [data-scope='menubar'][data-part='item']:not([data-disabled]):is(:hover, [data-highlighted]) {
218
246
  background: var(--xh-menubar-item-bg-hover, var(--xh-bg-subtle));
219
247
  }
220
248
 
221
- [data-scope='menubar'][data-part='item']:focus {
249
+ /* 打开子菜单的触发条目是展开路径,走品牌淡底加粗强档。
250
+ 必须排在轻档之后:悬停或焦点回到它身上时同特指度靠书写顺序压过轻档 */
251
+ [data-scope='menubar'][data-part='item']:not([data-disabled])[data-state='open'] {
252
+ background: var(--xh-menubar-item-bg-active, var(--xh-_menubar-item-active-bg));
253
+ font-weight: var(--xh-menubar-item-active-font-weight, var(--xh-font-weight-semibold));
254
+ }
255
+
256
+ /* 带子菜单的条目行尾画右向小箭头:不点开也看得出还有下一级。
257
+ 位置靠 margin 顶到行尾,图形取兜底字形令牌 */
258
+ [data-scope='menubar'][data-part='item'][aria-haspopup='menu']::after {
259
+ content: '';
260
+ flex: none;
261
+ margin-inline-start: auto;
262
+ inline-size: var(--xh-icon-size, var(--xh-glyph-size-text));
263
+ block-size: var(--xh-icon-size, var(--xh-glyph-size-text));
264
+ background-color: currentColor;
265
+ -webkit-mask: var(--xh-glyph-mark-chevron-right) center / contain no-repeat;
266
+ mask: var(--xh-glyph-mark-chevron-right) center / contain no-repeat;
267
+ }
268
+
269
+ /* rtl 下子菜单开在左侧,箭头跟着指向行进方向 */
270
+ [dir='rtl'] [data-scope='menubar'][data-part='item'][aria-haspopup='menu']::after {
271
+ -webkit-mask-image: var(--xh-glyph-mark-chevron-left);
272
+ mask-image: var(--xh-glyph-mark-chevron-left);
273
+ }
274
+
275
+ /* 键盘落焦的条目画内收环;指针触发的聚焦不画 */
276
+ [data-scope='menubar'][data-part='item']:focus-visible {
277
+ outline: var(--xh-ring-width) solid var(--xh-ring-focus);
278
+ outline-offset: calc(-1 * var(--xh-ring-width));
279
+ }
280
+
281
+ [data-scope='menubar'][data-part='item']:focus:not(:focus-visible) {
222
282
  outline: none;
223
283
  }
224
284
 
@@ -246,7 +306,7 @@
246
306
  align-items: center;
247
307
  justify-content: center;
248
308
  inline-size: var(--xh-menubar-item-indicator-size, var(--xh-control-indicator-size));
249
- color: var(--xh-menubar-item-indicator-fg, var(--xh-fg-subtle));
309
+ color: var(--xh-menubar-item-indicator-fg, var(--xh-fg-brand));
250
310
  }
251
311
 
252
312
  [data-scope='menubar'][data-part='item-indicator'][hidden] {
@@ -264,14 +324,26 @@
264
324
  margin-block: var(--xh-menubar-separator-my, var(--xh-space-1));
265
325
  background: var(--xh-menubar-separator-color, var(--xh-border-default));
266
326
  }
327
+
328
+ /* 没写内容就由皮肤画兜底字形;作者往部件里塞了自己的图形,这几条即不命中 */
329
+ [data-scope='menubar'][data-part='item-indicator']:empty::before {
330
+ content: '';
331
+ display: inline-block;
332
+ inline-size: var(--xh-icon-size, var(--xh-glyph-size-text));
333
+ block-size: var(--xh-icon-size, var(--xh-glyph-size-text));
334
+ vertical-align: var(--xh-glyph-baseline-shift);
335
+ background-color: currentColor;
336
+ -webkit-mask: var(--xh-glyph-mark-check) center / contain no-repeat;
337
+ mask: var(--xh-glyph-mark-check) center / contain no-repeat;
338
+ }
267
339
  }
268
340
 
269
341
  @layer xihan.motion {
270
342
  /* 自带前缀独占一个名字,不动公共的那份关键帧 */
271
- @keyframes xh-menubar-in {
343
+ @keyframes xh-pop-in {
272
344
  from {
273
345
  opacity: 0;
274
- scale: 0.96;
346
+ scale: var(--xh-motion-scale-enter);
275
347
  }
276
348
 
277
349
  to {
@@ -279,4 +351,16 @@
279
351
  scale: 1;
280
352
  }
281
353
  }
354
+
355
+ @keyframes xh-pop-out {
356
+ from {
357
+ opacity: 1;
358
+ scale: 1;
359
+ }
360
+
361
+ to {
362
+ opacity: 0;
363
+ scale: var(--xh-motion-scale-enter);
364
+ }
365
+ }
282
366
  }
@@ -1,19 +1,36 @@
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 -4px;
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
  }
15
27
 
16
28
  @layer xihan.components {
29
+ /* 皮肤在场的标记:开发模式下按 scope 探一次,取不到就说明这份皮肤没被引入。 */
30
+ [data-scope='navigation-menu'] {
31
+ --xh-navigation-menu-skin: 1;
32
+ }
33
+
17
34
  /* 根节点是 nav 地标,不参与排版;给 relative 是为了让共享外壳(viewport)有个定位参照系。
18
35
  这里不给 display,UA 的 [hidden]{display:none} 就仍然压得住 */
19
36
  [data-scope='navigation-menu'][data-part='root'] {
@@ -24,14 +41,17 @@
24
41
  --xh-_navigation-menu-trigger-h: var(--xh-control-h-md);
25
42
  --xh-_navigation-menu-trigger-px: var(--xh-control-px-md);
26
43
  --xh-_navigation-menu-trigger-gap: var(--xh-control-gap-md);
27
- --xh-_navigation-menu-link-p: var(--xh-space-2);
44
+ --xh-_navigation-menu-link-py: var(--xh-space-1_5);
45
+ --xh-_navigation-menu-link-px: var(--xh-control-px-md);
28
46
  --xh-_navigation-menu-link-font-size: var(--xh-text-body-size);
29
47
 
30
- /* 语气落在三处:条目的高亮底、展开着的 trigger 与当前链接的文字色、指示条。
31
- 没写 data-tone 时这几个 --xh-_tone-* 都没被声明,各自退回原来的取值。
48
+ /* 悬停与键盘锚点恒中性灰轻档、不接语气槽——两档同色相的话打开路径就认不出来了 */
49
+ --xh-_navigation-menu-highlight-bg: var(--xh-bg-subtle);
50
+
51
+ /* 语气落在三处:展开着的 trigger 的底色、当前链接的文字色、指示条。
52
+ 没写 data-tone 时这几个 --xh-_tone-* 都没被声明,各自退回品牌色。
32
53
  聚焦环不在其列,它恒是 --xh-ring-focus */
33
- --xh-_navigation-menu-highlight-bg: var(--xh-_tone-subtle-hover, var(--xh-bg-subtle-hover));
34
- --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));
35
55
  --xh-_navigation-menu-current-fg: var(--xh-_tone-fg, var(--xh-fg-brand));
36
56
  --xh-_navigation-menu-accent: var(--xh-_tone, var(--xh-fg-brand));
37
57
 
@@ -44,21 +64,23 @@
44
64
  /* 缺省档写在上面的基础规则里。链接的内边距不在控件内边距那把尺上(它比控件矮一档),
45
65
  三档一律取空间尺,缺省档的取值原样保留 */
46
66
  [data-scope='navigation-menu'][data-part='root'][data-size='sm'] {
47
- --xh-_navigation-menu-font-size: var(--xh-font-size-sm);
67
+ --xh-_navigation-menu-font-size: var(--xh-control-font-sm);
48
68
  --xh-_navigation-menu-trigger-h: var(--xh-control-h-sm);
49
69
  --xh-_navigation-menu-trigger-px: var(--xh-control-px-sm);
50
70
  --xh-_navigation-menu-trigger-gap: var(--xh-control-gap-sm);
51
- --xh-_navigation-menu-link-p: var(--xh-space-1_5);
52
- --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);
53
74
  }
54
75
 
55
76
  [data-scope='navigation-menu'][data-part='root'][data-size='lg'] {
56
- --xh-_navigation-menu-font-size: var(--xh-font-size-lg);
77
+ --xh-_navigation-menu-font-size: var(--xh-control-font-lg);
57
78
  --xh-_navigation-menu-trigger-h: var(--xh-control-h-lg);
58
79
  --xh-_navigation-menu-trigger-px: var(--xh-control-px-lg);
59
80
  --xh-_navigation-menu-trigger-gap: var(--xh-control-gap-lg);
60
- --xh-_navigation-menu-link-p: var(--xh-space-3);
61
- --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);
62
84
  }
63
85
 
64
86
  /* 指示条的定位参照系(它是 absolute,量出来的偏移就是相对这里的)。
@@ -109,7 +131,7 @@
109
131
  line-height: var(--xh-leading-none);
110
132
  white-space: nowrap;
111
133
  cursor: pointer;
112
- 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);
113
135
  }
114
136
 
115
137
  [data-scope='navigation-menu'][data-part='trigger'][hidden] {
@@ -125,8 +147,11 @@
125
147
  outline-offset: var(--xh-ring-offset);
126
148
  }
127
149
 
150
+ /* 展开着的那一张是打开路径,走品牌淡底强档:哪一张开着必须一眼看得出来。
151
+ 不加粗:横排的栏加粗会推挤相邻触发器。
152
+ 必须排在轻档之后:指针回到它身上时同特指度靠书写顺序压过轻档 */
128
153
  [data-scope='navigation-menu'][data-part='trigger'][data-state='open'] {
129
- 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));
130
155
  }
131
156
 
132
157
  /* 集合条目用 data-disabled,不用 :disabled:它带的是 aria-disabled,
@@ -144,24 +169,24 @@
144
169
  /* 面板贴着自己那一项落位:横排从 trigger 底下长出来 */
145
170
  [data-scope='navigation-menu'][data-part='content'] {
146
171
  position: absolute;
147
- z-index: var(--xh-layer-popover);
172
+ z-index: var(--xh-navigation-menu-layer, var(--xh-layer-popover));
148
173
  inset-block-start: calc(100% + var(--xh-navigation-menu-content-offset, var(--xh-space-1)));
149
174
  inset-inline-start: 0;
150
175
  display: flex;
151
176
  flex-direction: column;
152
177
  gap: var(--xh-navigation-menu-content-gap, var(--xh-space-1));
153
- min-inline-size: var(--xh-navigation-menu-content-min-w, var(--xh-overlay-min-w));
154
- 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));
155
180
  border: var(--xh-stroke-thin) solid var(--xh-navigation-menu-content-border, var(--xh-border-default));
156
181
  border-radius: var(--xh-navigation-menu-content-radius, var(--xh-shape-surface));
157
182
  background: var(--xh-navigation-menu-content-bg, var(--xh-bg-surface));
158
- 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));
159
184
  }
160
185
 
161
186
  /* display 会盖掉 hidden 属性的 UA 规则,收起态显式让位 */
162
- [data-scope='navigation-menu'][data-part='content'][hidden] {
163
- display: none;
164
- }
187
+ /* 这里刻意没有 [data-part='content'][hidden] { display: none },与 dialog 一致:
188
+ 收起态连接层会给 content 打 hidden,而上面那条 display 正是要盖掉 UA 的
189
+ [hidden]{display:none}——退场动画得先能播。真正的收起由宿主在退场结束后落成内联 display。 */
165
190
 
166
191
  /* 竖排导航:面板改从侧边长出来 */
167
192
  [data-scope='navigation-menu'][data-part='content'][data-orientation='vertical'] {
@@ -170,7 +195,12 @@
170
195
  }
171
196
 
172
197
  [data-scope='navigation-menu'][data-part='content'][data-state='open'] {
173
- 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;
174
204
  }
175
205
 
176
206
  /* 面板整批塞进共享外壳时,落位归外壳管,面板自己回到静态流里——
@@ -186,8 +216,8 @@
186
216
  [data-scope='navigation-menu'][data-part='link'] {
187
217
  display: flex;
188
218
  align-items: center;
189
- padding-block: var(--xh-navigation-menu-link-py, var(--xh-_navigation-menu-link-p));
190
- 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));
191
221
  border-radius: var(--xh-navigation-menu-link-radius, var(--xh-shape-control));
192
222
  color: var(--xh-navigation-menu-link-fg, var(--xh-fg-default));
193
223
  font-size: var(--xh-navigation-menu-link-font-size, var(--xh-_navigation-menu-link-font-size));
@@ -222,7 +252,7 @@
222
252
  margin: 0;
223
253
  inset-block-end: calc(var(--xh-navigation-menu-indicator-thickness, var(--xh-stroke-thick)) * -1);
224
254
  block-size: var(--xh-navigation-menu-indicator-thickness, var(--xh-stroke-thick));
225
- 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));
226
256
  background: var(--xh-navigation-menu-indicator-color, var(--xh-_navigation-menu-accent));
227
257
  transition:
228
258
  inset-inline-start var(--xh-motion-duration-enter) var(--xh-motion-ease-enter),
@@ -247,7 +277,7 @@
247
277
  /* 共享面板外壳:只管落位与统一的面板外观,里面装哪一份内容归 content */
248
278
  [data-scope='navigation-menu'][data-part='viewport'] {
249
279
  position: absolute;
250
- z-index: var(--xh-layer-popover);
280
+ z-index: var(--xh-navigation-menu-layer, var(--xh-layer-popover));
251
281
  inset-block-start: calc(100% + var(--xh-navigation-menu-content-offset, var(--xh-space-1)));
252
282
  inset-inline-start: 0;
253
283
  display: block;
@@ -255,7 +285,7 @@
255
285
  border: var(--xh-stroke-thin) solid var(--xh-navigation-menu-content-border, var(--xh-border-default));
256
286
  border-radius: var(--xh-navigation-menu-content-radius, var(--xh-shape-surface));
257
287
  background: var(--xh-navigation-menu-content-bg, var(--xh-bg-surface));
258
- 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));
259
289
  }
260
290
 
261
291
  [data-scope='navigation-menu'][data-part='viewport'][hidden] {
@@ -1,4 +1,9 @@
1
1
  @layer xihan.components {
2
+ /* 皮肤在场的标记:开发模式下按 scope 探一次,取不到就说明这份皮肤没被引入。 */
3
+ [data-scope='number-animation'] {
4
+ --xh-number-animation-skin: 1;
5
+ }
6
+
2
7
  [data-scope='number-animation'][data-part='root'] {
3
8
  /* 不写尺寸就跟着上下文的字号走:这个数常常摆在别人的标题、卡片标题或统计数值槽里,
4
9
  自带一个字号只会跟摆放它的地方打架。三个档位各自换掉这个私有槽 */
@@ -19,14 +24,14 @@
19
24
 
20
25
  /* —— 尺寸 —— */
21
26
  [data-scope='number-animation'][data-part='root'][data-size='sm'] {
22
- --xh-_number-animation-size: var(--xh-font-size-lg);
27
+ --xh-_number-animation-size: var(--xh-control-font-lg);
23
28
  }
24
29
 
25
30
  [data-scope='number-animation'][data-part='root'][data-size='md'] {
26
- --xh-_number-animation-size: var(--xh-font-size-2xl);
31
+ --xh-_number-animation-size: var(--xh-text-heading-2-size);
27
32
  }
28
33
 
29
34
  [data-scope='number-animation'][data-part='root'][data-size='lg'] {
30
- --xh-_number-animation-size: var(--xh-font-size-3xl);
35
+ --xh-_number-animation-size: var(--xh-text-heading-1-size);
31
36
  }
32
37
  }