@xihan-ui/styles 2.0.0 → 3.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 (156) hide show
  1. package/CHANGELOG.md +1328 -0
  2. package/README.md +6 -1
  3. package/component-tokens.d.ts +505 -111
  4. package/components.tokens.json +34750 -26291
  5. package/css/accordion.css +39 -13
  6. package/css/alert.css +61 -3
  7. package/css/anchor.css +49 -11
  8. package/css/approval.css +124 -84
  9. package/css/avatar-group.css +1 -1
  10. package/css/avatar.css +13 -5
  11. package/css/back-top.css +63 -44
  12. package/css/badge.css +63 -13
  13. package/css/bar-code.css +1 -1
  14. package/css/breadcrumb.css +63 -4
  15. package/css/button-group.css +5 -5
  16. package/css/button.css +69 -21
  17. package/css/calendar-picker.css +27 -8
  18. package/css/calendar-range-picker.css +48 -11
  19. package/css/card.css +116 -2
  20. package/css/carousel.css +153 -48
  21. package/css/cartesian-chart.css +830 -0
  22. package/css/cascader.css +184 -70
  23. package/css/checkbox-group.css +69 -99
  24. package/css/checkbox.css +21 -54
  25. package/css/citation.css +470 -0
  26. package/css/clipboard.css +23 -66
  27. package/css/code-view.css +103 -8
  28. package/css/collapsible.css +37 -11
  29. package/css/color-field.css +18 -0
  30. package/css/color-picker.css +57 -62
  31. package/css/color-slider.css +26 -19
  32. package/css/color-swatch-picker.css +8 -6
  33. package/css/combobox.css +82 -37
  34. package/css/command.css +48 -48
  35. package/css/context-menu.css +43 -28
  36. package/css/date-field.css +23 -0
  37. package/css/date-picker.css +57 -24
  38. package/css/date-range-picker.css +301 -14
  39. package/css/description.css +17 -1
  40. package/css/descriptions.css +43 -1
  41. package/css/dialog.css +99 -43
  42. package/css/diff-view.css +101 -16
  43. package/css/download-trigger.css +46 -80
  44. package/css/drawer.css +168 -133
  45. package/css/editable.css +19 -0
  46. package/css/empty-state.css +8 -7
  47. package/css/field-array.css +36 -0
  48. package/css/field.css +17 -19
  49. package/css/fieldset.css +1 -1
  50. package/css/file-upload.css +126 -136
  51. package/css/flex.css +324 -8
  52. package/css/float-button.css +168 -41
  53. package/css/floating-panel.css +59 -27
  54. package/css/form.css +26 -20
  55. package/css/funnel-chart.css +106 -0
  56. package/css/graph-chart.css +205 -0
  57. package/css/grid-list.css +235 -0
  58. package/css/grid.css +252 -1
  59. package/css/heatmap.css +119 -36
  60. package/css/hierarchy-chart.css +298 -0
  61. package/css/hover-card.css +33 -18
  62. package/css/icon.css +100 -0
  63. package/css/image-cropper.css +34 -8
  64. package/css/image-viewer.css +169 -26
  65. package/css/image.css +23 -4
  66. package/css/infinite-scroll.css +2 -2
  67. package/css/input-group.css +13 -15
  68. package/css/json-viewer.css +55 -7
  69. package/css/kbd.css +1 -1
  70. package/css/layout.css +71 -21
  71. package/css/liquid.css +106 -0
  72. package/css/list.css +2 -2
  73. package/css/listbox.css +72 -23
  74. package/css/loading-bar.css +27 -13
  75. package/css/log.css +131 -35
  76. package/css/markdown-stream.css +1 -1
  77. package/css/marquee.css +163 -7
  78. package/css/matrix-code.css +1 -1
  79. package/css/mention.css +35 -21
  80. package/css/menu.css +40 -28
  81. package/css/menubar.css +42 -28
  82. package/css/message-feed.css +174 -53
  83. package/css/navigation-menu.css +177 -18
  84. package/css/notification.css +431 -110
  85. package/css/number-field.css +22 -0
  86. package/css/page-header.css +4 -2
  87. package/css/pagination.css +129 -29
  88. package/css/password-input.css +40 -8
  89. package/css/pie-chart.css +247 -0
  90. package/css/popconfirm.css +50 -58
  91. package/css/popover.css +55 -21
  92. package/css/progress.css +308 -10
  93. package/css/prompt-input.css +37 -1
  94. package/css/question-flow.css +104 -64
  95. package/css/radar-chart.css +233 -0
  96. package/css/radio-group.css +372 -14
  97. package/css/rating.css +25 -27
  98. package/css/reasoning.css +62 -55
  99. package/css/reset.css +1 -1
  100. package/css/resizable.css +6 -1
  101. package/css/sankey-chart.css +174 -0
  102. package/css/scroll-area.css +32 -0
  103. package/css/scrollbar.css +1 -1
  104. package/css/select.css +76 -59
  105. package/css/side-nav.css +177 -30
  106. package/css/signature-pad.css +23 -8
  107. package/css/skeleton.css +13 -14
  108. package/css/slider.css +39 -17
  109. package/css/sortable.css +38 -8
  110. package/css/sparkline.css +164 -0
  111. package/css/spinner.css +50 -22
  112. package/css/splitter.css +8 -2
  113. package/css/statistic.css +10 -0
  114. package/css/steps.css +257 -38
  115. package/css/switch.css +30 -55
  116. package/css/table.css +168 -128
  117. package/css/tabs.css +243 -31
  118. package/css/tag-group.css +65 -37
  119. package/css/tag.css +55 -14
  120. package/css/tags-input.css +40 -3
  121. package/css/text-field.css +19 -0
  122. package/css/time-field.css +20 -1
  123. package/css/time-picker.css +44 -17
  124. package/css/time-range-picker.css +45 -18
  125. package/css/timeline.css +1 -1
  126. package/css/toggle-group.css +8 -8
  127. package/css/toggle.css +6 -5
  128. package/css/tool-call.css +64 -56
  129. package/css/toolbar.css +105 -7
  130. package/css/tooltip.css +18 -7
  131. package/css/tour.css +49 -21
  132. package/css/transfer.css +104 -81
  133. package/css/tree-select.css +235 -58
  134. package/css/tree.css +240 -147
  135. package/css/truncate.css +55 -12
  136. package/css/typography.css +93 -0
  137. package/css/virtualizer.css +57 -1
  138. package/css/watermark.css +23 -0
  139. package/family/action-control.css +14 -5
  140. package/family/chart.css +480 -0
  141. package/family/check-mark.css +94 -0
  142. package/family/choice-card.css +97 -0
  143. package/family/collection-item.css +70 -27
  144. package/family/field-chrome.css +1 -12
  145. package/family/loading-ring.css +95 -0
  146. package/family/material.css +72 -0
  147. package/family/menu-choice.css +56 -0
  148. package/family/motion.css +208 -11
  149. package/family/tag-list.css +59 -0
  150. package/index.css +23363 -14091
  151. package/index.unlayered.css +23198 -13922
  152. package/package.json +20 -8
  153. package/css/gradient-text.css +0 -91
  154. package/css/icon-wrapper.css +0 -81
  155. package/css/segmented.css +0 -280
  156. package/css/toast.css +0 -499
