@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
package/css/cascader.css CHANGED
@@ -12,13 +12,16 @@
12
12
 
13
13
  /* 形态档只换触发框的描边与底色这三个槽,浮层与列不跟着变:
14
14
  变的是「这是个输入位」的表达方式,不是弹出内容的表达方式 */
15
- --xh-_cascader-border: var(--xh-border-default);
16
- --xh-_cascader-border-hover: var(--xh-border-strong);
15
+ --xh-_cascader-border: var(--xh-border-control);
16
+ --xh-_cascader-border-hover: var(--xh-border-control-hover);
17
17
  --xh-_cascader-bg: var(--xh-bg-canvas);
18
18
 
19
19
  /* 选中条目的文字色随语气走,没写 data-tone 时退回品牌强调色 */
20
20
  --xh-_cascader-selected-fg: var(--xh-_tone-fg, var(--xh-fg-brand-strong));
21
21
 
22
+ /* 展开路径的底色:随语气走淡底,没写 data-tone 时退回品牌淡底 */
23
+ --xh-_cascader-active-bg: var(--xh-_tone-subtle, var(--xh-bg-brand-subtle));
24
+
22
25
  display: inline-flex;
23
26
  flex-wrap: wrap;
24
27
  align-items: center;
@@ -34,15 +37,15 @@
34
37
  /* 形态只决定描边与底色怎么用;用哪族颜色由 data-tone 决定,没写 tone 就沿用原来的中性配色 */
35
38
  /* outline 就是缺省那一身:描边加画布底,写出来只为让三档并列可读 */
36
39
  [data-scope='cascader'][data-part='root'][data-variant='outline'] {
37
- --xh-_cascader-border: var(--xh-border-default);
38
- --xh-_cascader-border-hover: var(--xh-border-strong);
40
+ --xh-_cascader-border: var(--xh-border-control);
41
+ --xh-_cascader-border-hover: var(--xh-border-control-hover);
39
42
  --xh-_cascader-bg: var(--xh-bg-canvas);
40
43
  }
41
44
 
42
45
  /* subtle 是填充式:底色接过「这里能点」的表达,描边随之让位 */
43
46
  [data-scope='cascader'][data-part='root'][data-variant='subtle'] {
44
47
  --xh-_cascader-border: transparent;
45
- --xh-_cascader-border-hover: var(--xh-_tone-border, var(--xh-border-default));
48
+ --xh-_cascader-border-hover: var(--xh-_tone-border, var(--xh-border-control-hover));
46
49
  --xh-_cascader-bg: var(--xh-_tone-subtle, var(--xh-bg-subtle));
47
50
  }
48
51
 
@@ -118,9 +121,9 @@
118
121
  }
119
122
 
120
123
  /* trigger 是整个控件唯一的 Tab 停靠点(展开后停靠点才移进列里),落焦必须看得见。
121
- 语气落在环上:没写 data-tone 时 --xh-_tone 没被声明,退回原来的聚焦环色 */
124
+ 聚焦环恒用固定环色,不随语气走 */
122
125
  [data-scope='cascader'][data-part='trigger']:focus-visible {
123
- outline: var(--xh-ring-width) solid var(--xh-_tone, var(--xh-ring-focus));
126
+ outline: var(--xh-ring-width) solid var(--xh-ring-focus);
124
127
  outline-offset: var(--xh-ring-offset);
125
128
  }
126
129
 
@@ -171,6 +174,11 @@
171
174
  display: none;
172
175
  }
173
176
 
177
+ /* 没写内容就由皮肤画箭头;作者往部件里塞了自己的图形,这条规则即不命中 */
178
+ [data-scope='cascader'][data-part='indicator']:empty::before {
179
+ content: '▾';
180
+ }
181
+
174
182
  [data-scope='cascader'][data-part='indicator'][data-state='open'] {
175
183
  rotate: 180deg;
176
184
  }
@@ -216,7 +224,7 @@
216
224
  /* 清空按钮退出了 Tab 序列(tabindex=-1),正常操作走不到这里;
217
225
  留着是给程序化聚焦兜底,落焦时得看得见 */
218
226
  [data-scope='cascader'][data-part='clear-trigger']:focus-visible {
219
- outline: var(--xh-ring-width) solid var(--xh-_tone, var(--xh-ring-focus));
227
+ outline: var(--xh-ring-width) solid var(--xh-ring-focus);
220
228
  outline-offset: var(--xh-ring-offset);
221
229
  }
222
230
 
@@ -268,16 +276,24 @@
268
276
  }
269
277
 
270
278
  [data-scope='cascader'][data-part='content'][data-state='open'] {
279
+ /* 入场横移沿书写方向起始缘:位移量经私有槽供给关键帧,rtl 只翻符号 */
280
+ --xh-_cascader-slide: -0.25rem;
281
+
271
282
  animation: xh-cascader-in var(--xh-motion-duration-enter) var(--xh-motion-ease-enter);
272
283
  }
273
284
 
