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

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 (58) hide show
  1. package/CHANGELOG.md +261 -0
  2. package/css/back-top.css +2 -2
  3. package/css/button-group.css +1 -1
  4. package/css/button.css +1 -1
  5. package/css/calendar.css +1 -1
  6. package/css/carousel.css +2 -2
  7. package/css/cascader.css +199 -24
  8. package/css/checkbox-group.css +20 -20
  9. package/css/checkbox.css +1 -1
  10. package/css/clipboard.css +3 -3
  11. package/css/color-picker.css +21 -5
  12. package/css/combobox.css +23 -20
  13. package/css/composer.css +1 -1
  14. package/css/context-menu.css +56 -26
  15. package/css/date-field.css +5 -5
  16. package/css/date-picker.css +66 -2
  17. package/css/drawer.css +3 -3
  18. package/css/dynamic-input.css +2 -2
  19. package/css/editable.css +6 -6
  20. package/css/field.css +32 -1
  21. package/css/file-upload.css +3 -3
  22. package/css/float-button.css +2 -2
  23. package/css/form.css +17 -5
  24. package/css/hover-card.css +15 -11
  25. package/css/image-viewer.css +176 -0
  26. package/css/listbox.css +9 -6
  27. package/css/mention.css +14 -22
  28. package/css/menu.css +38 -23
  29. package/css/menubar.css +28 -17
  30. package/css/number-field.css +16 -16
  31. package/css/pin-input.css +6 -6
  32. package/css/popconfirm.css +23 -0
  33. package/css/popover.css +15 -11
  34. package/css/popselect.css +31 -16
  35. package/css/progress.css +68 -1
  36. package/css/radio-group.css +1 -1
  37. package/css/select.css +148 -17
  38. package/css/side-nav.css +163 -0
  39. package/css/slider.css +55 -0
  40. package/css/steps.css +2 -2
  41. package/css/switch.css +27 -0
  42. package/css/table.css +6 -6
  43. package/css/tags-input.css +7 -7
  44. package/css/text-field.css +23 -10
  45. package/css/thread.css +1 -1
  46. package/css/time-field.css +5 -5
  47. package/css/time-picker.css +36 -26
  48. package/css/toggle-group.css +1 -1
  49. package/css/toggle.css +1 -1
  50. package/css/tone.css +22 -0
  51. package/css/tooltip.css +20 -15
  52. package/css/tour.css +16 -12
  53. package/css/transfer.css +11 -9
  54. package/css/tree-select.css +26 -18
  55. package/css/tree.css +8 -5
  56. package/index.css +6 -2
  57. package/index.unlayered.css +1499 -413
  58. package/package.json +4 -2