@@ -6,6 +6,8 @@
6
6
  /* 定义 checkbox group 样式。 */
7
7
 
8
8
  @import '../family/action-control.css';
9
+ @import '../family/check-mark.css';
10
+ @import '../family/choice-card.css';
9
11
 
10
12
  @layer xihan.components {
11
13
  /* 皮肤在场的标记:开发模式下按 scope 探一次,取不到就说明这份皮肤没被引入。 */
@@ -18,7 +20,7 @@
18
20
  [data-scope='checkbox-group'][data-part='root'] {
19
21
  /* 尺寸档只换这四个私有槽,条目、方框与全选格都从 root 继承它们,
20
22
  换档不必给每个部件各写一条选择器。方框与字形照 checkbox 的档位走,
21
- 单体与集合里的同一枚方框必须一样大;条目文字是控件文字,随档取 --xh-control-font-*(§6.4) */
23
+ 单体与集合里的同一枚方框必须一样大;条目文字是控件文字,随档取 --xh-control-font-* */
22
24
  --xh-_checkbox-group-box: var(--xh-control-indicator-md);
23
25
  --xh-_checkbox-group-glyph: calc(var(--xh-_checkbox-group-box) * 0.75);
24
26
  --xh-_checkbox-group-gap: var(--xh-control-gap-md);
@@ -26,10 +28,11 @@
26
28
  /* 作者塞进指示符槽的图标和皮肤画的兜底字形共用盒比例(与 checkbox 同一把尺);显式 icon-size 仍可覆盖 */
27
29
  --xh-icon-size: var(--xh-checkbox-group-icon-size, var(--xh-_checkbox-group-glyph));
28
30
 
29
- /* 勾中的填色随语气走;没写 data-tone 时退回品牌色 */
30
- --xh-_checkbox-group-accent: var(--xh-_tone, var(--xh-bg-brand));
31
+ /* 勾中的填色随语气走,与独立 Checkbox 同一支:选中态是小面积控件边界,取保证 3:1 的语气 control 色;
32
+ 没写 data-tone 时退回品牌色 */
33
+ --xh-_checkbox-group-accent: var(--xh-_tone-border-control, var(--xh-bg-brand));
31
34
  --xh-_checkbox-group-on-accent: var(--xh-_tone-on, var(--xh-fg-on-brand));
32
- /* 方框是字段家族的控制盒(§8.3 字段静息形态):透明底 + --xh-border-control 描边 + 无影,不消费海拔与顶光 */
35
+ /* 方框是字段家族的控制盒(字段静息形态):透明底 + --xh-border-control 描边 + 无影,不消费海拔与顶光 */
33
36
  --xh-_checkbox-group-bg: var(--xh-checkbox-group-indicator-bg, transparent);
34
37
  /* 条目与全选格是方框的承载面:行自己坐画布走 100 → 200,行面上的方框按淡底容器阶梯再上一档(200 → 300)。
35
38
  两支私有槽是这一档的唯一来源——宿主拿它们给 --xh-action-host-bg-* 赋值(桥接槽只写不读),
@@ -38,7 +41,7 @@
38
41
  --xh-_checkbox-group-host-bg-pressed: var(--xh-bg-subtle-active);
39
42
 
40
43
  /* 标题与条目都是根的直接子节点,一支 gap 同时管「标题到集合」与「条目之间」:
41
- 集合标题与集合隔 --xh-space-2(§6.4),同组条目之间也是同一档紧密关系 */
44
+ 集合标题与集合隔 --xh-space-2,同组条目之间也是同一档紧密关系 */
42
45
  display: flex;
43
46
  gap: var(--xh-checkbox-group-gap, var(--xh-space-2));
44
47
  }
@@ -71,7 +74,18 @@
71
74
  align-items: center;
72
75
  }