274
- /* 一列:自己定宽、自己滚。列与列之间用一条分隔线,比留白更能说明「这是下一级」 */
285
+ [dir='rtl'] [data-scope='cascader'][data-part='content'][data-state='open'] {
286
+ --xh-_cascader-slide: 0.25rem;
287
+ }
288
+
289
+ /* 一列:宽度由内容撑出、设下限防塌,高度定死——切换展开路径时浮层不上下跳动,
290
+ 溢出的条目在列内自己滚。列与列之间用一条分隔线,比留白更能说明「这是下一级」 */
275
291
  [data-scope='cascader'][data-part='column'] {
276
292
  display: flex;
277
293
  flex: none;
278
294
  flex-direction: column;
279
- inline-size: var(--xh-cascader-column-w, 11rem);
280
- max-block-size: var(--xh-cascader-column-max-h, 16rem);
295
+ min-inline-size: var(--xh-cascader-column-min-w, 7rem);
296
+ block-size: var(--xh-cascader-column-h, 11.25rem);
281
297
  padding-block: var(--xh-cascader-column-py, var(--xh-space-1));
282
298
  padding-inline: var(--xh-cascader-column-px, var(--xh-space-1));
283
299
  overflow-y: auto;
@@ -295,8 +311,14 @@
295
311
  border-inline-start: var(--xh-stroke-thin) solid var(--xh-cascader-column-divider, var(--xh-border-subtle));
296
312
  }
297
313
 
298
- /* 列不进 Tab 序列也不承载焦点,落焦不画环:高亮永远长在条目上 */
299
- [data-scope='cascader'][data-part='column']:focus-visible {
314
+ /* 焦点落在根列上只有一种情形:指针打开、无选中值、还没有任何条目当锚点。
315
+ 那一刻它认领着 Tab 位,环画在列内沿;有锚点时环长在条目上,列不再画 */
316
+ [data-scope='cascader'][data-part='column'][tabindex='0']:focus-visible {
317
+ outline: var(--xh-ring-width) solid var(--xh-ring-focus);
318
+ outline-offset: calc(-1 * var(--xh-ring-width));
319
+ }
320
+
321
+ [data-scope='cascader'][data-part='column']:not([tabindex='0']):focus-visible {
300
322
  outline: none;
301
323
  }
302
324
 
@@ -304,8 +326,9 @@
304
326
  display: flex;
305
327
  align-items: center;
306
328
  gap: var(--xh-cascader-row-gap, var(--xh-_cascader-gap));
307
- padding-block: var(--xh-cascader-row-py, var(--xh-space-1));
308
- padding-inline: var(--xh-cascader-row-px, var(--xh-control-px-sm));
329
+ max-inline-size: var(--xh-cascader-row-max-w, 25rem);
330
+ padding-block: var(--xh-cascader-row-py, var(--xh-space-1_5));
331
+ padding-inline: var(--xh-cascader-row-px, var(--xh-control-px-md));
309
332
  border-radius: var(--xh-cascader-row-radius, var(--xh-shape-control));
310
333
  color: var(--xh-cascader-row-fg, var(--xh-fg-default));
311
334
  font-size: var(--xh-cascader-row-font-size, var(--xh-_cascader-font-size));
@@ -314,6 +337,9 @@
314
337
  white-space: nowrap;
315
338
  cursor: pointer;
316
339
  user-select: none;
340
+ transition:
341
+ background var(--xh-motion-duration-micro) var(--xh-motion-ease-enter),
342
+ color var(--xh-motion-duration-micro) var(--xh-motion-ease-enter);
317
343
  }
318
344
 