@@ -0,0 +1,176 @@
1
+ @layer xihan.components {
2
+ [data-scope='image-viewer'][data-part='backdrop'] {
3
+ position: fixed;
4
+ inset: 0;
5
+ z-index: var(--xh-layer-modal);
6
+ /* 看片要压住页面底色,遮罩比普通对话框更深 */
7
+ background: var(--xh-image-viewer-backdrop-bg, color-mix(in oklab, var(--xh-color-neutral-950) 78%, transparent));
8
+ }
9
+
10
+ [data-scope='image-viewer'][data-part='backdrop'][data-state='open'] {
11
+ animation: xh-fade-in var(--xh-motion-duration-enter) var(--xh-motion-ease-enter);
12
+ }
13
+
14
+ [data-scope='image-viewer'][data-part='backdrop'][data-state='closed'] {
15
+ animation: xh-fade-out var(--xh-motion-duration-exit) var(--xh-motion-ease-exit);
16
+ }
17
+
18
+ [data-scope='image-viewer'][data-part='positioner'] {
19
+ position: fixed;
20
+ inset: 0;
21
+ z-index: var(--xh-layer-modal);
22
+ display: flex;
23
+ align-items: center;
24
+ justify-content: center;
25
+ }
26
+
27
+ [data-scope='image-viewer'][data-part='content'] {
28
+ position: relative;
29
+ inline-size: 100%;
30
+ block-size: 100%;
31
+ display: flex;
32
+ align-items: center;
33
+ justify-content: center;
34
+ outline: none;
35
+ /* 深色底上的工具条与计数固定用浅字,不随主题翻 */
36
+ color: var(--xh-image-viewer-fg, var(--xh-color-neutral-0));
37
+ }
38
+
39
+ [data-scope='image-viewer'][data-part='content'][data-state='open'] {
40
+ animation: xh-fade-in var(--xh-motion-duration-enter) var(--xh-motion-ease-enter);
41
+ }
42
+
43
+ [data-scope='image-viewer'][data-part='content'][data-state='closed'] {
44
+ animation: xh-fade-out var(--xh-motion-duration-exit) var(--xh-motion-ease-exit);
45
+ }
46
+
47
+ [data-scope='image-viewer'][data-part='content'][hidden] {
48
+ display: none;
49
+ }
50
+
51
+ [data-scope='image-viewer'][data-part='viewport'] {
52
+ position: absolute;
53
+ inset: 0;
54
+ display: flex;
55
+ align-items: center;
56
+ justify-content: center;
57
+ overflow: hidden;
58
+ cursor: grab;
59
+ /* 平移与滚轮都归指针会话,浏览器手势不抢 */
60
+ touch-action: none;
61
+ }
62
+
63
+ [data-scope='image-viewer'][data-part='viewport'][data-panning] {
64
+ cursor: grabbing;
65
+ }
66
+
67
+ [data-scope='image-viewer'][data-part='image'] {
68
+ max-inline-size: 90%;
69
+ max-block-size: 85%;
70
+ user-select: none;
71
+ /* 变换是内联 style 写的,只给缩放旋转一点缓动;拖拽平移要跟手,不缓 */
72
+ transition: transform var(--xh-duration-fast) var(--xh-ease-out);
73
+ }
74
+
75
+ [data-scope='image-viewer'][data-part='image'][data-panning] {
76
+ transition: none;
77
+ }
78
+
79
+ /* —— 悬浮件共用:半透明深底加浅字 —— */
80
+ [data-scope='image-viewer'][data-part='toolbar'],
81
+ [data-scope='image-viewer'][data-part='counter'],
82
+ [data-scope='image-viewer'][data-part='prev-trigger'],
83
+ [data-scope='image-viewer'][data-part='next-trigger'],
84
+ [data-scope='image-viewer'][data-part='close-trigger'] {
85
+ position: absolute;
86
+ z-index: 1;
87
+ background: var(--xh-image-viewer-chrome-bg, color-mix(in oklab, var(--xh-color-neutral-950) 55%, transparent));
88
+ color: inherit;
89
+ border: none;
90
+ border-radius: var(--xh-shape-pill);
91
+ }
92
+
93
+ [data-scope='image-viewer'][data-part='toolbar'] {
94
+ inset-block-end: var(--xh-space-6);
95
+ inset-inline-start: 50%;
96
+ translate: -50% 0;
97
+ display: flex;
98
+ align-items: center;
99
+ gap: var(--xh-space-1);
100
+ padding: var(--xh-space-1_5) var(--xh-space-3);
101
+ }
102
+
103
+ /* 工具条里的按钮:底色交给工具条,本体只管命中区 */
104
+ [data-scope='image-viewer'][data-part='toolbar'] > [data-part] {
105
+ position: static;
106
+ display: inline-flex;
107
+ align-items: center;
108
+ justify-content: center;
109
+ inline-size: var(--xh-control-action-size);
110
+ block-size: var(--xh-control-action-size);
111
+ background: none;
112
+ border: none;
113
+ border-radius: var(--xh-shape-control);
114
+ color: inherit;
115
+ font-size: var(--xh-glyph-size-sm);
116
+ cursor: pointer;
117
+ }
118
+
119
+ [data-scope='image-viewer'][data-part='counter'] {
120
+ inset-block-start: var(--xh-space-6);
121
+ inset-inline-start: 50%;
122
+ translate: -50% 0;
123
+ padding: var(--xh-space-1) var(--xh-space-3);
124
+ font-size: var(--xh-font-size-sm);
125
+ }
126
+
127
+ [data-scope='image-viewer'][data-part='prev-trigger'],
128
+ [data-scope='image-viewer'][data-part='next-trigger'],
129
+ [data-scope='image-viewer'][data-part='close-trigger'] {
130
+ display: inline-flex;
131
+ align-items: center;
132
+ justify-content: center;
133
+ inline-size: var(--xh-control-h-lg);
134
+ block-size: var(--xh-control-h-lg);
135
+ font-size: var(--xh-glyph-size-md);
136
+ cursor: pointer;
137
+ }
138
+
139
+ [data-scope='image-viewer'][data-part='prev-trigger'] {
140
+ inset-inline-start: var(--xh-space-6);
141
+ inset-block-start: 50%;
142
+ translate: 0 -50%;
143
+ }
144
+
145
+ [data-scope='image-viewer'][data-part='next-trigger'] {
146
+ inset-inline-end: var(--xh-space-6);
147
+ inset-block-start: 50%;
148
+ translate: 0 -50%;
149
+ }
150
+
151
+ [data-scope='image-viewer'][data-part='close-trigger'] {
152
+ inset-block-start: var(--xh-space-6);
153
+ inset-inline-end: var(--xh-space-6);
154
+ }
155
+
156
+ [data-scope='image-viewer'] button[data-part]:focus-visible {
157
+ outline: var(--xh-ring-width) solid var(--xh-ring-focus);
158
+ outline-offset: var(--xh-ring-offset);
159
+ }
160
+
161
+ [data-scope='image-viewer'] button[data-part]:disabled {
162
+ opacity: var(--xh-state-disabled-opacity);
163
+ cursor: not-allowed;
164
+ }
165
+
166
+ @media (prefers-reduced-motion: reduce) {
167
+ [data-scope='image-viewer'][data-part='backdrop'],
168
+ [data-scope='image-viewer'][data-part='content'] {
169
+ animation-duration: 0.01ms;
170
+ }
171
+
172
+ [data-scope='image-viewer'][data-part='image'] {
173
+ transition: none;
174
+ }
175
+ }
176
+ }
package/css/listbox.css CHANGED
@@ -74,7 +74,7 @@
74
74
  [data-scope='listbox'][data-part='item-group-label'] {
75
75
  display: block;
76
76
  padding-block: var(--xh-listbox-group-label-py, var(--xh-space-1));
77
- padding-inline: var(--xh-listbox-group-label-px, var(--xh-control-px-sm));
77
+ padding-inline: var(--xh-listbox-group-label-px, var(--xh-control-px-md));
78
78
  color: var(--xh-listbox-group-label-fg, var(--xh-fg-subtle));
79
79
  font-size: var(--xh-listbox-group-label-font-size, var(--xh-font-size-xs));
80
80
  font-weight: var(--xh-listbox-group-label-font-weight, var(--xh-font-weight-medium));
@@ -94,8 +94,8 @@
94
94
  display: flex;
95
95
  align-items: center;
96
96
  gap: var(--xh-listbox-item-gap, var(--xh-control-gap-md));
97
- padding-block: var(--xh-listbox-item-py, var(--xh-space-1));
98
- padding-inline: var(--xh-listbox-item-px, var(--xh-control-px-sm));
97
+ padding-block: var(--xh-listbox-item-py, var(--xh-space-1_5));
98
+ padding-inline: var(--xh-listbox-item-px, var(--xh-control-px-md));
99
99
  border-radius: var(--xh-listbox-item-radius, var(--xh-shape-control));
100
100
  color: var(--xh-listbox-item-fg, var(--xh-fg-default));
101
101
  font-size: var(--xh-listbox-item-font-size, var(--xh-text-body-size));
@@ -104,6 +104,9 @@
104
104
  white-space: nowrap;
105
105
  cursor: pointer;
106
106
  user-select: none;
107
+ transition:
108
+ background var(--xh-motion-duration-micro) var(--xh-motion-ease-enter),
109
+ color var(--xh-motion-duration-micro) var(--xh-motion-ease-enter);
107
110
  }