73
76
 
74
- /* 集合标题(§6.4):14 / 500 / fg-muted,字号不随 size 档 */
77
+ /* card 形态:卡片撑满竖排的一列;横排时各卡等分一行、按内容等高,窄到放不下两张就折到下一行 */
78
+ [data-scope='checkbox-group'][data-part='root'][data-variant='card'] {
79
+ align-items: stretch;
80
+ }
81
+
82
+ [data-scope='checkbox-group'][data-part='root'][data-variant='card'][data-orientation='horizontal']
83
+ > [data-scope='checkbox-group'][data-part='item'] {
84
+ flex: 1 1 0;
85
+ min-inline-size: min(var(--xh-control-min-w), 100%);
86
+ }
87
+
88
+ /* 集合标题:14 / 500 / fg-muted,字号不随 size 档 */
75
89
  [data-scope='checkbox-group'][data-part='label'] {
76
90
  color: var(--xh-checkbox-group-label-fg, var(--xh-fg-muted));
77
91
  font-size: var(--xh-checkbox-group-label-font-size, var(--xh-text-label-size));
@@ -85,7 +99,7 @@
85
99
  color: var(--xh-checkbox-group-label-fg-disabled, var(--xh-fg-subtle));
86
100
  }
87
101
 
88
- /* 条目是「方框 + 文案」的整行命中区(§9.2):接 Action Control row 档、ghost 形态,悬停 / 按下 / 禁用面、手型、
102
+ /* 条目是「方框 + 文案」的整行命中区:接 Action Control row 档、ghost 形态,悬停 / 按下 / 禁用面、手型、
89
103
  过渡与焦点环由家族给,按下只换面不缩放(row 档专属按压块 scale: none);这里只把使用者槽映射到桥接槽。
90
104
  行自己坐画布走 100 → 200(--xh-action-bg-* 钉住自己的面),行面上的方框按淡底容器阶梯再上一档
91
105
  (--xh-action-host-bg-* 向内声明自己是方框的承载面,host 槽只对后代生效——自己的面已由 --xh-action-bg-* 钉住;
@@ -122,7 +136,7 @@
122
136
  家族的 :hover / 按压块不排 readonly,只能从槽上收回;排掉禁用项是因为这条选择器权重高过家族的禁用块,
123
137
  不排就会把 not-allowed 覆盖回 default */
124
138
  [data-scope='checkbox-group'][data-part='root'][data-readonly]