319
345
  /* 条目常挂不卸载:不属于当前这一列的那些靠 hidden 收起。
@@ -322,14 +348,21 @@
322
348
  display: none;
323
349
  }
324
350
 
325
- /* 指针悬停、键盘高亮与展开路径共用同一张底:三者都是「此刻停在这儿」,
326
- data-highlighted 跟的是连接层记的焦点条目 */
327
- [data-scope='cascader'][data-part='item']:not([data-disabled]):is(:hover, [data-highlighted], [data-active]) {
328
- background: var(--xh-cascader-row-bg-highlight, var(--xh-bg-subtle-hover));
351
+ /* 底色分两档、靠色相分家:悬停与键盘锚点是中性灰轻档,展开路径是品牌淡底加粗。
352
+ hover 恒中性灰、不接语气槽——两档同色相的话路径就认不出来了。
353
+ 悬停展开把路径挪走后留在原地的锚点降回轻档,每列至多一条路径高亮 */
354
+ [data-scope='cascader'][data-part='item']:not([data-disabled]):is(:hover, [data-highlighted]) {
355
+ background: var(--xh-cascader-row-bg-hover, var(--xh-bg-subtle));
356
+ }
357
+
358
+ /* 必须排在轻档之后:锚点走到路径上时同特指度靠书写顺序压过轻档 */
359
+ [data-scope='cascader'][data-part='item']:not([data-disabled])[data-active] {
360
+ background: var(--xh-cascader-row-bg-active, var(--xh-_cascader-active-bg));
361
+ font-weight: var(--xh-cascader-row-active-font-weight, var(--xh-font-weight-semibold));
329
362
  }
330
363
 
331
- /* 选中只换文字色与字重,配合行尾的 ✓ 标记;底色整条通道留给悬停,
332
- 两者因此能同时看见 */
364
+ /* 选中只换文字色与字重,配合行尾的 ✓ 标记;底色强档归展开路径、轻档归悬停,
365
+ 三者因此能同时看见 */
333
366
  [data-scope='cascader'][data-part='item'][data-selected] {
334
367
  color: var(--xh-cascader-row-fg-selected, var(--xh-_cascader-selected-fg));
335
368
  font-weight: var(--xh-cascader-row-selected-font-weight, var(--xh-font-weight-medium));
@@ -337,7 +370,7 @@
337
370
 
338
371
  /* 条目自己就是 option,环直接画在它身上;往内收,行是撑满列宽的,环画在外沿会被裁掉 */
339
372
  [data-scope='cascader'][data-part='item']:focus-visible {
340
- outline: var(--xh-ring-width) solid var(--xh-_tone, var(--xh-ring-focus));
373
+ outline: var(--xh-ring-width) solid var(--xh-ring-focus);
341
374
  outline-offset: calc(-1 * var(--xh-ring-width));
342
375
  }
343
376
 
@@ -348,6 +381,28 @@
348
381
  cursor: not-allowed;
349
382
  }
350
383
 
384
+ /* 分支条目行尾画右向小箭头:不点开也看得出还有下一级。
385
+ 全边框描好后抹掉块末与行首两边,剩下的直角旋成箭头;位置由 item-text 的 flex:1 顶到行尾 */
386
+ [data-scope='cascader'][data-part='item'][data-branch]::after {
387
+ content: '';
388
+ flex: none;
389
+ inline-size: var(--xh-cascader-branch-arrow-size, var(--xh-space-1_5));
390
+ block-size: var(--xh-cascader-branch-arrow-size, var(--xh-space-1_5));
391
+ border: var(--xh-glyph-stroke-light) solid var(--xh-cascader-branch-arrow-fg, var(--xh-fg-subtle));
392
+ border-block-end: 0;
393
+ border-inline-start: 0;
394
+ rotate: 45deg;
395
+ }
396
+
397
+ /* rtl 下剩下的是块首与行末(物理左上)两边,反向旋 45 度才指向行进方向 */
398
+ [dir='rtl'] [data-scope='cascader'][data-part='item'][data-branch]::after {
399
+ rotate: -45deg;
400
+ }
401
+
402
+ [data-scope='cascader'][data-part='item'][data-branch][data-disabled]::after {
403
+ border-color: var(--xh-fg-disabled);
404
+ }
405
+
351
406
  [data-scope='cascader'][data-part='item-text'] {
352
407
  flex: 1;
353
408
  min-inline-size: 0;
@@ -362,7 +417,7 @@
362
417
  flex: none;
363
418
  align-items: center;
364
419
  justify-content: center;
365
- inline-size: var(--xh-cascader-indicator-size, var(--xh-control-indicator-size));
420
+ inline-size: var(--xh-cascader-item-indicator-size, var(--xh-control-indicator-size));
366
421
  color: var(--xh-cascader-item-indicator-fg, var(--xh-_tone, var(--xh-bg-brand)));
367
422
  visibility: hidden;
368
423
  }
@@ -371,22 +426,142 @@
371
426
  display: none;
372
427
  }
373
428
 
429
+ /* 没写内容就由皮肤画勾;作者往部件里塞了自己的图形,这条规则即不命中 */
430
+ [data-scope='cascader'][data-part='item-indicator']:empty::before {
431
+ content: '✓';
432
+ }
433
+
374
434
  [data-scope='cascader'][data-part='item-indicator'][data-selected] {
375
435
  visibility: visible;
376
436
  }
377
437
 
438
+ /* 级联勾选的半选态只在皮肤自绘(:empty)时露面画横杠:
439
+ 作者塞了自己的选中图形时,半选放出来会顶着一个语义相反的勾,表达交还作者 */
440
+ [data-scope='cascader'][data-part='item-indicator'][data-indeterminate]:empty {
441
+ visibility: visible;
442
+ }
443
+
444
+ [data-scope='cascader'][data-part='item-indicator'][data-indeterminate]:not([data-selected]):empty::before {
445
+ content: '−';
446
+ font-weight: var(--xh-font-weight-semibold);
447
+ }
448
+
378
449
  [data-scope='cascader'][data-part='item-indicator'][data-disabled] {
379
450
  color: var(--xh-fg-disabled);
380
451
  }