108
111
 
109
112
  /* 条目可以按需收起(过滤掉的选项),有 display 就得补这条 */
@@ -111,10 +114,10 @@
111
114
  display: none;
112
115
  }
113
116
 
114
- /* 键盘高亮与指针高亮共用一套底色:条目本身承载焦点,不另画描边。
115
- data-highlighted 跟的是连接层记的焦点条目,与选中互相独立 */
117
+ /* 悬停与键盘锚点共用中性灰轻档:data-highlighted 跟的是连接层记的焦点条目,
118
+ 与选中互相独立 */
116
119
  [data-scope='listbox'][data-part='item']:not([data-disabled]):is(:hover, [data-highlighted]) {
117
- background: var(--xh-listbox-item-bg-highlight, var(--xh-bg-subtle-hover));
120
+ background: var(--xh-listbox-item-bg-hover, var(--xh-bg-subtle));
118
121
  }
119
122
 
120
123
  /* 选中只换文字色与字重,配合行尾的 ✓ 标记;底色整条通道留给高亮,
package/css/mention.css CHANGED
@@ -9,14 +9,11 @@
9
9
 
10
10
  /* 形态档只换这三个槽:缺省即 outline(描边 + 画布底) */
11
11
  --xh-_mention-input-bg: var(--xh-bg-canvas);
12
- --xh-_mention-input-border: var(--xh-border-default);
13
- --xh-_mention-input-border-hover: var(--xh-border-strong);
12
+ --xh-_mention-input-border: var(--xh-border-control);
13
+ --xh-_mention-input-border-hover: var(--xh-border-control-hover);
14
14
 
15
- /* 强调色随语气走,只落在聚焦与高亮上,正文文字色不动。
16
- 没写 data-tone 时 --xh-_tone 没被声明,三处都退回原来的取值 */
15
+ /* 聚焦环恒用固定环色,不随语气走 */
17
16
  --xh-_mention-ring: var(--xh-ring-focus);
18
- --xh-_mention-item-highlight-bg: var(--xh-_tone-subtle-hover, var(--xh-bg-subtle-hover));
19
- --xh-_mention-item-highlight-fg: var(--xh-_tone-fg, var(--xh-fg-brand-strong));
20
17
 
21
18
  display: block;
22
19
  }
@@ -47,21 +44,21 @@
47
44
  形态只决定描边与底色怎么用,用哪族颜色由 data-tone 决定 */
48
45
  [data-scope='mention'][data-part='root'][data-variant='outline'] {
49
46
  --xh-_mention-input-bg: var(--xh-bg-canvas);
50
- --xh-_mention-input-border: var(--xh-border-default);
51
- --xh-_mention-input-border-hover: var(--xh-border-strong);
47
+ --xh-_mention-input-border: var(--xh-border-control);
48
+ --xh-_mention-input-border-hover: var(--xh-border-control-hover);
52
49
  }
53
50
 
54
51
  /* 填充式:底色顶替描边,悬停时才浮出一道淡边 */
55
52
  [data-scope='mention'][data-part='root'][data-variant='subtle'] {
56
53
  --xh-_mention-input-bg: var(--xh-_tone-subtle, var(--xh-bg-subtle));
57
54
  --xh-_mention-input-border: transparent;
58
- --xh-_mention-input-border-hover: var(--xh-_tone-border, var(--xh-border-default));
55
+ --xh-_mention-input-border-hover: var(--xh-_tone-border, var(--xh-border-control-hover));
59
56
  }
60
57
 
61
58
  [data-scope='mention'][data-part='root'][data-variant='ghost'] {
62
59
  --xh-_mention-input-bg: transparent;
63
60
  --xh-_mention-input-border: transparent;
64
- --xh-_mention-input-border-hover: var(--xh-_tone-border, var(--xh-border-default));
61
+ --xh-_mention-input-border-hover: var(--xh-_tone-border, var(--xh-border-control-hover));
65
62
  }
66
63
 