125
- [data-scope='checkbox-group'][data-part='item']:not([data-disabled]) {
139
+ [data-scope='checkbox-group'][data-part='item']:not([data-disabled]):not([data-xh-choice-card]) {
126
140
  --xh-action-bg-hover: transparent;
127
141
  --xh-action-bg-pressed: transparent;
128
142
  --xh-action-cursor-rest: default;
@@ -149,7 +163,7 @@
149
163
  box-shadow: var(--xh-checkbox-group-indicator-shadow, none);
150
164
  font-size: var(--xh-checkbox-group-indicator-font-size, var(--xh-_checkbox-group-glyph));
151
165
  line-height: var(--xh-leading-none);
152
- /* 方框不缩放(§9.2 行级只换面),过渡只有底与描边;按下走 press 时间线、释放同走 micro */
166
+ /* 方框不缩放(行级只换面),过渡只有底与描边;按下走 press 时间线、释放同走 micro */
153
167
  transition:
154
168
  background-color var(--xh-motion-duration-micro) var(--xh-motion-ease-enter),
155
169
  border-color var(--xh-motion-duration-micro) var(--xh-motion-ease-enter);
@@ -161,7 +175,7 @@
161
175
  content: '';
162
176
  }
163
177
 
164
- /* 悬停整行时未勾选的方框描边升一档(字段静息 → hover 的同一条阶梯,§8.3);
178
+ /* 悬停整行时未勾选的方框描边升一档(字段静息 → hover 的同一条阶梯);
165
179
  勾中的方框描边与底同色,悬停不换描边——填色本身已经在表达状态 */
166
180
  @media (hover: hover) {
167
181
  [data-scope='checkbox-group'][data-part='root']:not([data-disabled]):not([data-readonly]):not([data-invalid])
@@ -182,7 +196,7 @@
182
196
  }
183
197
 
184
198
  /* 按下去要有回应。方框不是激活宿主:宿主是投影了 row 档的整行(条目 / 全选格),方框在宿主的
185
- :hover / :is(:active, [data-pressed]) 下读宿主 host 槽的同一来源换面、不缩放(§9.2)——行按下是 200,
199
+ :hover / :is(:active, [data-pressed]) 下读宿主 host 槽的同一来源换面、不缩放——行按下是 200,
186
200
  坐在上面的方框到 300(行以 --xh-action-host-bg-pressed 声明自己是方框的承载面,桥接槽只写不读,
187
201
  方框读的是喂给它的那支私有槽),勾中的换到语气的 active 档;
188
202
  与家族按压块同一时间线(按下 --xh-motion-duration-press,释放同走 micro) */
@@ -203,67 +217,9 @@
203
217
  --xh-_checkbox-group-bg: var(--xh-checkbox-group-indicator-bg-checked-pressed, var(--xh-_tone-active, var(--xh-bg-brand-active)));
204
218
  }
205
219
 
206
- /* 勾号由皮肤补,作者不必自己往 indicator 里塞字符 */
207
- [data-scope='checkbox-group'][data-part='indicator'][data-state='checked']:empty::before {
208
- content: '';
209
- display: inline-block;
210
- inline-size: var(--xh-icon-size, var(--xh-glyph-size-text));
211
- block-size: var(--xh-icon-size, var(--xh-glyph-size-text));
212
- vertical-align: var(--xh-glyph-baseline-shift);
213
- background-color: currentColor;
214
- -webkit-mask: var(--xh-glyph-mark-check) center / contain no-repeat;
215
- mask: var(--xh-glyph-mark-check) center / contain no-repeat;
216
- }
217
-
218
- /* 全选格的三态:checked 打勾、indeterminate 打横杠、unchecked 留空。
219
- indeterminate 就是读屏听到的 aria-checked=mixed,两者同源,样式只认 data-state。
220
-
221
- 字形走 ::after 而不是画方框的那颗 ::before:mask 会把所在元素的描边与底色一并裁成
222
- 字形的轮廓,写在 ::before 上就等于把方框本身裁没了,只剩一枚白勾。条目那一侧是
223
- 真实节点当方框、它的 ::before 当字形的两层结构,这里 anatomy 到 trigger 为止、
224
- 没有第二个节点,只能用第二个伪元素补上那一层。
225
- 方框是行首那颗 ::before、宽度即指示符尺寸,所以字形按「盒与字形的宽度差之半」
226
- 内推即落在圆心;纵向靠 inset-block: 0 + margin-block: auto 居中。
227
- font-size 与 ::before 同值,--xh-icon-size 的 1em 兜底才和条目那侧量得一样大 */
228
- [data-scope='checkbox-group'][data-part='select-all-trigger'][data-state='checked']::after {
229
- content: '';
230
- position: absolute;
231
- inset-block: 0;
232
- inset-inline-start: 0;
233
- margin-block: auto;
234
- margin-inline-start: calc(
235
- (
236
- var(--xh-checkbox-group-indicator-size, var(--xh-_checkbox-group-box)) -
237
- var(--xh-icon-size, var(--xh-glyph-size-text))
238
- ) / 2
239
- );
240
- inline-size: var(--xh-icon-size, var(--xh-glyph-size-text));
241
- block-size: var(--xh-icon-size, var(--xh-glyph-size-text));
242
- background-color: var(--xh-checkbox-group-indicator-fg, var(--xh-_checkbox-group-on-accent));
243
- font-size: var(--xh-checkbox-group-indicator-font-size, var(--xh-_checkbox-group-glyph));
244
- -webkit-mask: var(--xh-glyph-mark-check) center / contain no-repeat;
245
- mask: var(--xh-glyph-mark-check) center / contain no-repeat;
246
- }
247
-
248
- [data-scope='checkbox-group'][data-part='select-all-trigger'][data-state='indeterminate']::after {
249
- content: '';
250
- position: absolute;
251
- inset-block: 0;
252
- inset-inline-start: 0;
253
- margin-block: auto;
254
- margin-inline-start: calc(
255
- (
256
- var(--xh-checkbox-group-indicator-size, var(--xh-_checkbox-group-box)) -
257
- var(--xh-icon-size, var(--xh-glyph-size-text))
258
- ) / 2
259
- );
260
- inline-size: var(--xh-icon-size, var(--xh-glyph-size-text));
261
- block-size: var(--xh-icon-size, var(--xh-glyph-size-text));
262
- background-color: var(--xh-checkbox-group-indicator-fg, var(--xh-_checkbox-group-on-accent));
263
- font-size: var(--xh-checkbox-group-indicator-font-size, var(--xh-_checkbox-group-glyph));
264
- -webkit-mask: var(--xh-glyph-mark-minus) center / contain no-repeat;
265
- mask: var(--xh-glyph-mark-minus) center / contain no-repeat;
266
- }
220
+ /* 方框里的勾与全选格的三态标记(checked 打勾、indeterminate 打横杠、unchecked 留空)由勾选标记配方画:
221
+ 常驻、按状态淡变并轻缩放。条目的方框是真实节点,标记是它的 ::before;全选格的 anatomy 到 trigger
222
+ 为止,方框只能是行首那颗 ::before,标记是 ::after、叠在方框正中——两支桥接槽写在 trigger 上 */
267
223
 