452
+
453
+ /* —— 搜索视图:输入框横占整行排在列上方,候选列表替换列视图 —— */
454
+ [data-scope='cascader'][data-part='content']:has([data-part='input']:not([hidden])) {
455
+ flex-wrap: wrap;
456
+ }
457
+
458
+ [data-scope='cascader'][data-part='input'] {
459
+ flex-basis: 100%;
460
+ min-inline-size: 0;
461
+ padding-block: var(--xh-cascader-input-py, var(--xh-space-2));
462
+ padding-inline: var(--xh-cascader-input-px, var(--xh-control-px-md));
463
+ border: none;
464
+ border-block-end: var(--xh-stroke-thin) solid var(--xh-cascader-content-border, var(--xh-border-default));
465
+ border-start-start-radius: inherit;
466
+ border-start-end-radius: inherit;
467
+ background: none;
468
+ color: inherit;
469
+ font-family: inherit;
470
+ font-size: var(--xh-cascader-input-font-size, var(--xh-_cascader-font-size));
471
+ line-height: var(--xh-leading-normal);
472
+ }
473
+
474
+ [data-scope='cascader'][data-part='input']:focus-visible {
475
+ outline: none;
476
+ }
477
+
478
+ [data-scope='cascader'][data-part='input'][hidden] {
479
+ display: none;
480
+ }
481
+
482
+ [data-scope='cascader'][data-part='search-list'] {
483
+ display: flex;
484
+ flex-basis: 100%;
485
+ flex-direction: column;
486
+ max-block-size: var(--xh-cascader-search-max-h, 11.25rem);
487
+ padding: var(--xh-cascader-search-p, var(--xh-space-1));
488
+ overflow-y: auto;
489
+ }
490
+
491
+ [data-scope='cascader'][data-part='search-list'][hidden] {
492
+ display: none;
493
+ }
494
+
495
+ /* 无候选时列表自身不占位,空态交给 empty 部件出面 */
496
+ [data-scope='cascader'][data-part='search-list'][data-empty] {
497
+ padding: 0;
498
+ }
499
+
500
+ /* 搜索视图里列整体让位 */
501
+ [data-scope='cascader'][data-part='content'][data-searching] [data-part='column'] {
502
+ display: none;
503
+ }
504
+
505
+ /* 候选与列内条目同一套行度量,虚拟高亮与悬停同用轻档 */
506
+ [data-scope='cascader'][data-part='search-item'] {
507
+ padding-block: var(--xh-cascader-row-py, var(--xh-space-1_5));
508
+ padding-inline: var(--xh-cascader-row-px, var(--xh-control-px-md));
509
+ overflow: hidden;
510
+ border-radius: var(--xh-cascader-row-radius, var(--xh-shape-control));
511
+ color: var(--xh-cascader-row-fg, var(--xh-fg-default));
512
+ font-size: var(--xh-cascader-row-font-size, var(--xh-_cascader-font-size));
513
+ line-height: var(--xh-cascader-row-leading, var(--xh-leading-normal));
514
+ text-overflow: ellipsis;
515
+ white-space: nowrap;
516
+ cursor: pointer;
517
+ user-select: none;
518
+ transition: background var(--xh-motion-duration-micro) var(--xh-motion-ease-enter);
519
+ }
520
+
521
+ [data-scope='cascader'][data-part='search-item']:not([data-disabled]):is(:hover, [data-highlighted]) {
522
+ background: var(--xh-cascader-row-bg-hover, var(--xh-bg-subtle));
523
+ }
524
+
525
+ [data-scope='cascader'][data-part='search-item'][data-disabled] {
526
+ color: var(--xh-fg-disabled);
527
+ cursor: not-allowed;
528
+ }
529
+
530
+ [data-scope='cascader'][data-part='search-item'][hidden] {
531
+ display: none;
532
+ }
533
+
534
+ /* —— 空态:当前视图没有条目时由 empty 部件出面,文案由适配器或作者供给,皮肤只管排版 —— */
535
+ /* 根列没有条目时那条空列让位,占位面接管整个浮层 */
536
+ [data-scope='cascader'][data-part='content'][data-empty] [data-part='column'] {
537
+ display: none;
538
+ }
539
+
540
+ [data-scope='cascader'][data-part='empty'] {
541
+ display: flex;
542
+ flex: 1 1 100%;
543
+ align-items: center;
544
+ justify-content: center;
545
+ min-inline-size: var(--xh-cascader-column-min-w, 7rem);
546
+ min-block-size: var(--xh-cascader-empty-min-h, 5rem);
547
+ padding: var(--xh-cascader-empty-p, var(--xh-space-3));
548
+ color: var(--xh-cascader-empty-fg, var(--xh-fg-subtle));
549
+ font-size: var(--xh-cascader-row-font-size, var(--xh-_cascader-font-size));
550
+ }
551
+
552
+ [data-scope='cascader'][data-part='empty'][hidden] {
553
+ display: none;
554
+ }
381
555
  }
382
556
 