67
64
  /* 框与聚焦环都长在输入框自己身上:这里没有把输入框和别的控件裹成一体的输入行,
@@ -166,8 +163,8 @@
166
163
  display: flex;
167
164
  align-items: center;
168
165
  gap: var(--xh-mention-item-gap, var(--xh-_mention-gap));
169
- padding-block: var(--xh-mention-item-py, var(--xh-space-1));
170
- padding-inline: var(--xh-mention-item-px, var(--xh-control-px-sm));
166
+ padding-block: var(--xh-mention-item-py, var(--xh-space-1_5));
167
+ padding-inline: var(--xh-mention-item-px, var(--xh-control-px-md));
171
168
  border-radius: var(--xh-mention-item-radius, var(--xh-shape-control));
172
169
  color: var(--xh-mention-item-fg, var(--xh-fg-default));
173
170
  font-size: var(--xh-mention-item-font-size, var(--xh-_mention-font-size));
@@ -176,18 +173,19 @@
176
173
  white-space: nowrap;
177
174
  cursor: pointer;
178
175
  user-select: none;
176
+ transition:
177
+ background var(--xh-motion-duration-micro) var(--xh-motion-ease-enter),
178
+ color var(--xh-motion-duration-micro) var(--xh-motion-ease-enter);
179
179
  }
180
180
 
181
181
  [data-scope='mention'][data-part='item'][hidden] {
182
182
  display: none;
183
183
  }
184
184
 
185
- /* 只认 data-highlighted,不写 :hover:指针划过时连接层已经把高亮搬过来了,
185
+ /* 键盘锚点走中性灰轻档。只认 data-highlighted,不写 :hover:指针划过时连接层已经把高亮搬过来了,
186
186
  两套底色各画各的会出现"鼠标停在 A 上、回车却插进了 B" */
187
187
  [data-scope='mention'][data-part='item'][data-highlighted]:not([data-disabled]) {
188
- background: var(--xh-mention-item-bg-highlight, var(--xh-_mention-item-highlight-bg));
189
- color: var(--xh-mention-item-fg-highlight, var(--xh-_mention-item-highlight-fg));
190
- font-weight: var(--xh-mention-item-font-weight-highlight, var(--xh-font-weight-medium));
188
+ background: var(--xh-mention-item-bg-hover, var(--xh-bg-subtle));
191
189
  }
192
190
 
193
191
  /* 禁用走 aria-disabled 而非原生 disabled(原生 disabled 不派 click,禁用守卫就走不到),
@@ -210,12 +208,6 @@
210
208
  display: none;
211
209
  }
212
210
 
213
- /* 候选行里除文本以外的部分(作者摆的头像、副标题)由作者自己画;
214
- 这里只把强调色透出去,作者要用就取它 */
215
- [data-scope='mention'][data-part='item'][data-highlighted] [data-part='item-text'] {
216
- color: var(--xh-mention-item-fg-highlight, var(--xh-_mention-item-highlight-fg));
217
- }
218
-
219
211
  [data-scope='mention'][data-part='item'][data-disabled] [data-part='item-text'] {
220
212
  color: var(--xh-fg-disabled);
221
213
  }
package/css/menu.css CHANGED
@@ -15,13 +15,14 @@
15
15
  [data-scope='menu'][data-part='content'] {
16
16
  /* 尺寸档只换这四个私有槽,条目从 content 继承它们,换档不必给每个部件各写一条选择器。
17
17
  菜单没有 root 部件(浮层树的最外层就是 content),三轴属性都落在这里 */
18
- --xh-_menu-item-py: var(--xh-space-2);
19
- --xh-_menu-item-px: var(--xh-control-px-sm);
18
+ --xh-_menu-item-py: var(--xh-space-1_5);
19
+ --xh-_menu-item-px: var(--xh-control-px-md);
20
20
  --xh-_menu-item-gap: var(--xh-control-gap-md);
21
21
  --xh-_menu-font-size: var(--xh-text-body-size);
22
22
 
23
- /* 条目高亮底随语气走。没写 data-tone 时 --xh-_tone-subtle-hover 没被声明,退回原来的取值 */
24
- --xh-_menu-item-highlight-bg: var(--xh-_tone-subtle-hover, var(--xh-bg-subtle-hover));
23
+ /* 打开子菜单的触发条目走品牌淡底强档,随语气换色相;没写 data-tone 时退回品牌淡底。
24
+ 悬停与键盘焦点恒中性灰轻档、不接语气槽——两档同色相的话打开路径就认不出来了 */
25
+ --xh-_menu-item-active-bg: var(--xh-_tone-subtle, var(--xh-bg-brand-subtle));
25
26
 
26
27
  display: flex;
27
28
  flex-direction: column;
@@ -52,18 +53,18 @@
52
53
  }
53
54
 
54
55
  /* —— 尺寸 —— */
55
- /* 缺省档写在 content 的基础规则里。条目内外边距缺省档本就不在 control-h/px 那把尺上
56
- (高度由 padding 撑出来、行内内缩取的是 sm 档),故按 space 档上下各挪一级 */
56
+ /* 缺省档写在 content 的基础规则里。条目高度由 padding 撑出来:
57
+ 纵向走 space 档、行内内缩走 control-px 档(随密度轴),换档各挪一级 */
57
58
  [data-scope='menu'][data-part='content'][data-size='sm'] {
58
59
  --xh-_menu-item-py: var(--xh-space-1);
59
- --xh-_menu-item-px: var(--xh-space-1);
60
+ --xh-_menu-item-px: var(--xh-control-px-sm);
60
61
  --xh-_menu-item-gap: var(--xh-control-gap-sm);
61
62
  --xh-_menu-font-size: var(--xh-font-size-sm);
62
63
  }
63
64
 