268
224
  /* 校验失败标在每个方框上:root 上的 data-invalid 是唯一出处,条目自己不带这个属性 */
269
225
  [data-scope='checkbox-group'][data-part='root'][data-invalid]
@@ -271,7 +227,7 @@
271
227
  border-color: var(--xh-checkbox-group-indicator-border-invalid, var(--xh-border-invalid));
272
228
  }
273
229
 
274
- /* 禁用(§7.2):--xh-border-default 描边 + --xh-bg-subtle 底 + --xh-fg-disabled 字形,不靠 opacity */
230
+ /* 禁用:--xh-border-default 描边 + --xh-bg-subtle 底 + --xh-fg-disabled 字形,不靠 opacity */
275
231
  [data-scope='checkbox-group'][data-part='root'][data-disabled]
276
232
  [data-scope='checkbox-group'][data-part='indicator'],
277
233
  [data-scope='checkbox-group'][data-part='item'][data-disabled]
@@ -283,17 +239,49 @@
283
239
  color: var(--xh-checkbox-group-indicator-fg-disabled, var(--xh-fg-disabled));
284
240
  }
285
241
 
242
+ /* 全选格的标记画在 ::after 上,禁用色经桥接槽给,与条目方框里置灰的勾同色 */
243
+ [data-scope='checkbox-group'][data-part='select-all-trigger'][data-disabled] {
244
+ --xh-check-mark-fg: var(--xh-checkbox-group-indicator-fg-disabled, var(--xh-fg-disabled));
245
+ }
246
+
286
247
  [data-scope='checkbox-group'][data-part='item-text'] {
287
248
  color: inherit;
288
249
  user-select: none;
289
250
  }
290
251
 
252
+ /* 卡片的文案是卡的标题:取标签字重,与说明拉开层级 */
253
+ [data-scope='checkbox-group'][data-part='item'][data-xh-choice-card] > [data-scope='checkbox-group'][data-part='item-text'] {
254
+ font-weight: var(--xh-checkbox-group-card-title-font-weight, var(--xh-text-label-weight));
255
+ }
256
+
257
+ /* 说明是次级文字:13 / fg-muted / 正文行高,不随选中与语气换色;落在文案下方同一列。
258
+ 列表形态的条目带了说明时同样排成两行,行首的方框对齐第一行 */
259
+ [data-scope='checkbox-group'][data-part='item-description'] {
260
+ grid-column: 2;
261
+ color: var(--xh-checkbox-group-item-description-fg, var(--xh-fg-muted));
262
+ font-size: var(--xh-checkbox-group-item-description-font-size, var(--xh-text-secondary-size));
263
+ font-weight: var(--xh-font-weight-regular);
264
+ line-height: var(--xh-leading-normal);
265
+ user-select: none;
266
+ }
267
+
268
+ [data-scope='checkbox-group'][data-part='item']:not([data-xh-choice-card]):has(> [data-scope='checkbox-group'][data-part='item-description']) {
269
+ display: grid;
270
+ grid-template-columns: auto minmax(0, 1fr);
271
+ align-items: center;
272
+ row-gap: var(--xh-checkbox-group-item-row-gap, var(--xh-space-1));
273
+ }
274
+
275
+ [data-scope='checkbox-group'][data-part='item'][data-disabled] > [data-scope='checkbox-group'][data-part='item-description'] {
276
+ color: var(--xh-checkbox-group-item-description-fg-disabled, var(--xh-fg-disabled));
277
+ }
278
+
291
279
  /* 全选格与条目同形(接 Action Control row 档 ghost、xs 命中地板、按下只换面不缩放,方框读宿主 host 槽),
292
280
  但字重加一档,读起来才不像又一个普通选项。它是普通元素而非原生控件(三态只有非原生控件表达得出),
293
281
  家族的禁用块同样只读 data-disabled。position 是给叠在方框上的那颗字形 ::after 当定位基准 */