383
557
  @layer xihan.motion {
384
558
  /* 浮层是横向长出来的:淡入之外再沿书写方向起始缘推一小段,观感上像列被「拉开」。
559
+ 位移量从 content 上的私有槽取,rtl 侧翻符号后同一份关键帧两个方向都对。
385
560
  关键帧写在本文件里、名字带组件前缀,不动公共的那一份 */
386
561
  @keyframes xh-cascader-in {
387
562
  from {
388
563
  opacity: 0;
389
- translate: -0.25rem 0;
564
+ translate: var(--xh-_cascader-slide, -0.25rem) 0;
390
565
  }
391
566
 
392
567
  to {
@@ -70,19 +70,19 @@
70
70
  /* 全选格与条目格共用同一套盒子,并成一条规则写:分开写迟早只改到一半,两个方框就此走形。
71
71
  尺寸与选中态照 checkbox 的 root 搬,同一份视觉语言在单体与集合里必须一致。
72
72
  trigger 那格没有对应的角色节点(anatomy 到 trigger 为止),只能由伪元素补出来 */
73
- [data-scope='checkbox-group'][data-part='item-control'],
73
+ [data-scope='checkbox-group'][data-part='indicator'],
74
74
  [data-scope='checkbox-group'][data-part='trigger']::before {
75
75
  display: inline-flex;
76
76
  flex: none;
77
77
  align-items: center;
78
78
  justify-content: center;
79
- inline-size: var(--xh-checkbox-group-control-size, 16px);
80
- block-size: var(--xh-checkbox-group-control-size, 16px);
81
- border: var(--xh-stroke-thin) solid var(--xh-checkbox-group-control-border, var(--xh-border-default));
82
- border-radius: var(--xh-checkbox-group-control-radius, var(--xh-radius-sm));
83
- background: var(--xh-checkbox-group-control-bg, var(--xh-bg-canvas));
84
- color: var(--xh-checkbox-group-control-fg, var(--xh-fg-on-brand));
85
- font-size: var(--xh-checkbox-group-control-font-size, 12px);
79
+ inline-size: var(--xh-checkbox-group-indicator-size, 16px);
80
+ block-size: var(--xh-checkbox-group-indicator-size, 16px);
81
+ border: var(--xh-stroke-thin) solid var(--xh-checkbox-group-indicator-border, var(--xh-border-control));
82
+ border-radius: var(--xh-checkbox-group-indicator-radius, var(--xh-radius-sm));
83
+ background: var(--xh-checkbox-group-indicator-bg, var(--xh-bg-canvas));
84
+ color: var(--xh-checkbox-group-indicator-fg, var(--xh-fg-on-brand));
85
+ font-size: var(--xh-checkbox-group-indicator-font-size, 12px);
86
86
  line-height: var(--xh-leading-none);
87
87
  transition:
88
88
  background var(--xh-motion-duration-micro) var(--xh-motion-ease-enter),
@@ -90,7 +90,7 @@
90
90
  }
91
91
 
92
92
  /* content 只能给伪元素,绝不能并进上面那条:content 落在普通元素上会顶掉它的全部子节点,
93
- item-control 里作者写的图标就此消失 */
93
+ indicator 里作者写的图标就此消失 */
94
94
  [data-scope='checkbox-group'][data-part='trigger']::before {
95
95
  content: '';
96
96
  }
@@ -98,19 +98,19 @@
98
98
  /* 悬停只加深空方框的描边。已选中的那一格必须排除:这条选择器的权重高过下面那条填色规则,
99
99
  不排除就会在悬停时把 brand 描边换回灰色,方框看起来"缺了一圈" */
100
100
  [data-scope='checkbox-group'][data-part='item']:not([data-disabled]):hover
101
- [data-scope='checkbox-group'][data-part='item-control']:not([data-state='checked']) {
102
- border-color: var(--xh-checkbox-group-control-border-hover, var(--xh-border-strong));
101
+ [data-scope='checkbox-group'][data-part='indicator']:not([data-state='checked']) {
102
+ border-color: var(--xh-checkbox-group-indicator-border-hover, var(--xh-border-control-hover));
103
103
  }
104
104
 
105
105
  /* 选中即填色:条目是二态,全选格三态里 all 与 some 都算"有值",共用同一副填色 */
106
- [data-scope='checkbox-group'][data-part='item-control'][data-state='checked'],
106
+ [data-scope='checkbox-group'][data-part='indicator'][data-state='checked'],
107
107
  [data-scope='checkbox-group'][data-part='trigger']:is([data-state='all'], [data-state='some'])::before {
108
- border-color: var(--xh-checkbox-group-control-border-checked, var(--xh-bg-brand));
109
- background: var(--xh-checkbox-group-control-bg-checked, var(--xh-bg-brand));
108
+ border-color: var(--xh-checkbox-group-indicator-border-checked, var(--xh-bg-brand));
109
+ background: var(--xh-checkbox-group-indicator-bg-checked, var(--xh-bg-brand));
110
110
  }
111
111
 
112
- /* 勾号由皮肤补,作者不必自己往 item-control 里塞字符 */
113
- [data-scope='checkbox-group'][data-part='item-control'][data-state='checked']::before {
112
+ /* 勾号由皮肤补,作者不必自己往 indicator 里塞字符 */
113
+ [data-scope='checkbox-group'][data-part='indicator'][data-state='checked']::before {
114
114
  content: '✓';
115
115
  }
116
116
 
@@ -126,8 +126,8 @@
126
126
 
127
127
  /* 校验失败标在每个方框上:root 上的 data-invalid 是唯一出处,条目自己不带这个属性 */
128
128
  [data-scope='checkbox-group'][data-part='root'][data-invalid]
129
- [data-scope='checkbox-group'][data-part='item-control'] {
130
- border-color: var(--xh-checkbox-group-control-border-invalid, var(--xh-color-danger-500));
129
+ [data-scope='checkbox-group'][data-part='indicator'] {
130
+ border-color: var(--xh-checkbox-group-indicator-border-invalid, var(--xh-color-danger-500));
131
131
  }
132
132
 
133
133
  [data-scope='checkbox-group'][data-part='item-text'] {
@@ -170,7 +170,7 @@
170
170
  /* 表单出口:连接层已经把整套视觉隐藏写进内联 style(absolute + 1px + clip-path),
171
171
  这里绝不能再补 display:none——那份输入必须留在布局里,原生校验提示要有处可贴。
172
172
  只补一条不吃指针,免得它挡住条目的点击 */
173
- [data-scope='checkbox-group'][data-part='item-hidden-input'] {
173
+ [data-scope='checkbox-group'][data-part='hidden-input'] {
174
174
  pointer-events: none;
175
175
  }
176
176
 
@@ -178,7 +178,7 @@
178
178
  不补的话作者给节点加 hidden 后它照样显示 */
179
179
  [data-scope='checkbox-group'][data-part='root'][hidden],
180
180
  [data-scope='checkbox-group'][data-part='item'][hidden],
181
- [data-scope='checkbox-group'][data-part='item-control'][hidden],
181
+ [data-scope='checkbox-group'][data-part='indicator'][hidden],
182
182
  [data-scope='checkbox-group'][data-part='trigger'][hidden] {
183
183
  display: none;
184
184
  }
package/css/checkbox.css CHANGED
@@ -18,7 +18,7 @@
18
18
  inline-size: var(--xh-_checkbox-box);
19
19
  block-size: var(--xh-_checkbox-box);
20
20
  padding: 0;
21
- border: 1px solid var(--xh-checkbox-border, var(--xh-border-default));
21
+ border: 1px solid var(--xh-checkbox-border, var(--xh-border-control));
22
22
  border-radius: var(--xh-radius-sm);
23
23
  background: var(--xh-checkbox-bg, var(--xh-bg-canvas));
24
24
  color: var(--xh-checkbox-fg, var(--xh-_checkbox-on-accent));
package/css/clipboard.css CHANGED
@@ -38,7 +38,7 @@
38
38
  block-size: var(--xh-clipboard-input-h, var(--xh-control-h-md));
39
39
  padding-inline: var(--xh-clipboard-input-px, var(--xh-control-px-md));
40
40
  padding-block: 0;
41
- border: var(--xh-stroke-thin) solid var(--xh-clipboard-input-border, var(--xh-border-default));
41
+ border: var(--xh-stroke-thin) solid var(--xh-clipboard-input-border, var(--xh-border-control));
42
42
  border-radius: var(--xh-clipboard-input-radius, var(--xh-shape-control));
43
43
  /* 只读态压低底色表示"改不动",但仍可聚焦、可选中复制 */
44
44
  background: var(--xh-clipboard-input-bg, var(--xh-bg-subtle));
@@ -66,7 +66,7 @@
66
66
  block-size: var(--xh-clipboard-trigger-h, var(--xh-control-h-md));
67
67
  padding-inline: var(--xh-clipboard-trigger-px, var(--xh-control-px-md));
68
68
  padding-block: 0;
69
- border: var(--xh-stroke-thin) solid var(--xh-clipboard-trigger-border, var(--xh-border-default));
69
+ border: var(--xh-stroke-thin) solid var(--xh-clipboard-trigger-border, var(--xh-border-control));
70
70
  border-radius: var(--xh-clipboard-trigger-radius, var(--xh-shape-control));
71
71
  background: var(--xh-clipboard-trigger-bg, var(--xh-bg-canvas));
72
72
  color: var(--xh-clipboard-trigger-fg, var(--xh-fg-default));
@@ -89,7 +89,7 @@
89
89
  }
90
90
 
91
91
  [data-scope='clipboard'][data-part='trigger']:hover {
92
- border-color: var(--xh-clipboard-trigger-border-hover, var(--xh-border-strong));
92
+ border-color: var(--xh-clipboard-trigger-border-hover, var(--xh-border-control-hover));
93
93
  background: var(--xh-clipboard-trigger-bg-hover, var(--xh-bg-subtle-hover));
94
94
  }
95
95
 
@@ -43,7 +43,7 @@
43
43
  min-inline-size: var(--xh-color-picker-trigger-min-w, 9rem);
44
44
  block-size: var(--xh-color-picker-trigger-h, var(--xh-control-h-md));
45
45
  padding-inline: var(--xh-color-picker-trigger-px, var(--xh-control-px-md));
46
- border: var(--xh-stroke-thin) solid var(--xh-color-picker-trigger-border, var(--xh-border-default));
46
+ border: var(--xh-stroke-thin) solid var(--xh-color-picker-trigger-border, var(--xh-border-control));
47
47
  border-radius: var(--xh-color-picker-trigger-radius, var(--xh-shape-control));
48
48
  background: var(--xh-color-picker-trigger-bg, var(--xh-bg-canvas));
49
49
  color: var(--xh-color-picker-trigger-fg, var(--xh-fg-default));
@@ -55,7 +55,7 @@
55
55
  }
56
56
 
57
57
  [data-scope='color-picker'][data-part='trigger']:hover:not(:disabled) {
58
- border-color: var(--xh-color-picker-trigger-border-hover, var(--xh-border-strong));
58
+ border-color: var(--xh-color-picker-trigger-border-hover, var(--xh-border-control-hover));
59
59
  }
60
60
 
61
61
  [data-scope='color-picker'][data-part='trigger']:focus-visible {
@@ -301,7 +301,7 @@
301
301
  min-inline-size: 0;
302
302
  block-size: var(--xh-color-picker-input-h, var(--xh-control-h-sm));
303
303
  padding-inline: var(--xh-color-picker-input-px, var(--xh-control-px-sm));
304
- border: var(--xh-stroke-thin) solid var(--xh-color-picker-input-border, var(--xh-border-default));
304
+ border: var(--xh-stroke-thin) solid var(--xh-color-picker-input-border, var(--xh-border-control));
305
305
  border-radius: var(--xh-color-picker-input-radius, var(--xh-shape-control));
306
306
  background: var(--xh-color-picker-input-bg, var(--xh-bg-canvas));
307
307
  color: inherit;
@@ -341,7 +341,7 @@
341
341
  inline-size: var(--xh-color-picker-action-size, 1.75rem);
342
342
  block-size: var(--xh-color-picker-action-size, 1.75rem);
343
343
  padding: 0;
344
- border: var(--xh-stroke-thin) solid var(--xh-color-picker-action-border, var(--xh-border-default));
344
+ border: var(--xh-stroke-thin) solid var(--xh-color-picker-action-border, var(--xh-border-control));
345
345
  border-radius: var(--xh-color-picker-action-radius, var(--xh-shape-control));
346
346
  background: var(--xh-color-picker-action-bg, transparent);
347
347
  color: var(--xh-color-picker-action-fg, var(--xh-fg-muted));
@@ -385,7 +385,7 @@
385
385
  inline-size: var(--xh-color-picker-swatch-item-size, 1.25rem);
386
386
  block-size: var(--xh-color-picker-swatch-item-size, 1.25rem);
387
387
  padding: 0;
388
- border: var(--xh-stroke-thin) solid var(--xh-color-picker-swatch-border, var(--xh-border-default));
388
+ border: var(--xh-stroke-thin) solid var(--xh-color-picker-swatch-border, var(--xh-border-control));
389
389
  border-radius: var(--xh-color-picker-swatch-radius, var(--xh-radius-sm));
390
390
  cursor: pointer;
391
391
  }
@@ -421,4 +421,20 @@
421
421
  [data-scope='color-picker'][data-part='swatch-group'][hidden] {
422
422
  display: none;
423
423
  }
424
+
425
+ /* 连接层把它写成 type=hidden,UA 自己就不渲染;这里的视觉隐藏是给元素升级前那一瞬兜底
426
+ (作者手写的是一个普通 input,升级完成前它是可见的文本框)。
427
+ 刻意不写 display:写了反而会盖掉 UA 对 type=hidden 的收起,把它显出来 */
428
+ [data-scope='color-picker'][data-part='hidden-input'] {
429
+ position: absolute;
430
+ inline-size: 1px;
431
+ block-size: 1px;
432
+ padding: 0;
433
+ margin: -1px;
434
+ border: 0;
435
+ overflow: hidden;
436
+ clip-path: inset(50%);
437
+ white-space: nowrap;
438
+ pointer-events: none;
439
+ }
424
440
  }
package/css/combobox.css CHANGED
@@ -10,14 +10,13 @@
10
10
 
11
11
  /* 形态档只换这三个槽:缺省即 outline(描边 + 画布底) */
12
12
  --xh-_combobox-control-bg: var(--xh-bg-canvas);
13
- --xh-_combobox-control-border: var(--xh-border-default);
14
- --xh-_combobox-control-border-hover: var(--xh-border-strong);
13
+ --xh-_combobox-control-border: var(--xh-border-control);
14
+ --xh-_combobox-control-border-hover: var(--xh-border-control-hover);
15
15
 
16
- /* 强调色随语气走,只落在聚焦与选中上,正文文字色不动。
17
- 没写 data-tone 时 --xh-_tone 没被声明,三处都退回原来的取值 */
16
+ /* 聚焦环恒用固定环色;强调色随语气走,只落在勾选标记与选中文字上,正文文字色不动。
17
+ 没写 data-tone 时 --xh-_tone 没被声明,两处都退回原来的取值 */
18
18
  --xh-_combobox-ring: var(--xh-ring-focus);
19
19
  --xh-_combobox-accent: var(--xh-_tone, var(--xh-bg-brand));
20
- --xh-_combobox-item-highlight-bg: var(--xh-_tone-subtle-hover, var(--xh-bg-subtle-hover));
21
20
  --xh-_combobox-item-selected-fg: var(--xh-_tone-fg, var(--xh-fg-brand-strong));
22
21
 
23
22
  display: inline-flex;
@@ -53,21 +52,21 @@
53
52
  形态只决定描边与底色怎么用,用哪族颜色由 data-tone 决定 */
54
53
  [data-scope='combobox'][data-part='root'][data-variant='outline'] {
55
54
  --xh-_combobox-control-bg: var(--xh-bg-canvas);
56
- --xh-_combobox-control-border: var(--xh-border-default);
57
- --xh-_combobox-control-border-hover: var(--xh-border-strong);
55
+ --xh-_combobox-control-border: var(--xh-border-control);
56
+ --xh-_combobox-control-border-hover: var(--xh-border-control-hover);
58
57
  }
59
58
 
60
59
  /* 填充式:底色顶替描边,悬停时才浮出一道淡边 */
61
60
  [data-scope='combobox'][data-part='root'][data-variant='subtle'] {
62
61
  --xh-_combobox-control-bg: var(--xh-_tone-subtle, var(--xh-bg-subtle));
63
62
  --xh-_combobox-control-border: transparent;
64
- --xh-_combobox-control-border-hover: var(--xh-_tone-border, var(--xh-border-default));
63
+ --xh-_combobox-control-border-hover: var(--xh-_tone-border, var(--xh-border-control-hover));
65
64
  }
66
65
 
67
66
  [data-scope='combobox'][data-part='root'][data-variant='ghost'] {
68
67
  --xh-_combobox-control-bg: transparent;
69
68
  --xh-_combobox-control-border: transparent;
70
- --xh-_combobox-control-border-hover: var(--xh-_tone-border, var(--xh-border-default));
69
+ --xh-_combobox-control-border-hover: var(--xh-_tone-border, var(--xh-border-control-hover));
71
70
  }
72
71
 
73
72
  [data-scope='combobox'][data-part='label'] {
@@ -205,11 +204,11 @@
205
204
  display: none;
206
205
  }
207
206
 
208
- /* 展开时箭头翻个面,指向与列表的去向一致;transition 要重写全份,只补一条会覆盖掉上面那条 */
209
- [data-scope='combobox'][data-part='trigger'] {
210
- transition:
211
- background var(--xh-motion-duration-micro) var(--xh-motion-ease-enter),
212
- rotate var(--xh-motion-duration-micro) var(--xh-motion-ease-enter);
207
+ /* 展开时箭头翻个面,指向与列表的去向一致。转的是字形或作者塞的图形,不转按钮本体:
208
+ 按钮自带悬停底色,整个按钮转会带着底色一起转 */
209
+ [data-scope='combobox'][data-part='trigger']:empty::before,
210
+ [data-scope='combobox'][data-part='trigger'] > * {
211
+ transition: rotate var(--xh-motion-duration-micro) var(--xh-motion-ease-enter);
213
212
  }
214
213
 
215
214
  /* 没写内容就由皮肤画箭头;作者往部件里塞了自己的图形,这条规则即不命中 */
@@ -222,7 +221,8 @@
222
221
  content: '✕';
223
222
  }
224
223
 
225
- [data-scope='combobox'][data-part='trigger'][data-state='open'] {
224
+ [data-scope='combobox'][data-part='trigger'][data-state='open']:empty::before,
225
+ [data-scope='combobox'][data-part='trigger'][data-state='open'] > * {
226
226
  rotate: 180deg;
227
227
  }
228
228
 
@@ -315,7 +315,7 @@
315
315
  [data-scope='combobox'][data-part='item-group-label'] {
316
316
  display: block;
317
317
  padding-block: var(--xh-combobox-group-label-py, var(--xh-space-1));
318
- padding-inline: var(--xh-combobox-group-label-px, var(--xh-control-px-sm));
318
+ padding-inline: var(--xh-combobox-group-label-px, var(--xh-control-px-md));
319
319
  color: var(--xh-combobox-group-label-fg, var(--xh-fg-subtle));
320
320
  font-size: var(--xh-combobox-group-label-font-size, var(--xh-font-size-xs));
321
321
  font-weight: var(--xh-combobox-group-label-font-weight, var(--xh-font-weight-medium));
@@ -331,8 +331,8 @@
331
331
  display: flex;
332
332
  align-items: center;
333
333
  gap: var(--xh-combobox-item-gap, var(--xh-_combobox-gap));
334
- padding-block: var(--xh-combobox-item-py, var(--xh-space-1));
335
- padding-inline: var(--xh-combobox-item-px, var(--xh-control-px-sm));
334
+ padding-block: var(--xh-combobox-item-py, var(--xh-space-1_5));
335
+ padding-inline: var(--xh-combobox-item-px, var(--xh-control-px-md));
336
336
  border-radius: var(--xh-combobox-item-radius, var(--xh-shape-control));
337
337
  color: var(--xh-combobox-item-fg, var(--xh-fg-default));
338
338
  font-size: var(--xh-combobox-item-font-size, var(--xh-_combobox-font-size));
@@ -341,6 +341,9 @@
341
341
  white-space: nowrap;
342
342
  cursor: pointer;
343
343
  user-select: none;
344
+ transition:
345
+ background var(--xh-motion-duration-micro) var(--xh-motion-ease-enter),
346
+ color var(--xh-motion-duration-micro) var(--xh-motion-ease-enter);
344
347
  }
345
348
 
346
349
  /* 候选按需收起(作者自己藏掉某几条)时要让位,有 display 就得补这条 */
@@ -348,10 +351,10 @@
348
351
  display: none;
349
352
  }
350
353
 
351
- /* 只认 data-highlighted,不写 :hover:指针划过时连接层已经把高亮搬过来了,
354
+ /* 键盘锚点走中性灰轻档。只认 data-highlighted,不写 :hover:指针划过时连接层已经把高亮搬过来了,
352
355
  两套底色各画各的会出现"鼠标停在 A 上、回车提交的却是 B" */
353
356
  [data-scope='combobox'][data-part='item'][data-highlighted]:not([data-disabled]) {
354
- background: var(--xh-combobox-item-bg-highlight, var(--xh-_combobox-item-highlight-bg));
357
+ background: var(--xh-combobox-item-bg-hover, var(--xh-bg-subtle));
355
358
  }
356
359
 
357
360
  /* 选中只换文字色与字重,配合行尾的 ✓ 标记;底色整条通道留给高亮,