64
65
  [data-scope='menu'][data-part='content'][data-size='lg'] {
65
- --xh-_menu-item-py: var(--xh-space-3);
66
- --xh-_menu-item-px: var(--xh-space-3);
66
+ --xh-_menu-item-py: var(--xh-space-2);
67
+ --xh-_menu-item-px: var(--xh-control-px-lg);
67
68
  --xh-_menu-item-gap: var(--xh-control-gap-lg);
68
69
  --xh-_menu-font-size: var(--xh-font-size-lg);
69
70
  }
@@ -77,15 +78,25 @@
77
78
  border-radius: var(--xh-menu-item-radius, var(--xh-shape-control));
78
79
  color: var(--xh-menu-item-fg, var(--xh-fg-default));
79
80
  font-size: var(--xh-menu-item-font-size, var(--xh-_menu-font-size));
80
- line-height: var(--xh-leading-none);
81
+ line-height: var(--xh-menu-item-leading, var(--xh-leading-normal));
81
82
  white-space: nowrap;
82
83
  cursor: pointer;
83
84
  user-select: none;
85
+ transition:
86
+ background var(--xh-motion-duration-micro) var(--xh-motion-ease-enter),
87
+ color var(--xh-motion-duration-micro) var(--xh-motion-ease-enter);
84
88
  }
85
89
 
86
- /* 键盘高亮与指针高亮共用一套底色:条目本身承载焦点,不另画描边 */
90
+ /* 悬停与键盘焦点共用中性灰轻档:条目本身承载焦点,不另画描边 */
87
91
  [data-scope='menu'][data-part='item']:not([data-disabled]):is(:hover, :focus) {
88
- background: var(--xh-menu-item-bg-highlight, var(--xh-_menu-item-highlight-bg));
92
+ background: var(--xh-menu-item-bg-hover, var(--xh-bg-subtle));
93
+ }
94
+
95
+ /* 打开子菜单的触发条目是展开路径,走品牌淡底加粗强档。
96
+ 必须排在轻档之后:悬停或焦点回到它身上时同特指度靠书写顺序压过轻档 */
97
+ [data-scope='menu'][data-part='item']:not([data-disabled])[data-state='open'] {
98
+ background: var(--xh-menu-item-bg-active, var(--xh-_menu-item-active-bg));
99
+ font-weight: var(--xh-menu-item-active-font-weight, var(--xh-font-weight-semibold));
89
100
  }
90
101
 
91
102
  [data-scope='menu'][data-part='item']:focus {
@@ -104,40 +115,44 @@
104
115
  }
105
116
 
106
117
  /* 箭头是旋转 45° 的方块,只保留朝向锚点那两条边的描边;
107
- 引擎不产出箭头偏移,因此沿交叉轴固定居中 */
118
+ 交叉轴落点由定位引擎经内联自定义属性写进来,没给时退回居中 */
108
119
  [data-scope='menu'][data-part='arrow'] {
120
+ --xh-_menu-arrow-size: var(--xh-menu-arrow-size, var(--xh-overlay-arrow-size));
121
+ --xh-_menu-arrow-x: 50%;
122
+ --xh-_menu-arrow-y: 50%;
123
+
109
124
  position: absolute;
110
- inline-size: var(--xh-menu-arrow-size, var(--xh-overlay-arrow-size));
111
- block-size: var(--xh-menu-arrow-size, var(--xh-overlay-arrow-size));
125
+ inline-size: var(--xh-_menu-arrow-size);
126
+ block-size: var(--xh-_menu-arrow-size);
112
127
  background: var(--xh-menu-bg, var(--xh-bg-surface));
113
128
  border: var(--xh-stroke-thin) solid var(--xh-menu-border, var(--xh-border-default));
114
129
  rotate: 45deg;
115
130
  }
116
131
 
117
132
  [data-scope='menu'][data-part='arrow'][data-placement^='bottom'] {
118
- inset-block-start: calc(var(--xh-menu-arrow-size, var(--xh-overlay-arrow-size)) / -2);
119
- inset-inline-start: calc(50% - var(--xh-menu-arrow-size, var(--xh-overlay-arrow-size)) / 2);
133
+ inset-block-start: calc(var(--xh-_menu-arrow-size) / -2);
134
+ inset-inline-start: calc(var(--xh-_menu-arrow-x) - var(--xh-_menu-arrow-size) / 2);
120
135
  border-block-end: 0;
121
136
  border-inline-end: 0;
122
137
  }
123
138
 
124
139
  [data-scope='menu'][data-part='arrow'][data-placement^='top'] {
125
- inset-block-end: calc(var(--xh-menu-arrow-size, var(--xh-overlay-arrow-size)) / -2);
126
- inset-inline-start: calc(50% - var(--xh-menu-arrow-size, var(--xh-overlay-arrow-size)) / 2);
140
+ inset-block-end: calc(var(--xh-_menu-arrow-size) / -2);
141
+ inset-inline-start: calc(var(--xh-_menu-arrow-x) - var(--xh-_menu-arrow-size) / 2);
127
142
  border-block-start: 0;
128
143
  border-inline-start: 0;
129
144
  }
130
145
 
131
146
  [data-scope='menu'][data-part='arrow'][data-placement^='right'] {
132
- inset-inline-start: calc(var(--xh-menu-arrow-size, var(--xh-overlay-arrow-size)) / -2);
133
- inset-block-start: calc(50% - var(--xh-menu-arrow-size, var(--xh-overlay-arrow-size)) / 2);
147
+ inset-inline-start: calc(var(--xh-_menu-arrow-size) / -2);
148
+ inset-block-start: calc(var(--xh-_menu-arrow-y) - var(--xh-_menu-arrow-size) / 2);
134
149
  border-block-start: 0;
135
150
  border-inline-end: 0;
136
151
  }