294
282
  [data-scope='checkbox-group'][data-part='select-all-trigger'] {
295
283
  --xh-action-gap: var(--xh-checkbox-group-select-all-trigger-gap, var(--xh-_checkbox-group-gap));
296
- /* 全选格的身份是嵌在 control 内的小方框(§6.3 select-all 方框取 inset),与条目方框同一档 */
284
+ /* 全选格的身份是嵌在 control 内的小方框(select-all 方框取 inset),与条目方框同一档 */
297
285
  --xh-action-radius: var(--xh-checkbox-group-select-all-trigger-radius, var(--xh-shape-inset));
298
286
  --xh-action-font-size: var(--xh-checkbox-group-select-all-trigger-font-size, var(--xh-_checkbox-group-font-size));
299
287
  --xh-action-padding-inline: 0;
@@ -308,6 +296,9 @@
308
296
  /* 行自己的面已由上面两支钉住,host 槽只对方框(::before)生效:200 → 300 */
309
297
  --xh-action-host-bg-hover: var(--xh-_checkbox-group-host-bg-hover);
310
298
  --xh-action-host-bg-pressed: var(--xh-_checkbox-group-host-bg-pressed);
299
+ /* 勾选标记叠在行首方框正中:方框边长与标记色交给配方 */
300
+ --xh-check-mark-box-size: var(--xh-checkbox-group-indicator-size, var(--xh-_checkbox-group-box));
301
+ --xh-check-mark-fg: var(--xh-checkbox-group-indicator-fg, var(--xh-_checkbox-group-on-accent));
311
302
 
312
303
  position: relative;
313
304
  inline-size: auto;
@@ -327,18 +318,12 @@
327
318
  }
328
319
 
329
320
  /* 家族 row 档在粗指针下用 ::after 把热区扩到 44px 高:条目按 24px 行 + 8px 间距密排,热区会压进相邻条目 2px、
330
- 指针落错行,A 档 24px 由 xs 地板保住(两者都不在 coarse-target 的 B 档名单);勾中 / 半选时全选格的 ::after
331
- 是叠在方框上的字形,家族的热区 translate 会把它拖走,钉回原位(同 transfer select-all-trigger) */
321
+ 指针落错行,A 档 24px 由 xs 地板保住(两者都不在 coarse-target 的 B 档名单);全选格的 ::after 是叠在方框上的
322
+ 勾选标记,热区由勾选标记配方逐项钉回 */
332
323
  @media (pointer: coarse) {
333
- [data-scope='checkbox-group'][data-part='item']::after,
334
- [data-scope='checkbox-group'][data-part='select-all-trigger']::after {
324
+ [data-scope='checkbox-group'][data-part='item']::after {
335
325
  min-block-size: 0;
336
326
  }
337
-
338
- [data-scope='checkbox-group'][data-part='select-all-trigger']:is([data-state='checked'], [data-state='indeterminate'])::after {
339
- min-block-size: 0;
340
- translate: none;
341
- }
342
327
  }
343
328
 
344
329
  /* 表单出口:连接层已经把整套视觉隐藏写进内联 style(absolute + 1px + clip-path),
@@ -357,22 +342,7 @@
357
342
  display: none;
358
343
  }
359
344
 
360
- @media (forced-colors: active) {
361
- /* 真实描边保留方框,系统前景重绘状态字形。 */
362
- [data-scope='checkbox-group'][data-part='indicator'][data-state='checked']:empty::before,
363
- [data-scope='checkbox-group'][data-part='select-all-trigger']:is([data-state='checked'], [data-state='indeterminate'])::after {
364
- background-color: CanvasText;
365
- }
366
-
367
- [data-scope='checkbox-group'][data-part='item'][data-disabled]
368
- [data-scope='checkbox-group'][data-part='indicator'][data-state='checked']:empty::before,
369
- [data-scope='checkbox-group'][data-part='select-all-trigger'][data-disabled]:is(
370
- [data-state='checked'],
371
- [data-state='indeterminate']
372
- )::after {
373
- background-color: GrayText;
374
- }
375
- }
345
+ /* 强制色:真实描边保留方框,状态字形的系统前景由勾选标记配方给 */
376
346
 
