@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
package/css/toolbar.css CHANGED
@@ -1,3 +1,13 @@
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
+ /* 定义 toolbar 样式。 */
7
+
8
+ /* 独立皮肤传递引入条目的动作控件配方,full bundle 递归去重。 */
9
+ @import '../family/action-control.css';
10
+
1
11
  @layer xihan.components {
2
12
  /* 皮肤在场的标记:开发模式下按 scope 探一次,取不到就说明这份皮肤没被引入。 */
3
13
  [data-scope='toolbar'] {
@@ -7,19 +17,35 @@
7
17
  /* 一条控件带:条目之间留固定间距,分隔线再把它们切成语义上的几段。
8
18
  排布只能读 data-orientation——它与 aria-orientation 同源,但样式不该去读 ARIA */
9
19
  [data-scope='toolbar'][data-part='root'] {
10
- /* 尺寸档只换这两个私有槽:条目之间的间距,与整条的内边距 */
11
- --xh-_toolbar-gap: var(--xh-space-1);
20
+ /* 尺寸档同时约束工具条排布与默认条目。 */
21
+ --xh-_toolbar-gap: var(--xh-space-2);
12
22
  --xh-_toolbar-p: var(--xh-space-1);
23
+ --xh-_toolbar-item-h: var(--xh-control-h-md);
24
+ --xh-_toolbar-separator-size: calc(var(--xh-_toolbar-item-h) / 2);
25
+ --xh-icon-size: var(--xh-toolbar-icon-size, var(--xh-glyph-size-md));
26
+
27
+ /* 缺省 ghost:工具条只组织控件,不额外画外框;条目按画布承载走 hover 100 → pressed 200。 */
28
+ --xh-_toolbar-root-p: 0;
29
+ --xh-_toolbar-root-border-width: 0;
30
+ --xh-_toolbar-root-border: transparent;
31
+ --xh-_toolbar-root-bg: transparent;
32
+ --xh-_toolbar-root-bg-disabled: transparent;
13
33
 
34
+ /* 一行排不下就折行:条目宽度由各自的控件决定,硬撑一行会把整条顶出容器 */
14
35
  display: flex;
36
+ flex-wrap: wrap;
15
37
  align-items: center;
16
38
  gap: var(--xh-toolbar-gap, var(--xh-_toolbar-gap));
17
- padding-block: var(--xh-toolbar-py, var(--xh-_toolbar-p));
18
- padding-inline: var(--xh-toolbar-px, var(--xh-_toolbar-p));
19
- border: var(--xh-stroke-thin) solid var(--xh-toolbar-border, var(--xh-border-default));
39
+ padding-block: var(--xh-toolbar-py, var(--xh-_toolbar-root-p));
40
+ padding-inline: var(--xh-toolbar-px, var(--xh-_toolbar-root-p));
41
+ border: var(--xh-_toolbar-root-border-width) solid var(--xh-toolbar-border, var(--xh-_toolbar-root-border));
20
42
  border-radius: var(--xh-toolbar-radius, var(--xh-shape-surface));
21
- background: var(--xh-toolbar-bg, var(--xh-bg-surface));
43
+ background: var(--xh-toolbar-bg, var(--xh-_toolbar-root-bg));
22
44
  color: var(--xh-toolbar-fg, var(--xh-fg-default));
45
+ /* 整条置灰与恢复是一次状态切换,底色与字色淡着换,不硬切 */
46
+ transition:
47
+ background var(--xh-motion-duration-micro) var(--xh-motion-ease-enter),
48
+ color var(--xh-motion-duration-micro) var(--xh-motion-ease-enter);
23
49
  }
24
50
 
25
51
  [data-scope='toolbar'][data-part='root'][data-orientation='horizontal'] {
@@ -30,6 +56,38 @@
30
56
  [data-scope='toolbar'][data-part='root'][data-orientation='vertical'] {
31
57
  flex-direction: column;
32
58
  align-items: stretch;
59
+ flex-wrap: nowrap;
60
+ }
61
+
62
+ /* —— 变体 —— */
63
+ [data-scope='toolbar'][data-part='root'][data-variant='ghost'] {
64
+ --xh-_toolbar-root-p: 0;
65
+ --xh-_toolbar-root-border-width: 0;
66
+ --xh-_toolbar-root-border: transparent;
67
+ --xh-_toolbar-root-bg: transparent;
68
+ --xh-_toolbar-root-bg-disabled: transparent;
69
+ }
70
+
71
+ /* 淡底档:带内距、换成 subtle 底,描边让位给底色但留住 1px 边位(与 outline 几何一致),无影;
72
+ 淡底承载面向条目下发 hover 200 → pressed 300(§7.2) */
73
+ [data-scope='toolbar'][data-part='root'][data-variant='subtle'] {
74
+ --xh-_toolbar-root-p: var(--xh-_toolbar-p);
75
+ --xh-_toolbar-root-border-width: var(--xh-stroke-thin);
76
+ --xh-_toolbar-root-bg: var(--xh-bg-subtle);
77
+ --xh-action-host-bg-hover: var(--xh-bg-subtle-hover);
78
+ --xh-action-host-bg-pressed: var(--xh-bg-subtle-active);
79
+ }
80
+
81
+ /* 附着式工具面:一张静态内容面,--xh-border-default 描边 + surface 底 + 无影(§5.3 边界只由描边承担)。 */
82
+ [data-scope='toolbar'][data-part='root'][data-variant='outline'] {
83
+ --xh-_toolbar-root-p: var(--xh-_toolbar-p);
84
+ --xh-_toolbar-root-border-width: var(--xh-stroke-thin);
85
+ --xh-_toolbar-root-border: var(--xh-border-default);
86
+ --xh-_toolbar-root-bg: var(--xh-bg-surface);
87
+ --xh-_toolbar-root-bg-disabled: var(--xh-bg-muted);
88
+
89
+ border-radius: var(--xh-toolbar-radius, var(--xh-shape-surface));
90
+ box-shadow: var(--xh-toolbar-shadow, none);
33
91
  }
34
92
 
35
93
  /* —— 尺寸 —— */
@@ -38,11 +96,15 @@
38
96
  [data-scope='toolbar'][data-part='root'][data-size='sm'] {
39
97
  --xh-_toolbar-gap: var(--xh-space-0_5);
40
98
  --xh-_toolbar-p: var(--xh-space-0_5);
99
+ --xh-_toolbar-item-h: var(--xh-control-h-sm);
100
+ --xh-icon-size: var(--xh-toolbar-icon-size, var(--xh-glyph-size-sm));
41
101
  }
42
102
 
43
103
  [data-scope='toolbar'][data-part='root'][data-size='lg'] {
44
- --xh-_toolbar-gap: var(--xh-space-2);
104
+ --xh-_toolbar-gap: var(--xh-space-3);
45
105
  --xh-_toolbar-p: var(--xh-space-2);
106
+ --xh-_toolbar-item-h: var(--xh-control-h-lg);
107
+ --xh-icon-size: var(--xh-toolbar-icon-size, var(--xh-glyph-size-lg));
46
108
  }
47
109
 
48
110
  /* root 会在焦点进条前短暂拿到 tabindex=0,但它的 onFocus 立刻把焦点转投给条目,
@@ -52,9 +114,8 @@
52
114
  }
53
115
 
54
116
  [data-scope='toolbar'][data-part='root'][data-disabled] {
55
- background: var(--xh-toolbar-bg-disabled, var(--xh-bg-muted));
117
+ background: var(--xh-toolbar-bg-disabled, var(--xh-_toolbar-root-bg-disabled));
56
118
  color: var(--xh-fg-disabled);
57
- cursor: not-allowed;
58
119
  }
59
120
 
60
121
  /* 给了 display 的角色节点必须补这条:display 声明会盖掉 UA 的 [hidden]{display:none},
@@ -63,57 +124,144 @@
63
124
  display: none;
64
125
  }
65
126
 
66
- /* 分组把一串相关控件收得更紧:组内间距比条上的总间距小,
67
- "这几个是一伙的"才看得出来 */
127
+ /* 分组只负责把相关操作连成一条,表面与交互状态由每个分段自己绘制。 */
68
128
  [data-scope='toolbar'][data-part='group'] {
69
- display: flex;
70
- align-items: center;
71
- gap: var(--xh-toolbar-group-gap, var(--xh-space-0_5));
129
+ display: inline-flex;
130
+ flex-wrap: nowrap;
131
+ align-items: stretch;
132
+ gap: var(--xh-toolbar-group-gap, var(--xh-space-0));
133
+ background: transparent;
72
134
  }
73
135
 
74
136
  [data-scope='toolbar'][data-part='group'][data-orientation='vertical'] {
75
137
  flex-direction: column;
76
138
  align-items: stretch;
139
+ flex-wrap: nowrap;
77
140
  }
78
141
 
79
142
  [data-scope='toolbar'][data-part='group'][hidden] {
80
143
  display: none;
81
144
  }
82
145
 
83
- /* 条目是作者自己的控件(按钮、切换钮、下拉触发器),观感归它自己的皮肤。
84
- 这里只补两件与导航直接相关的事:焦点环与禁用光标。
85
- 刻意不给 display——给了会把条目自身皮肤里的排布盖掉,也就不必补 [hidden] 那条 */
86
- [data-scope='toolbar'][data-part='item']:focus-visible {
87
- outline: var(--xh-ring-width) solid var(--xh-ring-focus);
88
- outline-offset: var(--xh-ring-offset);
146
+ /* 默认条目是一枚无描边工具按钮:盒型、三档几何、悬停 / 按下 / 禁用面与按压缩放由 Action Control 的
147
+ text 档给(ghost 形态:ghost 根按画布承载 hover 100 → pressed 200,subtle 根与分组由 host 槽下发
148
+ 200 300,§7.2);这里只把使用者槽映射到桥接槽(-gap / -h / -px / -radius / -bg / -bg-hover /
149
+ -bg-active / -bg-disabled / -fg / -font-size 保留为第一参数)。作者仍可用类名或内联样式完整覆盖。 */
150
+ [data-scope='toolbar'][data-part='item'] {
151
+ --xh-action-gap: var(--xh-toolbar-item-gap, var(--xh-control-gap-sm));
152
+ --xh-action-visual-size: var(--xh-toolbar-item-h, var(--xh-_action-profile-visual-size));
153
+ --xh-action-padding-inline: var(--xh-toolbar-item-px, var(--xh-_action-profile-padding-inline));
154
+ --xh-action-radius: var(--xh-toolbar-item-radius, var(--xh-_action-profile-radius));
155
+ --xh-action-bg-rest: var(--xh-toolbar-item-bg, var(--xh-_action-variant-bg-rest));
156
+ --xh-action-bg-hover: var(--xh-toolbar-item-bg-hover, var(--xh-_action-variant-bg-hover));
157
+ --xh-action-bg-pressed: var(--xh-toolbar-item-bg-active, var(--xh-_action-variant-bg-pressed));
158
+ --xh-action-bg-disabled: var(--xh-toolbar-item-bg-disabled, var(--xh-_action-variant-bg-disabled));
159
+ --xh-action-fg-rest: var(--xh-toolbar-item-fg, var(--xh-_action-variant-fg-rest));
160
+ --xh-action-fg-hover: var(--xh-toolbar-item-fg, var(--xh-_action-variant-fg-hover));
161
+ --xh-action-fg-pressed: var(--xh-toolbar-item-fg, var(--xh-_action-variant-fg-pressed));
162
+ --xh-action-font-size: var(--xh-toolbar-item-font-size, var(--xh-_action-profile-font-size));
163
+
164
+ font-weight: var(--xh-toolbar-item-font-weight, var(--xh-text-label-weight));
165
+ touch-action: manipulation;
89
166
  }
90
167
 
91
- /* 集合条目一律 aria-disabled 而非原生 disabled(禁用项仍要能当方向键的起点),
92
- 所以这里读 data-disabled,写 :disabled 永远不命中 */
93
- [data-scope='toolbar'][data-part='item'][data-disabled] {
94
- color: var(--xh-fg-disabled);
95
- cursor: not-allowed;
168
+ /* 无滑块开关的按下态(§7.3):品牌淡底 + 淡底前景,hover / 按下沿 12% → 20% → 28% 三档走;
169
+ 三态都经桥接槽交给家族画,禁用面仍由家族按 data-disabled */
170
+ [data-scope='toolbar'][data-part='item'][aria-pressed='true'] {
171
+ --xh-action-bg-rest: var(--xh-toolbar-item-bg-pressed, var(--xh-bg-brand-subtle));
172
+ --xh-action-bg-hover: var(--xh-toolbar-item-bg-pressed-hover, var(--xh-bg-brand-subtle-hover));
173
+ --xh-action-bg-pressed: var(--xh-toolbar-item-bg-pressed-active, var(--xh-bg-brand-subtle-active));
174
+ --xh-action-fg-rest: var(--xh-toolbar-item-fg-pressed, var(--xh-fg-on-brand-subtle));
175
+ --xh-action-fg-hover: var(--xh-toolbar-item-fg-pressed, var(--xh-fg-on-brand-subtle));
176
+ --xh-action-fg-pressed: var(--xh-toolbar-item-fg-pressed, var(--xh-fg-on-brand-subtle));
177
+ }
178
+
179
+ [data-scope='toolbar'][data-part='item'][hidden] {
180
+ display: none;
96
181
  }
97
182
 
98
- /* 分隔线画的是它自己的朝向:横排工具条里它是竖线,连接层给的就是 vertical。
99
- 粗的那一维写死描边宽度,长的那一维交给 align-self 拉伸,
100
- 沿长边再内缩一点,线才不会顶到工具条的上下边 */
183
+ /* 组内分段使用同一块中性操作面(淡底承载:hover 200 → pressed 300 由 host 槽下发);
184
+ 中间段保持直角,只给整组两端补回控件圆角。按下态 / 禁用面与散落条目同一套规则 */
185
+ [data-scope='toolbar'][data-part='group'] > [data-scope='toolbar'][data-part='item'] {
186
+ --xh-action-host-bg-hover: var(--xh-bg-subtle-hover);
187
+ --xh-action-host-bg-pressed: var(--xh-bg-subtle-active);
188
+ --xh-action-radius: 0;
189
+ --xh-action-bg-disabled: var(--xh-toolbar-item-bg-disabled, var(--xh-bg-subtle));
190
+
191
+ position: relative;
192
+ }
193
+
194
+ /* 组内未选中的段才铺中性面:选中段的品牌淡底由上面 aria-pressed 那条给,这条比它更特定,不守卫会把它盖掉 */
195
+ [data-scope='toolbar'][data-part='group'] > [data-scope='toolbar'][data-part='item']:not([aria-pressed='true']) {
196
+ --xh-action-bg-rest: var(--xh-toolbar-item-bg, var(--xh-bg-subtle));
197
+ }
198
+
199
+ [data-scope='toolbar'][data-part='group'][data-orientation='horizontal']
200
+ > [data-scope='toolbar'][data-part='item']:first-of-type {
201
+ border-start-start-radius: var(--xh-toolbar-item-radius, var(--xh-shape-control));
202
+ border-end-start-radius: var(--xh-toolbar-item-radius, var(--xh-shape-control));
203
+ }
204
+
205
+ [data-scope='toolbar'][data-part='group'][data-orientation='horizontal']
206
+ > [data-scope='toolbar'][data-part='item']:last-of-type {
207
+ border-start-end-radius: var(--xh-toolbar-item-radius, var(--xh-shape-control));
208
+ border-end-end-radius: var(--xh-toolbar-item-radius, var(--xh-shape-control));
209
+ }
210
+
211
+ [data-scope='toolbar'][data-part='group'][data-orientation='vertical']
212
+ > [data-scope='toolbar'][data-part='item']:first-of-type {
213
+ border-start-start-radius: var(--xh-toolbar-item-radius, var(--xh-shape-control));
214
+ border-start-end-radius: var(--xh-toolbar-item-radius, var(--xh-shape-control));
215
+ }
216
+
217
+ [data-scope='toolbar'][data-part='group'][data-orientation='vertical']
218
+ > [data-scope='toolbar'][data-part='item']:last-of-type {
219
+ border-end-start-radius: var(--xh-toolbar-item-radius, var(--xh-shape-control));
220
+ border-end-end-radius: var(--xh-toolbar-item-radius, var(--xh-shape-control));
221
+ }
222
+
223
+ /* 分隔线取控件高度的一半;横排工具条里画竖线,竖排工具条里画横线。 */
101
224
  [data-scope='toolbar'][data-part='separator'] {
102
225
  flex: none;
103
- align-self: stretch;
226
+ align-self: center;
104
227
  border-radius: var(--xh-toolbar-separator-radius, var(--xh-shape-pill));
105
228
  background: var(--xh-toolbar-separator-color, var(--xh-border-default));
106
229
  }
107
230
 
108
231
  [data-scope='toolbar'][data-part='separator'][data-orientation='vertical'] {
109
232
  inline-size: var(--xh-toolbar-separator-thickness, var(--xh-stroke-thin));
110
- margin-block: var(--xh-toolbar-separator-inset, var(--xh-space-1));
111
- margin-inline: var(--xh-toolbar-separator-gap, var(--xh-space-1));
233
+ block-size: var(--xh-_toolbar-separator-size);
234
+ margin-block: var(--xh-toolbar-separator-inset, var(--xh-space-0));
235
+ margin-inline: var(--xh-toolbar-separator-gap, var(--xh-space-0));
112
236
  }
113
237
 
114
238
  [data-scope='toolbar'][data-part='separator'][data-orientation='horizontal'] {
115
239
  block-size: var(--xh-toolbar-separator-thickness, var(--xh-stroke-thin));
116
- margin-block: var(--xh-toolbar-separator-gap, var(--xh-space-1));
117
- margin-inline: var(--xh-toolbar-separator-inset, var(--xh-space-1));
240
+ inline-size: var(--xh-_toolbar-separator-size);
241
+ margin-block: var(--xh-toolbar-separator-gap, var(--xh-space-0));
242
+ margin-inline: var(--xh-toolbar-separator-inset, var(--xh-space-0));
243
+ }
244
+
245
+ /* 组内分隔线覆盖在相邻分段的接缝上,不占额外宽度;半高弱线保留整体连续感。 */
246
+ [data-scope='toolbar'][data-part='group'] > [data-scope='toolbar'][data-part='separator'] {
247
+ background: var(--xh-toolbar-separator-color, var(--xh-fg-default));
248
+ opacity: var(--xh-toolbar-separator-opacity, var(--xh-control-separator-opacity));
249
+ pointer-events: none;
250
+ }
251
+
252
+ [data-scope='toolbar'][data-part='group'] > [data-scope='toolbar'][data-part='separator'][data-orientation='vertical'] {
253
+ margin-inline-start: calc(-1 * var(--xh-toolbar-separator-thickness, var(--xh-stroke-thin)));
254
+ }
255
+
256
+ [data-scope='toolbar'][data-part='group'] > [data-scope='toolbar'][data-part='separator'][data-orientation='horizontal'] {
257
+ margin-block-start: calc(-1 * var(--xh-toolbar-separator-thickness, var(--xh-stroke-thin)));
258
+ }
259
+
260
+ @media (forced-colors: active) {
261
+ /* 分段之间那条线画的是一块纯底色,这一档里底色被统一换成 Canvas,线整条消失,
262
+ 几段控件就连成了一长串。换成前景色画回来 */
263
+ [data-scope='toolbar'][data-part='separator'] {
264
+ background: CanvasText;
265
+ }
118
266
  }
119
267
  }
package/css/tooltip.css CHANGED
@@ -1,30 +1,12 @@
1
- @layer xihan.motion {
2
- /* 动画名的查找只认「文档里有没有这个名字」:引用别处文件里的名字,那份文件不一定在场,
3
- 动画会静默地整个不跑。每份皮肤都能单独引入,所以它用到的关键帧都写在自己身上。 */
4
- @keyframes xh-pop-in {
5
- from {
6
- opacity: 0;
7
- scale: var(--xh-motion-scale-enter);
8
- }
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
+ */
9
5
 
10
- to {
11
- opacity: 1;
12
- scale: 1;
13
- }
14
- }
6
+ /* 定义 tooltip 样式。 */
15
7
 
16
- @keyframes xh-pop-out {
17
- from {
18
- opacity: 1;
19
- scale: 1;
20
- }
21
-
22
- to {
23
- opacity: 0;
24
- scale: var(--xh-motion-scale-enter);
25
- }
26
- }
27
- }
8
+ /* 共享关键帧由 family/motion.css 提供,本皮肤 @import 它,单独引入仍成立。 */
9
+ @import '../family/motion.css';
28
10
 
29
11
  @layer xihan.components {
30
12
  /* 皮肤在场的标记:开发模式下按 scope 探一次,取不到就说明这份皮肤没被引入。 */
@@ -44,17 +26,23 @@
44
26
  cursor: inherit;
45
27
  }
46
28
 
47
- [data-scope='tooltip'][data-part='trigger']:focus-visible {
48
- outline: var(--xh-ring-width) solid var(--xh-ring-focus);
49
- outline-offset: var(--xh-ring-offset);
29
+ /* 这里的 data-disabled 关掉的是提示,不是宿主控件:光标仍旧交给宿主 */
30
+ [data-scope='tooltip'][data-part='trigger'][data-disabled] {
31
+ cursor: inherit;
50
32
  }
51
33
 
52
34
  /* 坐标由定位引擎写在行内 style 上,这里只兜底 SSR 首帧 */
53
35
  [data-scope='tooltip'][data-part='positioner'] {
36
+ /* 先截断祖先浮层的方向,再按本次实际 placement 只启用一侧。 */
37
+ --xh-_overlay-enter-up: 0;
38
+ --xh-_overlay-enter-down: 0;
39
+ --xh-_overlay-enter-left: 0;
40
+ --xh-_overlay-enter-right: 0;
41
+
54
42
  position: fixed;
55
43
  inset-block-start: 0;
56
44
  inset-inline-start: 0;
57
- z-index: var(--xh-tooltip-layer, var(--xh-layer-tooltip));
45
+ z-index: var(--xh-tooltip-layer, var(--xh-_layer, var(--xh-layer-tooltip)));
58
46
  /* 浮层不承载交互:指针必须能穿过去点到底下的东西 */
59
47
  pointer-events: none;
60
48
  }
@@ -64,18 +52,44 @@
64
52
  visibility: hidden;
65
53
  }
66
54
 
55
+ /* 进退位移按落定的那一侧给。placement 与 translate 都是物理方向,不随书写方向翻。 */
56
+ [data-scope='tooltip'][data-part='positioner'][data-placement^='top'] {
57
+ --xh-_overlay-enter-down: 1;
58
+ }
59
+
60
+ [data-scope='tooltip'][data-part='positioner'][data-placement^='bottom'] {
61
+ --xh-_overlay-enter-up: 1;
62
+ }
63
+
64
+ [data-scope='tooltip'][data-part='positioner'][data-placement^='left'] {
65
+ --xh-_overlay-enter-right: 1;
66
+ }
67
+
68
+ [data-scope='tooltip'][data-part='positioner'][data-placement^='right'] {
69
+ --xh-_overlay-enter-left: 1;
70
+ }
71
+
67
72
  [data-scope='tooltip'][data-part='content'] {
68
73
  /* 尺寸档只换这三个私有槽。tooltip 没有 root 部件,两轴都落在浮层树最外层的 content 上,
69
74
  箭头是它的后代,语气槽一并继承 */
70
75
  --xh-_tooltip-py: var(--xh-space-1);
71
76
  --xh-_tooltip-px: var(--xh-space-2);
72
77
  --xh-_tooltip-font-size: var(--xh-control-caption-md);
78
+ /* Tooltip 保留反白身份(真源 §8.4 登记的反白 compact frosted):短提示要与可交互的普通主题浮层一眼分开。
79
+ 94% 是六种 tone 在纯黑/纯白最坏底色上仍托住 4.5:1 正文的首个安全档。
80
+ 边不取 --xh-material-frosted-border:那是深色 14% 的透明边,压在反白深底上看不见,
81
+ §8.1 要求的 1px 可见边界由 on 色 20% 拼色承担;§8.1 禁玻璃高光,顶光缺省不画 */
82
+ --xh-_tooltip-solid: var(--xh-_tone, var(--xh-fg-default));
83
+ --xh-_tooltip-on: var(--xh-_tone-on, var(--xh-bg-surface));
84
+ --xh-_tooltip-border: color-mix(in oklab, var(--xh-_tooltip-on) 20%, transparent);
73
85
 
74
86
  /* 与 positioner 相反:浮层本体要能接指针,指针停在提示上就不该收起
75
87
  (长文案需要停留细看)。positioner 仍是 none,空白区域照样点得穿。 */
76
88
  /* 显式声明 display 是为了盖掉 UA 的 [hidden]{display:none}:收起那一帧 content 仍带 hidden,
77
89
  盒子得先在,退场动画才播得出来。真正的收起由宿主在退场结束后落成内联 display */
78
90
  display: block;
91
+ position: relative;
92
+ isolation: isolate;
79
93
  pointer-events: auto;
80
94
  max-inline-size: var(--xh-tooltip-max-w, var(--xh-overlay-max-w));
81
95
  padding-block: var(--xh-tooltip-py, var(--xh-_tooltip-py));
@@ -83,22 +97,47 @@
83
97
  /* 这里刻意用 control 而不是浮层那档 surface:提示气泡通常只有一行字、高度接近控件,
84
98
  8px 圆角在这个尺寸上占比过大,看着会发胖。档位定义里为此单列了一条 */
85
99
  border-radius: var(--xh-tooltip-radius, var(--xh-shape-control));
86
- /* 实心底与其上的文字色随语气走。没写 data-tone 时两个槽都没被声明,退回原来的取值 */
87
- background: var(--xh-tooltip-bg, var(--xh-_tone, var(--xh-fg-default)));
88
- color: var(--xh-tooltip-fg, var(--xh-_tone-on, var(--xh-bg-surface)));
100
+ border: var(--xh-stroke-thin) solid var(--xh-tooltip-border, var(--xh-_tooltip-border));
101
+ background: transparent;
102
+ color: var(--xh-tooltip-fg, var(--xh-_tooltip-on));
89
103
  font-size: var(--xh-tooltip-font-size, var(--xh-_tooltip-font-size));
90
104
  line-height: var(--xh-leading-normal);
91
- box-shadow: var(--xh-tooltip-shadow, var(--xh-elevation-floating));
105
+ overflow-wrap: anywhere;
106
+ text-wrap: pretty;
107
+ --xh-_tooltip-elevation-shadow: var(--xh-tooltip-shadow, var(--xh-material-frosted-compact-shadow));
108
+
109
+ /* 顶光槽缺省透明(§8.1 不用顶部高光),使用者要加自行灌色 */
110
+ box-shadow:
111
+ inset 0 var(--xh-stroke-thin) 0 var(--xh-tooltip-highlight, transparent),
112
+ var(--xh-_tooltip-elevation-shadow);
113
+ -webkit-backdrop-filter: var(--xh-tooltip-backdrop, var(--xh-material-frosted-compact-backdrop));
114
+ backdrop-filter: var(--xh-tooltip-backdrop, var(--xh-material-frosted-compact-backdrop));
92
115
  }
93
116
 
117
+ /* 光学层单独承载 tint 与透明度;backdrop-filter 只采样元素背后,不处理正文。 */
118
+ [data-scope='tooltip'][data-part='content']::before {
119
+ content: '';
120
+ position: absolute;
121
+ z-index: -1;
122
+ inset: 0;
123
+ border-radius: inherit;
124
+ background: var(--xh-tooltip-bg, var(--xh-_tooltip-solid));
125
+ opacity: var(--xh-material-frosted-compact-alpha);
126
+ pointer-events: none;
127
+ }
128
+
129
+ /* 入场走 enter 档(§9.5:锚定列表族的 tooltip 入场 --xh-motion-duration-enter),退场仍是 exit */
94
130
  [data-scope='tooltip'][data-part='content'][data-state='open'] {
95
- animation: xh-pop-in var(--xh-motion-duration-enter) var(--xh-motion-ease-enter);
131
+ animation: xh-overlay-slide-in var(--xh-motion-duration-enter) var(--xh-motion-ease-enter-strong);
132
+ /* 只在开着的这一档挂:合成层随 data-state 一起收走,收起后不再占着 */
133
+ will-change: opacity, translate;
96
134
  }
97
135
 
98
136
  /* 退场:收起那一帧 hidden 由退场闸门押后,这里才播得出来。forwards 把末态钉住,
99
137
  免得动画结束到真收起之间闪一下原样 */
100
138
  [data-scope='tooltip'][data-part='content'][data-state='closed'] {
101
- animation: xh-pop-out var(--xh-motion-duration-exit) var(--xh-motion-ease-exit) forwards;
139
+ will-change: opacity, translate;
140
+ animation: xh-overlay-slide-out var(--xh-motion-duration-exit) var(--xh-motion-ease-exit) forwards;
102
141
  }
103
142
 
104
143
  /* —— 尺寸 —— */
@@ -125,7 +164,31 @@
125
164
  --xh-_overlay-arrow-x: var(--xh-_tooltip-arrow-x);
126
165
  --xh-_overlay-arrow-y: var(--xh-_tooltip-arrow-y);
127
166
 
128
- background: var(--xh-tooltip-bg, var(--xh-_tone, var(--xh-fg-default)));
167
+ background: var(--xh-tooltip-bg, var(--xh-_tooltip-solid));
168
+ border: var(--xh-stroke-thin) solid var(--xh-tooltip-border, var(--xh-_tooltip-border));
169
+ opacity: var(--xh-material-frosted-compact-alpha);
170
+ }
171
+
172
+ /* 高对比仍保持反白语义:compact 配方已把 tint / blur / shadow 换成实体档,此处只加强同色边界。 */
173
+ :is([data-contrast='more'] *, [data-contrast='more'])[data-scope='tooltip'][data-part='content'] {
174
+ --xh-_tooltip-border: var(--xh-_tooltip-on);
175
+ }
176
+
177
+ @media (forced-colors: active) {
178
+ [data-scope='tooltip'][data-part='content'],
179
+ [data-scope='tooltip'][data-part='arrow'] {
180
+ border-color: CanvasText;
181
+ background: Canvas;
182
+ color: CanvasText;
183
+ box-shadow: none;
184
+ -webkit-backdrop-filter: none;
185
+ backdrop-filter: none;
186
+ }
187
+
188
+ [data-scope='tooltip'][data-part='content']::before {
189
+ background: Canvas;
190
+ opacity: 1;
191
+ }
129
192
  }
130
193
 
131
194
  /* 声明过任何 display 就盖掉了 UA 的 [hidden]{display:none},收起态得自己还回去。
@@ -133,4 +196,12 @@
133
196
  [data-scope='tooltip'][data-part='trigger'][hidden] {
134
197
  display: none;
135
198
  }
199
+
200
+ @media print {
201
+ /* 打印:定位层与遮罩是交互期才存在的东西,落到纸上只会盖住底下的正文。
202
+ 收起写在这份皮肤里而不是 reset:reset 层排在组件层之前,组件层里任何一条 display 都压得住它。 */
203
+ [data-scope='tooltip'][data-part='positioner'] {
204
+ display: none;
205
+ }
206
+ }
136
207
  }