137
152
 
138
153
  [data-scope='menu'][data-part='arrow'][data-placement^='left'] {
139
- inset-inline-end: calc(var(--xh-menu-arrow-size, var(--xh-overlay-arrow-size)) / -2);
140
- inset-block-start: calc(50% - var(--xh-menu-arrow-size, var(--xh-overlay-arrow-size)) / 2);
154
+ inset-inline-end: calc(var(--xh-_menu-arrow-size) / -2);
155
+ inset-block-start: calc(var(--xh-_menu-arrow-y) - var(--xh-_menu-arrow-size) / 2);
141
156
  border-block-end: 0;
142
157
  border-inline-start: 0;
143
158
  }
package/css/menubar.css CHANGED
@@ -5,14 +5,14 @@
5
5
  换档不必给每个部件各写一条选择器。菜单浮层在 positioner 里、也是 root 的后代,一并继承 */
6
6
  --xh-_menubar-trigger-py: var(--xh-space-1);
7
7
  --xh-_menubar-trigger-px: var(--xh-control-px-sm);
8
- --xh-_menubar-item-py: var(--xh-space-2);
9
- --xh-_menubar-item-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
10
  --xh-_menubar-font-size: var(--xh-text-body-size);
11
11
 
12
- /* 高亮底随语气走:展开着的那张菜单的 trigger 与菜单里的高亮条目共用这一档。
13
- 没写 data-tone 时 --xh-_tone-subtle-hover 没被声明,退回原来的中性底。
12
+ /* 展开着的那张菜单的 trigger 走品牌淡底强档,随语气换色相;没写 data-tone 时退回品牌淡底。
13
+ 悬停与键盘焦点恒中性灰轻档、不接语气槽——两档同色相的话哪张开着就认不出来了。
14
14
  聚焦环不在其列,它恒是 --xh-ring-focus */
15
- --xh-_menubar-highlight-bg: var(--xh-_tone-subtle-hover, var(--xh-bg-subtle-hover));
15
+ --xh-_menubar-active-bg: var(--xh-_tone-subtle, var(--xh-bg-brand-subtle));
16
16
 
17
17
  display: flex;
18
18
  align-items: center;
@@ -34,21 +34,21 @@
34
34
  }
35
35
 
36
36
  /* —— 尺寸 —— */
37
- /* 缺省档写在上面的基础规则里。内边距的缺省档已经落在控件内边距尺的 sm 那一格,
38
- 往下没有更小的一格,sm 档改取空间尺;lg 档回到控件尺的下一格 */
37
+ /* 缺省档写在上面的基础规则里。trigger 的行内内缩缺省落在控件尺 sm 档、再往下取空间尺;
38
+ 条目纵向走 space 档、行内内缩走 control-px 档(随密度轴),换档各挪一级 */
39
39
  [data-scope='menubar'][data-part='root'][data-size='sm'] {
40
40
  --xh-_menubar-trigger-py: var(--xh-space-0_5);
41
41
  --xh-_menubar-trigger-px: var(--xh-space-1_5);
42
- --xh-_menubar-item-py: var(--xh-space-1_5);
43
- --xh-_menubar-item-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
44
  --xh-_menubar-font-size: var(--xh-font-size-sm);
45
45
  }
46
46
 
47
47
  [data-scope='menubar'][data-part='root'][data-size='lg'] {
48
48
  --xh-_menubar-trigger-py: var(--xh-space-2);
49
49
  --xh-_menubar-trigger-px: var(--xh-control-px-md);
50
- --xh-_menubar-item-py: var(--xh-space-3);
51
- --xh-_menubar-item-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
52
  --xh-_menubar-font-size: var(--xh-font-size-lg);
53
53
  }
54
54
 
@@ -78,15 +78,23 @@
78
78
  white-space: nowrap;
79
79
  cursor: pointer;
80
80
  user-select: none;
81
+ transition: background var(--xh-motion-duration-micro) var(--xh-motion-ease-enter);
81
82
  }
82
83
 
83
84
  [data-scope='menubar'][data-part='trigger'][hidden] {
84
85
  display: none;
85
86
  }
86
87
 
87
- /* 展开着的那一项与指针悬停共用一套底色:菜单栏里"哪一张开着"必须一眼看得出来 */
88
- [data-scope='menubar'][data-part='trigger']:not([data-disabled]):is(:hover, [data-state='open']) {
89
- background: var(--xh-menubar-trigger-bg-active, var(--xh-_menubar-highlight-bg));
88
+ /* 指针悬停走中性灰轻档 */
89
+ [data-scope='menubar'][data-part='trigger']:not([data-disabled]):hover {
90
+ background: var(--xh-menubar-trigger-bg-hover, var(--xh-bg-subtle));
91
+ }
92
+
93
+ /* 展开着的那一张是打开路径,走品牌淡底强档:菜单栏里"哪一张开着"必须一眼看得出来。
94
+ 不加粗:横排的栏加粗会推挤相邻触发器。
95
+ 必须排在轻档之后:指针回到它身上时同特指度靠书写顺序压过轻档 */
96
+ [data-scope='menubar'][data-part='trigger']:not([data-disabled])[data-state='open'] {
97
+ background: var(--xh-menubar-trigger-bg-active, var(--xh-_menubar-active-bg));
90
98
  }
91
99
 
92
100
  /* trigger 自带 Tab 位(整条菜单栏唯一的那个),必须画得出焦点 */
@@ -189,10 +197,13 @@
189
197
  border-radius: var(--xh-menubar-item-radius, var(--xh-shape-control));
190
198
  color: var(--xh-menubar-item-fg, var(--xh-fg-default));
191
199
  font-size: var(--xh-menubar-item-font-size, var(--xh-_menubar-font-size));
192
- line-height: var(--xh-leading-none);
200
+ line-height: var(--xh-menubar-item-leading, var(--xh-leading-normal));
193
201
  white-space: nowrap;
194
202
  cursor: pointer;
195
203
  user-select: none;
204
+ transition:
205
+ background var(--xh-motion-duration-micro) var(--xh-motion-ease-enter),
206
+ color var(--xh-motion-duration-micro) var(--xh-motion-ease-enter);
196
207
  }