377
347
  @media print {
378
348
  [data-scope='checkbox-group'][data-part='indicator'][data-state='checked'],
package/css/checkbox.css CHANGED
@@ -6,6 +6,7 @@
6
6
  /* 定义 checkbox 样式。 */
7
7
 
8
8
  @import '../family/action-control.css';
9
+ @import '../family/check-mark.css';
9
10
 
10
11
  @layer xihan.components {
11
12
  /* 皮肤在场的标记:开发模式下按 scope 探一次,取不到就说明这份皮肤没被引入。 */
@@ -27,8 +28,8 @@
27
28
  /* 实心底上的勾与横杠,同样没写 data-tone 时退回原来的品牌底前景色 */
28
29
  --xh-_checkbox-on-accent: var(--xh-_tone-on, var(--xh-fg-on-brand));
29
30
 
30
- /* 方框接 Action Control icon 档(§9.1 定尺方框):盒型、悬停 / 按下 / 禁用面、0.97 缩放与换底、粗指针热区、
31
- 焦点环由家族配方给,这里只把使用者槽映射到桥接槽。面按字段静息形态取值(§8.3):透明底 +
31
+ /* 方框接 Action Control icon 档(定尺方框):盒型、悬停 / 按下 / 禁用面、0.97 缩放与换底、粗指针热区、
32
+ 焦点环由家族配方给,这里只把使用者槽映射到桥接槽。面按字段静息形态取值:透明底 +
32
33
  --xh-border-control 描边 + 无影,不消费海拔与顶光;悬停只把描边升一档,底不动;按下换到 200 档中性面
33
34
  (白底承载);边长随 --xh-control-indicator-* 走,不取家族的 profile 尺寸。
34
35
  常态 / 勾中 / 校验失败 / 只读只换下面四支私有槽,桥接槽的映射写一次 */
@@ -101,7 +102,7 @@
101
102
 
102
103
  /* 悬停标签文字时也让控制盒回应,整行可点不再只有移到 16px 小盒上才看得出来:
103
104
  指针落在方框上时由家族的悬停块换到 --xh-action-border-hover,落在标签文字上时这里补同一档;
104
- 未勾选的方框描边升一档(字段静息 → hover 的同一条阶梯,§8.3),勾中 / 校验失败的方框由上面的映射钉住不换 */
105
+ 未勾选的方框描边升一档(字段静息 → hover 的同一条阶梯),勾中 / 校验失败的方框由上面的映射钉住不换 */
105
106
  @media (hover: hover) {
106
107
  [data-scope='checkbox'][data-part='label']:not([data-disabled]):not([data-readonly]):hover
107
108
  [data-scope='checkbox'][data-part='root'] {
@@ -155,65 +156,32 @@
155
156
  }
156
157
  }
157
158
 
159
+ /* 指示器铺满方框。勾与半选杠由勾选标记配方画在它的 ::before 上(常驻、按状态淡变并轻缩放);
160
+ 作者往部件里塞了自己的图形时配方不画 */
158
161
  [data-scope='checkbox'][data-part='indicator'] {
159
162
  display: inline-flex;
160
163
  align-items: center;
161
164
  justify-content: center;
162
165
  inline-size: 100%;
163
166
  block-size: 100%;
164
- opacity: 0;
165
167
  line-height: var(--xh-leading-none);
166
168
  font-size: var(--xh-_checkbox-glyph);
167
169
  pointer-events: none;
168
- scale: var(--xh-motion-scale-enter);
169
- transition:
170
- opacity var(--xh-motion-duration-micro) var(--xh-motion-ease-enter),
171
- scale var(--xh-motion-duration-micro) var(--xh-motion-ease-enter-strong);
172
170
  }
173
171
 
174
- /* 没写内容就由皮肤画;作者往部件里塞了自己的图形,这条规则即不命中 */
175
- [data-scope='checkbox'][data-part='indicator']:empty::before {
176
- content: '';
177
- display: inline-block;
178
- inline-size: var(--xh-icon-size, var(--xh-glyph-size-text));
179
- block-size: var(--xh-icon-size, var(--xh-glyph-size-text));
180
- vertical-align: var(--xh-glyph-baseline-shift);
181
- background-color: currentColor;
182
- -webkit-mask: var(--xh-glyph-mark-check) center / contain no-repeat;
183
- mask: var(--xh-glyph-mark-check) center / contain no-repeat;
184
- }
185
-
186
- [data-scope='checkbox'][data-part='indicator']:is([data-state='checked'], [data-state='indeterminate']) {
187
- opacity: 1;
188
- scale: 1;
189
- }
190
-
191
- /* 半选换一枚横杠字形盖住勾:aria-checked=mixed 在视觉上也得与「全选」分得开。
192
- 横杠与勾同走字形令牌,作者换掉标记时两态一起换;此前这条是手画的几何盒
193
- (60% × stroke-thick),同一页上会出现两种横杠 */
172
+ /* 半选横杠另有一支前景槽,缺省与勾同色 */
194
173
  [data-scope='checkbox'][data-part='indicator'][data-state='indeterminate'] {
195
- position: relative;
196
- color: transparent;
197
- }
198
-
199
- [data-scope='checkbox'][data-part='indicator'][data-state='indeterminate']::after {
200
- position: absolute;
201
- inline-size: var(--xh-icon-size, var(--xh-glyph-size-text));
202
- block-size: var(--xh-icon-size, var(--xh-glyph-size-text));
203
- background-color: var(--xh-checkbox-indicator-fg, var(--xh-_checkbox-on-accent));
204
- content: '';
205
- -webkit-mask: var(--xh-glyph-mark-minus) center / contain no-repeat;
206
- mask: var(--xh-glyph-mark-minus) center / contain no-repeat;
174
+ --xh-check-mark-fg: var(--xh-checkbox-indicator-fg, var(--xh-_checkbox-on-accent));
207
175
  }
208
176
 
209
- /* 禁用时横杠也走置灰色:它自己画底色,不从 root 的 color 继承 */
177
+ /* 禁用时横杠也走置灰色 */
210
178
  [data-scope='checkbox'][data-part='root'][data-disabled]
211
- [data-scope='checkbox'][data-part='indicator'][data-state='indeterminate']::after {
212
- background-color: var(--xh-checkbox-fg-disabled, var(--xh-fg-disabled));
179
+ [data-scope='checkbox'][data-part='indicator'][data-state='indeterminate'] {
180
+ --xh-check-mark-fg: var(--xh-checkbox-fg-disabled, var(--xh-fg-disabled));
213
181
  }
214
182
 
215
183
  /* —— 带文字的整行:<label> 包住控件与文字,与 checkbox-group 的条目、switch 的标签同一副样子 ——
216
- 文字是控件自己的文字,字号随 size 档取 --xh-control-font-*(§6.4 控件字号随档);
184
+ 文字是控件自己的文字,字号随 size 档取 --xh-control-font-*(控件字号随档);
217
185
  行高取正文档,长文字可以自然换行 */
218
186
  [data-scope='checkbox'][data-part='label'] {
219
187
  --xh-_checkbox-label-gap: var(--xh-control-gap-md);
@@ -238,7 +206,7 @@
238
206
  --xh-_checkbox-label-font-size: var(--xh-control-font-lg);
239
207
  }
240
208
 
241
- /* 禁用标签色统一 --xh-fg-subtle(§6.4) */
209
+ /* 禁用标签色统一 --xh-fg-subtle */
242
210
  [data-scope='checkbox'][data-part='label'][data-disabled] {
243
211
  color: var(--xh-checkbox-label-fg-disabled, var(--xh-fg-subtle));
244
212
  cursor: not-allowed;
@@ -259,18 +227,17 @@
259
227
  }
260
228
 
261
229
  @media (forced-colors: active) {
262
- /* 真实 border 保住盒,系统前景重新画出勾与半选横杠。 */
263
- [data-scope='checkbox'][data-part='indicator']:empty::before,
264
- [data-scope='checkbox'][data-part='indicator'][data-state='indeterminate']::after {
265
- background-color: CanvasText;
266
- }
267
-
230
+ /* 真实 border 保住盒,勾与半选横杠的系统前景由配方给;禁用写在 root 上,指示器自己不带,这里补置灰。
231
+ 盒就是 root 本身:悬停与按下时家族把它涂成 Highlight,勾跟着换 HighlightText */
268
232
  [data-scope='checkbox'][data-part='root'][data-disabled]
269
- [data-scope='checkbox'][data-part='indicator']:empty::before,
270
- [data-scope='checkbox'][data-part='root'][data-disabled]
271
- [data-scope='checkbox'][data-part='indicator'][data-state='indeterminate']::after {
233
+ [data-scope='checkbox'][data-part='indicator']:empty::before {
272
234
  background-color: GrayText;
273
235
  }
236
+
237
+ [data-scope='checkbox'][data-part='root']:not([data-disabled]):not([data-loading]):is(:hover, :active, [data-pressed])
238
+ [data-scope='checkbox'][data-part='indicator']:empty::before {
239
+ background-color: HighlightText;
240
+ }
274
241
  }
275
242
 
276
243
  @media print {