197
208
 
198
209
  /* 条目可以按需收起(按上下文过滤掉的命令),有 display 就得补这条 */
@@ -200,11 +211,11 @@
200
211
  display: none;
201
212
  }
202
213
 
203
- /* 键盘高亮与指针高亮共用一套底色:条目本身承载焦点,不另画描边。
214
+ /* 悬停与键盘焦点共用中性灰轻档:条目本身承载焦点,不另画描边。
204
215
  data-highlighted 跟的是连接层记的焦点条目,与 :focus 说的是同一件事,
205
216
  子部件够不着那个伪类,只能读这个标记 */
206
217
  [data-scope='menubar'][data-part='item']:not([data-disabled]):is(:hover, :focus, [data-highlighted]) {
207
- background: var(--xh-menubar-item-bg-highlight, var(--xh-_menubar-highlight-bg));
218
+ background: var(--xh-menubar-item-bg-hover, var(--xh-bg-subtle));
208
219
  }
209
220
 
210
221
  [data-scope='menubar'][data-part='item']:focus {
@@ -12,18 +12,18 @@
12
12
 
13
13
  /* 形态档只换这几个私有槽:输入框的底与描边,加减钮的底与描边 */
14
14
  --xh-_number-field-bg: var(--xh-bg-canvas);
15
- --xh-_number-field-border: var(--xh-border-default);
16
- --xh-_number-field-border-hover: var(--xh-border-strong);
15
+ --xh-_number-field-border: var(--xh-border-control);
16
+ --xh-_number-field-border-hover: var(--xh-border-control-hover);
17
17
  --xh-_number-field-trigger-bg: var(--xh-bg-subtle);
18
18
  --xh-_number-field-trigger-bg-hover: var(--xh-bg-subtle-hover);
19
19
  --xh-_number-field-trigger-bg-active: var(--xh-bg-subtle-active);
20
- --xh-_number-field-trigger-border: var(--xh-border-default);
21
- --xh-_number-field-trigger-border-hover: var(--xh-border-strong);
20
+ --xh-_number-field-trigger-border: var(--xh-border-control);
21
+ --xh-_number-field-trigger-border-hover: var(--xh-border-control-hover);
22
22
 
23
23
  /* 语气只落在聚焦这一处:环与聚焦态描边。框里的数字不归它管。
24
24
  没写 data-tone 时 --xh-_tone 没被声明,退回原来的聚焦环色与常态描边 */
25
25
  --xh-_number-field-ring: var(--xh-ring-focus);
26
- --xh-_number-field-border-focus: var(--xh-number-field-input-border, var(--xh-_tone, var(--xh-border-default)));
26
+ --xh-_number-field-border-focus: var(--xh-number-field-input-border, var(--xh-_tone, var(--xh-border-control)));
27
27
 
28
28
  display: inline-flex;
29
29
  flex-direction: column;
@@ -58,14 +58,14 @@
58
58
  输入框没有实心档:填满一个要往里打字的框,字与底就没法同时读 */
59
59
  [data-scope='number-field'][data-part='root'][data-variant='outline'] {
60
60
  --xh-_number-field-bg: var(--xh-bg-canvas);
61
- --xh-_number-field-border: var(--xh-border-default);
62
- --xh-_number-field-border-hover: var(--xh-border-strong);
61
+ --xh-_number-field-border: var(--xh-border-control);
62
+ --xh-_number-field-border-hover: var(--xh-border-control-hover);
63
63
  --xh-_number-field-trigger-bg: var(--xh-bg-subtle);
64
64
  --xh-_number-field-trigger-bg-hover: var(--xh-bg-subtle-hover);
65
65
  --xh-_number-field-trigger-bg-active: var(--xh-bg-subtle-active);
66
- --xh-_number-field-trigger-border: var(--xh-border-default);
67
- --xh-_number-field-trigger-border-hover: var(--xh-border-strong);
68
- --xh-_number-field-border-focus: var(--xh-number-field-input-border, var(--xh-_tone, var(--xh-border-default)));
66
+ --xh-_number-field-trigger-border: var(--xh-border-control);
67
+ --xh-_number-field-trigger-border-hover: var(--xh-border-control-hover);
68
+ --xh-_number-field-border-focus: var(--xh-number-field-input-border, var(--xh-_tone, var(--xh-border-control)));
69
69
  }
70
70
 
71
71
  /* 填充式:底色顶替描边表达边界。描边只退成透明而不去掉,1px 的位置留着,
@@ -73,26 +73,26 @@
73
73
  [data-scope='number-field'][data-part='root'][data-variant='subtle'] {
74
74
  --xh-_number-field-bg: var(--xh-_tone-subtle, var(--xh-bg-subtle));
75
75
  --xh-_number-field-border: transparent;
76
- --xh-_number-field-border-hover: var(--xh-_tone-border, var(--xh-border-default));
76
+ --xh-_number-field-border-hover: var(--xh-_tone-border, var(--xh-border-control-hover));
77
77
  --xh-_number-field-trigger-bg: var(--xh-_tone-subtle, var(--xh-bg-subtle));
78
78
  --xh-_number-field-trigger-bg-hover: var(--xh-_tone-subtle-hover, var(--xh-bg-subtle-hover));
79
79
  --xh-_number-field-trigger-bg-active: var(--xh-_tone-subtle-active, var(--xh-bg-subtle-active));
80
80
  --xh-_number-field-trigger-border: transparent;
81
- --xh-_number-field-trigger-border-hover: var(--xh-_tone-border, var(--xh-border-default));
82
- --xh-_number-field-border-focus: var(--xh-_tone, var(--xh-border-default));
81
+ --xh-_number-field-trigger-border-hover: var(--xh-_tone-border, var(--xh-border-control-hover));
82
+ --xh-_number-field-border-focus: var(--xh-_tone, var(--xh-border-control));
83
83
  }
84
84
 
85
85
  /* 无框:底与描边都透明,平时只看得见数字,悬停与聚焦才浮出边界 */
86
86
  [data-scope='number-field'][data-part='root'][data-variant='ghost'] {
87
87
  --xh-_number-field-bg: transparent;
88
88
  --xh-_number-field-border: transparent;
89
- --xh-_number-field-border-hover: var(--xh-_tone-border, var(--xh-border-default));
89
+ --xh-_number-field-border-hover: var(--xh-_tone-border, var(--xh-border-control-hover));
90
90
  --xh-_number-field-trigger-bg: transparent;
91
91
  --xh-_number-field-trigger-bg-hover: var(--xh-_tone-subtle, var(--xh-bg-subtle-hover));
92
92
  --xh-_number-field-trigger-bg-active: var(--xh-_tone-subtle-active, var(--xh-bg-subtle-active));
93
93
  --xh-_number-field-trigger-border: transparent;
94
- --xh-_number-field-trigger-border-hover: var(--xh-_tone-border, var(--xh-border-default));
95
- --xh-_number-field-border-focus: var(--xh-_tone, var(--xh-border-default));
94
+ --xh-_number-field-trigger-border-hover: var(--xh-_tone-border, var(--xh-border-control-hover));
95
+ --xh-_number-field-border-focus: var(--xh-_tone, var(--xh-border-control));
96
96
  }
97
97
 
98
98
  [data-scope='number-field'][data-part='label'] {
package/css/pin-input.css CHANGED
@@ -8,8 +8,8 @@
8
8
  --xh-_pin-input-label-font-size: var(--xh-text-label-size);
9
9
  /* 形态档只换这三个私有槽,缺省这一份就是描边式(描边 + 画布底) */
10
10
  --xh-_pin-input-box-bg: var(--xh-bg-canvas);
11
- --xh-_pin-input-box-border: var(--xh-border-default);
12
- --xh-_pin-input-box-border-hover: var(--xh-border-strong);
11
+ --xh-_pin-input-box-border: var(--xh-border-control);
12
+ --xh-_pin-input-box-border-hover: var(--xh-border-control-hover);
13
13
  /* 聚焦环与填满态的强调色随语气走。没写 data-tone 时 --xh-_tone 没被声明,退回原来的取值 */
14
14
  --xh-_pin-input-ring: var(--xh-ring-focus);
15
15
  --xh-_pin-input-accent: var(--xh-_tone, var(--xh-bg-brand));
@@ -29,22 +29,22 @@
29
29
  不做 solid:实心填充盖住了"这里能打字"这件事,输入框用不上它 */
30
30
  [data-scope='pin-input'][data-part='root'][data-variant='outline'] {
31
31
  --xh-_pin-input-box-bg: var(--xh-bg-canvas);
32
- --xh-_pin-input-box-border: var(--xh-border-default);
33
- --xh-_pin-input-box-border-hover: var(--xh-border-strong);
32
+ --xh-_pin-input-box-border: var(--xh-border-control);
33
+ --xh-_pin-input-box-border-hover: var(--xh-border-control-hover);
34
34
  }
35
35
 
36
36
  /* 填充式:底色说明这里是一格输入位,描边让位给底色 */
37
37
  [data-scope='pin-input'][data-part='root'][data-variant='subtle'] {
38
38
  --xh-_pin-input-box-bg: var(--xh-_tone-subtle, var(--xh-bg-subtle));
39
39
  --xh-_pin-input-box-border: transparent;
40
- --xh-_pin-input-box-border-hover: var(--xh-_tone-border, var(--xh-border-default));
40
+ --xh-_pin-input-box-border-hover: var(--xh-_tone-border, var(--xh-border-control-hover));
41
41
  }
42
42
 
43
43
  /* 无边框、透明底:静息时格子完全隐入背景,可见反馈全靠悬停描边与聚焦环 */
44
44
  [data-scope='pin-input'][data-part='root'][data-variant='ghost'] {
45
45
  --xh-_pin-input-box-bg: transparent;
46
46
  --xh-_pin-input-box-border: transparent;
47
- --xh-_pin-input-box-border-hover: var(--xh-_tone-border, var(--xh-border-default));
47
+ --xh-_pin-input-box-border-hover: var(--xh-_tone-border, var(--xh-border-control-hover));
48
48
  }
49
49
 
50
50
  /* —— 尺寸 —— */