@xihan-ui/styles 1.0.0-alpha.3 → 1.1.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 (99) hide show
  1. package/CHANGELOG.md +1922 -0
  2. package/README.md +1 -1
  3. package/css/accordion.css +25 -2
  4. package/css/alert.css +13 -9
  5. package/css/anchor.css +1 -1
  6. package/css/avatar-group.css +5 -1
  7. package/css/avatar.css +6 -0
  8. package/css/back-top.css +6 -0
  9. package/css/badge.css +94 -36
  10. package/css/breadcrumb.css +1 -1
  11. package/css/button-group.css +4 -0
  12. package/css/button.css +6 -0
  13. package/css/calendar.css +39 -13
  14. package/css/card.css +15 -6
  15. package/css/cascader.css +29 -23
  16. package/css/checkbox-group.css +38 -10
  17. package/css/checkbox.css +21 -10
  18. package/css/collapsible.css +7 -1
  19. package/css/color-picker.css +22 -2
  20. package/css/combobox.css +18 -7
  21. package/css/context-menu.css +17 -6
  22. package/css/date-field.css +2 -2
  23. package/css/date-picker.css +27 -17
  24. package/css/descriptions.css +9 -3
  25. package/css/dialog.css +7 -1
  26. package/css/drawer.css +15 -5
  27. package/css/dynamic-input.css +7 -0
  28. package/css/ellipsis.css +6 -0
  29. package/css/empty-state.css +16 -6
  30. package/css/field.css +7 -0
  31. package/css/file-upload.css +1 -1
  32. package/css/flex.css +13 -7
  33. package/css/float-button.css +7 -0
  34. package/css/floating-panel.css +6 -0
  35. package/css/grid.css +11 -5
  36. package/css/heatmap.css +3 -2
  37. package/css/highlight.css +1 -1
  38. package/css/hotkeys.css +1 -1
  39. package/css/hover-card.css +3 -0
  40. package/css/image-cropper.css +4 -2
  41. package/css/image-viewer.css +18 -5
  42. package/css/json-viewer.css +34 -1
  43. package/css/layout.css +15 -7
  44. package/css/list.css +14 -5
  45. package/css/listbox.css +4 -2
  46. package/css/loading-bar.css +5 -4
  47. package/css/log.css +6 -2
  48. package/css/masonry.css +5 -5
  49. package/css/mention.css +13 -3
  50. package/css/menu.css +16 -5
  51. package/css/menubar.css +14 -6
  52. package/css/navigation-menu.css +2 -2
  53. package/css/notification.css +377 -0
  54. package/css/number-field.css +9 -3
  55. package/css/page-header.css +7 -0
  56. package/css/pagination.css +158 -1
  57. package/css/password-input.css +4 -4
  58. package/css/pin-input.css +2 -2
  59. package/css/popconfirm.css +9 -2
  60. package/css/popover.css +3 -0
  61. package/css/popselect.css +24 -4
  62. package/css/progress.css +8 -2
  63. package/css/radio-group.css +17 -6
  64. package/css/rating.css +2 -2
  65. package/css/resizable.css +113 -0
  66. package/css/result.css +15 -5
  67. package/css/scrollbar.css +3 -0
  68. package/css/segmented.css +1 -1
  69. package/css/select.css +25 -7
  70. package/css/side-nav.css +16 -5
  71. package/css/slider.css +4 -2
  72. package/css/sortable.css +103 -0
  73. package/css/space.css +6 -6
  74. package/css/steps.css +6 -6
  75. package/css/switch.css +9 -2
  76. package/css/table.css +309 -10
  77. package/css/tabs.css +148 -1
  78. package/css/tag.css +3 -1
  79. package/css/tags-input.css +3 -3
  80. package/css/text-field.css +3 -3
  81. package/css/thread.css +10 -2
  82. package/css/time-field.css +2 -2
  83. package/css/time-picker.css +6 -6
  84. package/css/timeline.css +7 -7
  85. package/css/toast.css +103 -53
  86. package/css/toggle-group.css +30 -4
  87. package/css/toggle.css +6 -0
  88. package/css/tone.css +47 -17
  89. package/css/tooltip.css +7 -1
  90. package/css/tour.css +9 -3
  91. package/css/transfer.css +38 -12
  92. package/css/tree-select.css +30 -5
  93. package/css/tree.css +175 -4
  94. package/css/typography.css +1 -1
  95. package/css/undefined.css +1 -0
  96. package/index.css +3 -1
  97. package/index.unlayered.css +2650 -634
  98. package/package.json +5 -3
  99. package/css/toaster.css +0 -74
package/css/popselect.css CHANGED
@@ -37,6 +37,9 @@
37
37
  引擎没算(尚未落位 / 无引擎 / 贴边归零)时退回自己那档静态上限 */
38
38
  --xh-_popselect-available-h: 100vh;
39
39
 
40
+ /* 候选列表的自绘条浮在内容之上:轨道不上底色,实色轨道会在列表右缘糊一条竖灰带 */
41
+ --xh-scrollbar-track-bg: transparent;
42
+
40
43
  position: fixed;
41
44
  z-index: var(--xh-popselect-layer, var(--xh-layer-popover));
42
45
  /* 空壳不吃指针,交互只发生在 content 上 */
@@ -53,8 +56,10 @@
53
56
  /* 尺寸档只换这四个私有槽,触发器与条目都从这两处继承它们,换档不必给每个部件各写一条选择器 */
54
57
  --xh-_popselect-h: var(--xh-control-h-md);
55
58
  --xh-_popselect-px: var(--xh-control-px-md);
59
+ --xh-_popselect-item-py: var(--xh-list-option-py-md);
60
+ --xh-_popselect-item-px: var(--xh-control-px-md);
56
61
  --xh-_popselect-gap: var(--xh-control-gap-md);
57
- --xh-_popselect-font-size: var(--xh-text-body-size);
62
+ --xh-_popselect-font-size: var(--xh-control-font-md);
58
63
 
59
64
  /* 形态档只换这三个槽:缺省即 outline(描边 + 画布底) */
60
65
  --xh-_popselect-control-bg: var(--xh-bg-canvas);
@@ -64,7 +69,7 @@
64
69
  /* 聚焦环恒用固定环色;强调色随语气走,只落在勾选标记与选中文字上,正文文字色不动。
65
70
  没写 data-tone 时 --xh-_tone 没被声明,两处都退回原来的取值 */
66
71
  --xh-_popselect-ring: var(--xh-ring-focus);
67
- --xh-_popselect-accent: var(--xh-_tone, var(--xh-bg-brand));
72
+ --xh-_popselect-accent: var(--xh-_tone, var(--xh-fg-brand));
68
73
  --xh-_popselect-item-selected-fg: var(--xh-_tone-fg, var(--xh-fg-brand-strong));
69
74
  }
70
75
 
@@ -91,6 +96,8 @@
91
96
  [data-scope='popselect']:is([data-part='root'], [data-part='positioner'])[data-size='sm'] {
92
97
  --xh-_popselect-h: var(--xh-control-h-sm);
93
98
  --xh-_popselect-px: var(--xh-control-px-sm);
99
+ --xh-_popselect-item-py: var(--xh-list-option-py-sm);
100
+ --xh-_popselect-item-px: var(--xh-control-px-sm);
94
101
  --xh-_popselect-gap: var(--xh-control-gap-sm);
95
102
  --xh-_popselect-font-size: var(--xh-control-font-sm);
96
103
  }
@@ -98,6 +105,8 @@
98
105
  [data-scope='popselect']:is([data-part='root'], [data-part='positioner'])[data-size='lg'] {
99
106
  --xh-_popselect-h: var(--xh-control-h-lg);
100
107
  --xh-_popselect-px: var(--xh-control-px-lg);
108
+ --xh-_popselect-item-py: var(--xh-list-option-py-lg);
109
+ --xh-_popselect-item-px: var(--xh-control-px-lg);
101
110
  --xh-_popselect-gap: var(--xh-control-gap-lg);
102
111
  --xh-_popselect-font-size: var(--xh-control-font-lg);
103
112
  }
@@ -245,6 +254,7 @@
245
254
  [data-scope='popselect'][data-part='content'] {
246
255
  display: flex;
247
256
  flex-direction: column;
257
+ gap: var(--xh-popselect-content-gap, var(--xh-list-option-gap));
248
258
  min-inline-size: var(--xh-popselect-content-min-w, var(--xh-overlay-menu-min-w));
249
259
  max-inline-size: var(--xh-popselect-content-max-w, var(--xh-overlay-max-w));
250
260
  max-block-size: min(var(--xh-popselect-content-max-h, var(--xh-overlay-menu-max-h)), var(--xh-_popselect-available-h));
@@ -290,8 +300,8 @@
290
300
  display: flex;
291
301
  align-items: center;
292
302
  gap: var(--xh-popselect-item-gap, var(--xh-_popselect-gap));
293
- padding-block: var(--xh-popselect-item-py, var(--xh-space-1_5));
294
- padding-inline: var(--xh-popselect-item-px, var(--xh-control-px-md));
303
+ padding-block: var(--xh-popselect-item-py, var(--xh-_popselect-item-py));
304
+ padding-inline: var(--xh-popselect-item-px, var(--xh-_popselect-item-px));
295
305
  border-radius: var(--xh-popselect-item-radius, var(--xh-shape-control));
296
306
  color: var(--xh-popselect-item-fg, var(--xh-fg-default));
297
307
  font-size: var(--xh-popselect-item-font-size, var(--xh-_popselect-font-size));
@@ -368,4 +378,14 @@
368
378
  [data-scope='popselect'][data-part='item-indicator'][data-state='checked'] {
369
379
  visibility: visible;
370
380
  }
381
+
382
+ /* 声明过任何 display 就盖掉了 UA 的 [hidden]{display:none},收起态得自己还回去。
383
+ 写在文件末尾:兜底必须排在该部件所有 display 声明之后 */
384
+ [data-scope='popselect'][data-part='root'][hidden],
385
+ [data-scope='popselect'][data-part='control'][hidden],
386
+ [data-scope='popselect'][data-part='trigger'][hidden],
387
+ [data-scope='popselect'][data-part='item'][hidden],
388
+ [data-scope='popselect'][data-part='item-indicator'][hidden] {
389
+ display: none;
390
+ }
371
391
  }
package/css/progress.css CHANGED
@@ -31,7 +31,7 @@
31
31
  overflow: hidden;
32
32
  inline-size: 100%;
33
33
  block-size: var(--xh-_thickness);
34
- border-radius: var(--xh-shape-pill);
34
+ border-radius: var(--xh-progress-track-radius, var(--xh-shape-pill));
35
35
  background: var(--xh-progress-track, var(--xh-bg-subtle-active));
36
36
  }
37
37
 
@@ -39,7 +39,7 @@
39
39
  轨道不跟着换族:只有已完成的那段换色,底槽保持中性才读得出"完成了多少"。 */
40
40
  [data-scope='progress'][data-part='range'] {
41
41
  block-size: 100%;
42
- border-radius: var(--xh-shape-pill);
42
+ border-radius: var(--xh-progress-range-radius, var(--xh-shape-pill));
43
43
  background: var(--xh-progress-range, var(--xh-_tone, var(--xh-bg-brand)));
44
44
  transition: inline-size var(--xh-motion-duration-micro) var(--xh-motion-ease-enter);
45
45
  }
@@ -146,4 +146,10 @@
146
146
  visibility: hidden;
147
147
  }
148
148
 
149
+
150
+ /* 声明过任何 display 就盖掉了 UA 的 [hidden]{display:none},收起态得自己还回去。
151
+ 写在文件末尾:兜底必须排在该部件所有 display 声明之后 */
152
+ [data-scope='progress'][data-part='root'][hidden] {
153
+ display: none;
154
+ }
149
155
  }
@@ -7,7 +7,8 @@
7
7
  [data-scope='radio-group'][data-part='root'] {
8
8
  /* 尺寸档只换这两个私有槽,标题与条目都从 root 继承它们,换档不必给每个部件各写一条选择器 */
9
9
  --xh-_radio-group-item-gap: var(--xh-control-gap-md);
10
- --xh-_radio-group-font-size: var(--xh-text-label-size);
10
+ --xh-_radio-group-font-size: var(--xh-control-font-md);
11
+ --xh-_radio-group-indicator: var(--xh-control-indicator-md);
11
12
  /* 选中色随语气走。没写 data-tone 时 --xh-_tone 没被声明,退回原来的品牌色 */
12
13
  --xh-_radio-group-accent: var(--xh-_tone, var(--xh-bg-brand));
13
14
 
@@ -28,11 +29,13 @@
28
29
  [data-scope='radio-group'][data-part='root'][data-size='sm'] {
29
30
  --xh-_radio-group-item-gap: var(--xh-control-gap-sm);
30
31
  --xh-_radio-group-font-size: var(--xh-control-font-sm);
32
+ --xh-_radio-group-indicator: var(--xh-control-indicator-sm);
31
33
  }
32
34
 
33
35
  [data-scope='radio-group'][data-part='root'][data-size='lg'] {
34
36
  --xh-_radio-group-item-gap: var(--xh-control-gap-lg);
35
37
  --xh-_radio-group-font-size: var(--xh-control-font-lg);
38
+ --xh-_radio-group-indicator: var(--xh-control-indicator-lg);
36
39
  }
37
40
 
38
41
  [data-scope='radio-group'][data-part='label'] {
@@ -71,10 +74,10 @@
71
74
  flex: none;
72
75
  align-items: center;
73
76
  justify-content: center;
74
- inline-size: var(--xh-radio-group-indicator-size, var(--xh-control-indicator-size));
75
- block-size: var(--xh-radio-group-indicator-size, var(--xh-control-indicator-size));
77
+ inline-size: var(--xh-radio-group-indicator-size, var(--xh-_radio-group-indicator));
78
+ block-size: var(--xh-radio-group-indicator-size, var(--xh-_radio-group-indicator));
76
79
  border: var(--xh-stroke-thin) solid var(--xh-radio-group-indicator-border, var(--xh-border-control));
77
- border-radius: var(--xh-shape-pill);
80
+ border-radius: var(--xh-radio-group-indicator-radius, var(--xh-shape-pill));
78
81
  background: var(--xh-radio-group-indicator-bg, var(--xh-bg-canvas));
79
82
  transition: border-color var(--xh-motion-duration-micro) var(--xh-motion-ease-enter);
80
83
  }
@@ -93,8 +96,8 @@
93
96
  直径取指示器的一半:换尺寸档时圈与点一起走,比例不散 */
94
97
  [data-scope='radio-group'][data-part='indicator']::before {
95
98
  content: '';
96
- inline-size: calc(var(--xh-radio-group-indicator-size, var(--xh-control-indicator-size)) / 2);
97
- block-size: calc(var(--xh-radio-group-indicator-size, var(--xh-control-indicator-size)) / 2);
99
+ inline-size: calc(var(--xh-radio-group-indicator-size, var(--xh-_radio-group-indicator)) / 2);
100
+ block-size: calc(var(--xh-radio-group-indicator-size, var(--xh-_radio-group-indicator)) / 2);
98
101
  border-radius: var(--xh-shape-pill);
99
102
  background: var(--xh-radio-group-indicator-dot, var(--xh-_radio-group-accent));
100
103
  scale: 0;
@@ -109,4 +112,12 @@
109
112
  color: inherit;
110
113
  user-select: none;
111
114
  }
115
+
116
+ /* 声明过任何 display 就盖掉了 UA 的 [hidden]{display:none},收起态得自己还回去。
117
+ 写在文件末尾:兜底必须排在该部件所有 display 声明之后 */
118
+ [data-scope='radio-group'][data-part='root'][hidden],
119
+ [data-scope='radio-group'][data-part='item'][hidden],
120
+ [data-scope='radio-group'][data-part='indicator'][hidden] {
121
+ display: none;
122
+ }
112
123
  }
package/css/rating.css CHANGED
@@ -8,9 +8,9 @@
8
8
  根上不留基准它就会贴到更外层的定位祖先上,原生校验提示跟着飘到页面别处。 */
9
9
  [data-scope='rating'][data-part='root'] {
10
10
  /* 尺寸档只换这三个私有槽,标题与星星都从 root 继承它们,换档不必给每个部件各写一条选择器 */
11
- --xh-_rating-item-gap: var(--xh-space-1);
11
+ --xh-_rating-item-gap: var(--xh-control-gap-md);
12
12
  --xh-_rating-item-size: var(--xh-font-size-2xl);
13
- --xh-_rating-font-size: var(--xh-text-label-size);
13
+ --xh-_rating-font-size: var(--xh-control-font-md);
14
14
  /* 点亮色随语气走。没写 data-tone 时 --xh-_tone 没被声明,退回原来的警示色 */
15
15
  --xh-_rating-accent: var(--xh-_tone, var(--xh-color-warning-500));
16
16
 
@@ -0,0 +1,113 @@
1
+ @layer xihan.components {
2
+ /* 皮肤在场的标记:开发模式下按 scope 探一次,取不到就说明这份皮肤没被引入。 */
3
+ [data-scope='resizable'] {
4
+ --xh-resizable-skin: 1;
5
+ }
6
+
7
+ /* 分工:**尺寸与位移**由连接层每帧写进内联样式(inline-size / block-size / left / top)。
8
+ 这份皮肤一条都不碰那四个——内联优先级更高,写了不但是死声明,
9
+ 还会在拖动的每一帧跟连接层抢位置。皮肤只管定位上下文、把手落位与状态表现。 */
10
+
11
+ /* 定位上下文,八向可调靠它才成立:
12
+ 推西边与北边时容器的起点会动,那段位移写成 left / top。relative 的 left / top
13
+ 是视觉位移、元素仍占原位,因此对边钉得住。改成 static 会让这两个方向只变尺寸不移位。 */
14
+ [data-scope='resizable'][data-part='root'] {
15
+ position: relative;
16
+ /* 把层序关在容器里:把手的 1 / 2 只跟彼此比,不跟外面的层号打架 */
17
+ isolation: isolate;
18
+ box-sizing: border-box;
19
+ }
20
+
21
+ /* 调整期间关掉选中:把手一按就会把容器里的文字刷成选中态 */
22
+ [data-scope='resizable'][data-part='root'][data-resizing] {
23
+ user-select: none;
24
+ }
25
+
26
+ [data-scope='resizable'][data-part='root'][hidden] {
27
+ display: none;
28
+ }
29
+
30
+ /* 把手压在边上,往外挪半个身位,两侧各留出一点可抓的余量——
31
+ 贴着边只有一两个像素能按到。落位按 data-edge 分派。 */
32
+ [data-scope='resizable'][data-part='handle'] {
33
+ position: absolute;
34
+ z-index: 1;
35
+ display: block;
36
+ touch-action: none;
37
+ }
38
+
39
+ [data-scope='resizable'][data-part='handle'][hidden] {
40
+ display: none;
41
+ }
42
+
43
+ /* 四条边:各占一整条,厚度是可抓的余量 */
44
+ [data-scope='resizable'][data-part='handle'][data-edge='n'],
45
+ [data-scope='resizable'][data-part='handle'][data-edge='s'] {
46
+ inset-inline: var(--xh-resizable-grip, var(--xh-space-2));
47
+ block-size: var(--xh-resizable-grip, var(--xh-space-2));
48
+ }
49
+
50
+ [data-scope='resizable'][data-part='handle'][data-edge='e'],
51
+ [data-scope='resizable'][data-part='handle'][data-edge='w'] {
52
+ inset-block: var(--xh-resizable-grip, var(--xh-space-2));
53
+ inline-size: var(--xh-resizable-grip, var(--xh-space-2));
54
+ }
55
+
56
+ /* 落位用逻辑属性:e 说的是行尾侧,从右往左排版时它就该落在屏幕左边——
57
+ 机器那边也是把逻辑边翻成物理边再算几何的,两处同源 */
58
+ [data-scope='resizable'][data-part='handle'][data-edge='n'] {
59
+ inset-block-start: calc(var(--xh-resizable-grip, var(--xh-space-2)) / -2);
60
+ }
61
+
62
+ [data-scope='resizable'][data-part='handle'][data-edge='s'] {
63
+ inset-block-end: calc(var(--xh-resizable-grip, var(--xh-space-2)) / -2);
64
+ }
65
+
66
+ [data-scope='resizable'][data-part='handle'][data-edge='e'] {
67
+ inset-inline-end: calc(var(--xh-resizable-grip, var(--xh-space-2)) / -2);
68
+ }
69
+
70
+ [data-scope='resizable'][data-part='handle'][data-edge='w'] {
71
+ inset-inline-start: calc(var(--xh-resizable-grip, var(--xh-space-2)) / -2);
72
+ }
73
+
74
+ /* 四个角:压在两条边的交点上,盖过相邻两条边(它们同时动两轴) */
75
+ [data-scope='resizable'][data-part='handle'][data-edge='ne'],
76
+ [data-scope='resizable'][data-part='handle'][data-edge='nw'],
77
+ [data-scope='resizable'][data-part='handle'][data-edge='se'],
78
+ [data-scope='resizable'][data-part='handle'][data-edge='sw'] {
79
+ z-index: 2;
80
+ inline-size: var(--xh-resizable-corner, var(--xh-space-3));
81
+ block-size: var(--xh-resizable-corner, var(--xh-space-3));
82
+ }
83
+
84
+ [data-scope='resizable'][data-part='handle'][data-edge='nw'] {
85
+ inset-block-start: calc(var(--xh-resizable-corner, var(--xh-space-3)) / -2);
86
+ inset-inline-start: calc(var(--xh-resizable-corner, var(--xh-space-3)) / -2);
87
+ }
88
+
89
+ [data-scope='resizable'][data-part='handle'][data-edge='ne'] {
90
+ inset-block-start: calc(var(--xh-resizable-corner, var(--xh-space-3)) / -2);
91
+ inset-inline-end: calc(var(--xh-resizable-corner, var(--xh-space-3)) / -2);
92
+ }
93
+
94
+ [data-scope='resizable'][data-part='handle'][data-edge='sw'] {
95
+ inset-block-end: calc(var(--xh-resizable-corner, var(--xh-space-3)) / -2);
96
+ inset-inline-start: calc(var(--xh-resizable-corner, var(--xh-space-3)) / -2);
97
+ }
98
+
99
+ [data-scope='resizable'][data-part='handle'][data-edge='se'] {
100
+ inset-block-end: calc(var(--xh-resizable-corner, var(--xh-space-3)) / -2);
101
+ inset-inline-end: calc(var(--xh-resizable-corner, var(--xh-space-3)) / -2);
102
+ }
103
+
104
+ [data-scope='resizable'][data-part='handle']:focus-visible {
105
+ outline: var(--xh-ring-width) solid var(--xh-ring-focus);
106
+ outline-offset: var(--xh-ring-offset);
107
+ }
108
+
109
+ /* 没开放的边不显示把手:留着一个抓不动的区域只会让人反复去试 */
110
+ [data-scope='resizable'][data-part='handle'][data-disabled] {
111
+ display: none;
112
+ }
113
+ }
package/css/result.css CHANGED
@@ -8,7 +8,7 @@
8
8
  /* 三个尺寸档只换这几个私有槽,图标与标题都从 root 继承它们,
9
9
  换档不必给每个部件各写一条选择器 */
10
10
  --xh-_result-gap: var(--xh-stack-gap-md);
11
- --xh-_result-py: var(--xh-section-py);
11
+ --xh-_result-py: var(--xh-section-py-md);
12
12
  --xh-_result-icon-size: var(--xh-glyph-size-3xl);
13
13
  --xh-_result-title-size: var(--xh-text-heading-3-size);
14
14
  /* 说明的读行宽度:整句话不收窄就会拉成一条难读的长行 */
@@ -34,15 +34,15 @@
34
34
 
35
35
  /* —— 尺寸 —— */
36
36
  [data-scope='result'][data-part='root'][data-size='sm'] {
37
- --xh-_result-gap: var(--xh-space-3);
38
- --xh-_result-py: var(--xh-space-6);
37
+ --xh-_result-gap: var(--xh-stack-gap-sm);
38
+ --xh-_result-py: var(--xh-section-py-sm);
39
39
  --xh-_result-icon-size: var(--xh-glyph-size-2xl);
40
40
  --xh-_result-title-size: var(--xh-control-font-lg);
41
41
  }
42
42
 
43
43
  [data-scope='result'][data-part='root'][data-size='lg'] {
44
- --xh-_result-gap: var(--xh-space-6);
45
- --xh-_result-py: var(--xh-space-8);
44
+ --xh-_result-gap: var(--xh-stack-gap-lg);
45
+ --xh-_result-py: var(--xh-section-py-lg);
46
46
  --xh-_result-icon-size: var(--xh-glyph-size-4xl);
47
47
  --xh-_result-title-size: var(--xh-text-heading-2-size);
48
48
  }
@@ -75,6 +75,9 @@
75
75
  align-items: center;
76
76
  justify-content: center;
77
77
  flex: none;
78
+ /* 作者塞进图标槽的 XhIcon 与皮肤画的字形同一把尺,都按展示档的图标框量 */
79
+ --xh-icon-size: var(--xh-result-icon-size, var(--xh-_result-icon-size));
80
+
78
81
  block-size: var(--xh-result-icon-size, var(--xh-_result-icon-size));
79
82
  inline-size: var(--xh-result-icon-size, var(--xh-_result-icon-size));
80
83
  color: var(--xh-result-icon-fg, var(--xh-_result-accent));
@@ -106,4 +109,11 @@
106
109
  justify-content: center;
107
110
  gap: var(--xh-result-action-gap, var(--xh-space-2));
108
111
  }
112
+
113
+ /* 声明过任何 display 就盖掉了 UA 的 [hidden]{display:none},收起态得自己还回去。
114
+ 写在文件末尾:兜底必须排在该部件所有 display 声明之后 */
115
+ [data-scope='result'][data-part='icon'][hidden],
116
+ [data-scope='result'][data-part='action'][hidden] {
117
+ display: none;
118
+ }
109
119
  }
package/css/scrollbar.css CHANGED
@@ -27,6 +27,9 @@
27
27
  --xh-_scrollbar-thickness: var(--xh-scrollbar-thickness-md);
28
28
 
29
29
  position: absolute;
30
+ /* 浮层的 positioner 一律 pointer-events: none,条子作为它的子节点会继承到,拖不动也点不着;
31
+ 收起态那条规则优先级更高,仍旧穿透 */
32
+ pointer-events: auto;
30
33
  /* touch-action 关掉浏览器自己的手势:不关的话手指一按滑块页面就跟着滚,
31
34
  指针随即被系统收走(pointercancel),拖到一半的滑块停在原地。
32
35
  user-select 同理——拖动时选中页面文字会让滑块"粘"住。 */
package/css/segmented.css CHANGED
@@ -11,7 +11,7 @@
11
11
  --xh-_segmented-h: var(--xh-control-h-md);
12
12
  --xh-_segmented-px: var(--xh-control-px-md);
13
13
  --xh-_segmented-gap: var(--xh-control-gap-md);
14
- --xh-_segmented-font-size: var(--xh-text-label-size);
14
+ --xh-_segmented-font-size: var(--xh-control-font-md);
15
15
  /* 指示器底色与选中段的文字色;没写 data-tone 时就是这里的取值 */
16
16
  --xh-_segmented-indicator-bg: var(--xh-bg-surface);
17
17
  --xh-_segmented-fg-selected: var(--xh-fg-default);
package/css/select.css CHANGED
@@ -54,9 +54,11 @@
54
54
  换档不必给每个部件各写一条选择器 */
55
55
  --xh-_select-h: var(--xh-control-h-md);
56
56
  --xh-_select-px: var(--xh-control-px-md);
57
+ --xh-_select-item-py: var(--xh-list-option-py-md);
58
+ --xh-_select-item-px: var(--xh-control-px-md);
57
59
  --xh-_select-gap: var(--xh-control-gap-md);
58
- --xh-_select-font-size: var(--xh-text-body-size);
59
- --xh-_select-label-font-size: var(--xh-text-label-size);
60
+ --xh-_select-font-size: var(--xh-control-font-md);
61
+ --xh-_select-label-font-size: var(--xh-control-font-md);
60
62
 
61
63
  /* 形态档只换这三个槽:缺省即 outline(描边 + 画布底) */
62
64
  --xh-_select-control-bg: var(--xh-bg-canvas);
@@ -66,7 +68,7 @@
66
68
  /* 聚焦环恒用固定环色;强调色随语气走,只落在勾选标记与选中文字上,正文文字色不动。
67
69
  没写 data-tone 时 --xh-_tone 没被声明,两处都退回原来的取值 */
68
70
  --xh-_select-ring: var(--xh-ring-focus);
69
- --xh-_select-accent: var(--xh-_tone, var(--xh-bg-brand));
71
+ --xh-_select-accent: var(--xh-_tone, var(--xh-fg-brand));
70
72
  --xh-_select-item-selected-fg: var(--xh-_tone-fg, var(--xh-fg-brand-strong));
71
73
  }
72
74
 
@@ -86,6 +88,8 @@
86
88
  [data-scope='select']:is([data-part='root'], [data-part='positioner'])[data-size='sm'] {
87
89
  --xh-_select-h: var(--xh-control-h-sm);
88
90
  --xh-_select-px: var(--xh-control-px-sm);
91
+ --xh-_select-item-py: var(--xh-list-option-py-sm);
92
+ --xh-_select-item-px: var(--xh-control-px-sm);
89
93
  --xh-_select-gap: var(--xh-control-gap-sm);
90
94
  --xh-_select-font-size: var(--xh-control-font-sm);
91
95
  --xh-_select-label-font-size: var(--xh-control-font-sm);
@@ -103,6 +107,8 @@
103
107
  [data-scope='select']:is([data-part='root'], [data-part='positioner'])[data-size='lg'] {
104
108
  --xh-_select-h: var(--xh-control-h-lg);
105
109
  --xh-_select-px: var(--xh-control-px-lg);
110
+ --xh-_select-item-py: var(--xh-list-option-py-lg);
111
+ --xh-_select-item-px: var(--xh-control-px-lg);
106
112
  --xh-_select-gap: var(--xh-control-gap-lg);
107
113
  --xh-_select-font-size: var(--xh-control-font-lg);
108
114
  --xh-_select-label-font-size: var(--xh-control-font-lg);
@@ -151,8 +157,6 @@
151
157
  block-size: var(--xh-select-control-h, var(--xh-_select-h));
152
158
  padding-inline: var(--xh-select-control-px, var(--xh-_select-px));
153
159
  min-inline-size: var(--xh-select-control-min-w, var(--xh-control-min-w));
154
- /* 多选会把 N 项的文本连成一串,框宽必须封顶;与浮层同一个上限,两半看着才是一件东西 */
155
- max-inline-size: var(--xh-select-control-max-w, var(--xh-overlay-max-w));
156
160
  border: var(--xh-stroke-thin) solid var(--xh-select-control-border, var(--xh-_select-control-border));
157
161
  border-radius: var(--xh-select-control-radius, var(--xh-shape-control));
158
162
  background: var(--xh-select-control-bg, var(--xh-_select-control-bg));
@@ -399,6 +403,7 @@
399
403
  display: flex;
400
404
  flex: 1 1 auto;
401
405
  flex-direction: column;
406
+ gap: var(--xh-select-list-gap, var(--xh-list-option-gap));
402
407
  min-block-size: 0;
403
408
  overflow-y: auto;
404
409
  }
@@ -453,8 +458,8 @@
453
458
  display: flex;
454
459
  align-items: center;
455
460
  gap: var(--xh-select-item-gap, var(--xh-_select-gap));
456
- padding-block: var(--xh-select-item-py, var(--xh-space-1_5));
457
- padding-inline: var(--xh-select-item-px, var(--xh-control-px-md));
461
+ padding-block: var(--xh-select-item-py, var(--xh-_select-item-py));
462
+ padding-inline: var(--xh-select-item-px, var(--xh-_select-item-px));
458
463
  border-radius: var(--xh-select-item-radius, var(--xh-shape-control));
459
464
  color: var(--xh-select-item-fg, var(--xh-fg-default));
460
465
  font-size: var(--xh-select-item-font-size, var(--xh-_select-font-size));
@@ -560,4 +565,17 @@
560
565
  -webkit-mask: var(--xh-glyph-mark-close) center / contain no-repeat;
561
566
  mask: var(--xh-glyph-mark-close) center / contain no-repeat;
562
567
  }
568
+
569
+ /* 声明过任何 display 就盖掉了 UA 的 [hidden]{display:none},收起态得自己还回去。
570
+ 写在文件末尾:兜底必须排在该部件所有 display 声明之后 */
571
+ [data-scope='select'][data-part='root'][hidden],
572
+ [data-scope='select'][data-part='control'][hidden],
573
+ [data-scope='select'][data-part='trigger'][hidden],
574
+ [data-scope='select'][data-part='tag'][hidden],
575
+ [data-scope='select'][data-part='indicator'][hidden],
576
+ [data-scope='select'][data-part='list'][hidden],
577
+ [data-scope='select'][data-part='item'][hidden],
578
+ [data-scope='select'][data-part='item-indicator'][hidden] {
579
+ display: none;
580
+ }
563
581
  }
package/css/side-nav.css CHANGED
@@ -76,8 +76,8 @@
76
76
  }
77
77
 
78
78
  [data-scope='side-nav'][data-part='group-label'] {
79
- padding-block: var(--xh-space-1);
80
- padding-inline: var(--xh-control-px-md);
79
+ padding-block: var(--xh-side-nav-group-label-py, var(--xh-space-1));
80
+ padding-inline: var(--xh-side-nav-group-label-px, var(--xh-control-px-md));
81
81
  font-size: var(--xh-text-caption-size);
82
82
  color: var(--xh-fg-subtle);
83
83
  user-select: none;
@@ -107,12 +107,12 @@
107
107
  [data-scope='side-nav'][data-part='link'] {
108
108
  display: flex;
109
109
  align-items: center;
110
- gap: var(--xh-control-gap-md);
110
+ gap: var(--xh-side-nav-link-gap, var(--xh-control-gap-md));
111
111
  inline-size: 100%;
112
112
  min-block-size: var(--xh-control-h-md);
113
- padding-inline: var(--xh-control-px-md);
113
+ padding-inline: var(--xh-side-nav-link-px, var(--xh-control-px-md));
114
114
  border: none;
115
- border-radius: var(--xh-shape-control);
115
+ border-radius: var(--xh-side-nav-link-radius, var(--xh-shape-control));
116
116
  background: none;
117
117
  color: inherit;
118
118
  font-size: var(--xh-text-body-size);
@@ -257,4 +257,15 @@
257
257
  -webkit-mask: var(--xh-glyph-mark-chevron-right) center / contain no-repeat;
258
258
  mask: var(--xh-glyph-mark-chevron-right) center / contain no-repeat;
259
259
  }
260
+
261
+ /* 声明过任何 display 就盖掉了 UA 的 [hidden]{display:none},收起态得自己还回去。
262
+ 写在文件末尾:兜底必须排在该部件所有 display 声明之后 */
263
+ [data-scope='side-nav'][data-part='root'][hidden],
264
+ [data-scope='side-nav'][data-part='group'][hidden],
265
+ [data-scope='side-nav'][data-part='branch'][hidden],
266
+ [data-scope='side-nav'][data-part='item'][hidden],
267
+ [data-scope='side-nav'][data-part='link'][hidden],
268
+ [data-scope='side-nav'][data-part='branch-indicator'][hidden] {
269
+ display: none;
270
+ }
260
271
  }
package/css/slider.css CHANGED
@@ -132,7 +132,9 @@
132
132
  background: var(--xh-slider-thumb-bg, var(--xh-_tone, var(--xh-bg-brand)));
133
133
  box-shadow: var(--xh-slider-thumb-shadow, var(--xh-elevation-raised));
134
134
  cursor: grab;
135
- transition: scale var(--xh-motion-duration-micro) var(--xh-motion-ease-enter);
135
+ transition:
136
+ scale var(--xh-motion-duration-micro) var(--xh-motion-ease-enter),
137
+ box-shadow var(--xh-motion-duration-micro) var(--xh-motion-ease-enter);
136
138
  }
137
139
 
138
140
  /* 内联样式把 inset-inline-start 定在值所在的比例上,那是拇指的**起始边**不是圆心;
@@ -203,7 +205,7 @@
203
205
  inset-block-start: 50%;
204
206
  inline-size: var(--xh-slider-mark-size, var(--xh-space-1));
205
207
  block-size: var(--xh-slider-mark-size, var(--xh-space-1));
206
- border-radius: var(--xh-shape-pill);
208
+ border-radius: var(--xh-slider-mark-radius, var(--xh-shape-pill));
207
209
  background: var(--xh-slider-mark-bg, var(--xh-border-strong));
208
210
  translate: -50% -50%;
209
211
  }
@@ -0,0 +1,103 @@
1
+ @layer xihan.components {
2
+ /* 皮肤在场的标记:开发模式下按 scope 探一次,取不到就说明这份皮肤没被引入。 */
3
+ [data-scope='sortable'] {
4
+ --xh-sortable-skin: 1;
5
+ }
6
+
7
+ /* 分工:**每一项的位移**由连接层每帧写进内联 transform(让位与跟手都在那儿算)。
8
+ 这份皮肤一条都不碰 transform——内联优先级更高,写了不但是死声明,
9
+ 还会在拖动的每一帧跟连接层抢位置。皮肤只管排布方向、间距、光标与状态表现。 */
10
+
11
+ [data-scope='sortable'][data-part='root'] {
12
+ display: flex;
13
+ gap: var(--xh-sortable-gap, var(--xh-space-2));
14
+ }
15
+
16
+ /* 拖动期间关掉选中:整项可拖时按下不 preventDefault,不关这条会一路刷蓝 */
17
+ [data-scope='sortable'][data-part='root'][data-dragging] {
18
+ user-select: none;
19
+ }
20
+
21
+ [data-scope='sortable'][data-part='root'][data-orientation='vertical'] {
22
+ flex-direction: column;
23
+ }
24
+
25
+ [data-scope='sortable'][data-part='root'][data-orientation='horizontal'] {
26
+ flex-direction: row;
27
+ }
28
+
29
+ /* 换行网格:主轴横排、允许折行,落点按最近中心判,与单轴那两档是不同的判据 */
30
+ [data-scope='sortable'][data-part='root'][data-orientation='both'] {
31
+ flex-direction: row;
32
+ flex-wrap: wrap;
33
+ }
34
+
35
+ /* 项里面放什么、怎么排全是使用者的事:这里不给 display 也不给间距。
36
+ 给了会盖掉使用者自己的单元格布局——网格里的一格被压成 flex 行之后就不再撑满,
37
+ 看起来像是尺寸算错了。皮肤只管拖起来那一项的视觉反馈。 */
38
+
39
+ /* 让位期间关掉过渡,跟手的那一项才不会慢半拍粘在指针后面。
40
+ 其余项反过来要过渡:它们是被让开的,瞬移会看不出发生了什么。 */
41
+ [data-scope='sortable'][data-part='root'][data-dragging] [data-part='item']:not([data-dragging]) {
42
+ transition: transform var(--xh-motion-duration-micro) var(--xh-motion-ease-enter);
43
+ }
44
+
45
+ [data-scope='sortable'][data-part='item'][data-dragging] {
46
+ /* 拖起来的那一项浮在上面。层级由连接层写内联,这里只管观感 */
47
+ box-shadow: var(--xh-sortable-item-shadow-dragging, var(--xh-elevation-raised));
48
+ opacity: var(--xh-sortable-item-opacity-dragging, 0.9);
49
+ }
50
+
51
+ [data-scope='sortable'][data-part='item-handle'] {
52
+ display: inline-flex;
53
+ align-items: center;
54
+ justify-content: center;
55
+ flex: none;
56
+ inline-size: var(--xh-sortable-handle-size, var(--xh-control-action-size));
57
+ block-size: var(--xh-sortable-handle-size, var(--xh-control-action-size));
58
+ padding: 0;
59
+ border: 0;
60
+ border-radius: var(--xh-sortable-handle-radius, var(--xh-shape-control));
61
+ background: transparent;
62
+ color: var(--xh-sortable-handle-fg, var(--xh-fg-muted));
63
+ cursor: grab;
64
+ }
65
+
66
+ [data-scope='sortable'][data-part='item-handle']:hover {
67
+ background: var(--xh-sortable-handle-bg-hover, var(--xh-bg-subtle-hover));
68
+ color: var(--xh-sortable-handle-fg-hover, var(--xh-fg-default));
69
+ }
70
+
71
+ [data-scope='sortable'][data-part='item-handle'][data-dragging] {
72
+ cursor: grabbing;
73
+ }
74
+
75
+ [data-scope='sortable'][data-part='item-handle']:focus-visible {
76
+ outline: var(--xh-ring-width) solid var(--xh-ring-focus);
77
+ outline-offset: var(--xh-ring-offset);
78
+ }
79
+
80
+ [data-scope='sortable'][data-part='item-handle'][aria-disabled='true'] {
81
+ cursor: not-allowed;
82
+ color: var(--xh-sortable-handle-fg-disabled, var(--xh-fg-disabled));
83
+ }
84
+
85
+ /* 活动区域只说给读屏听,不占版面。声明与 shared/visually-hidden.ts 逐条同值。 */
86
+ [data-scope='sortable'][data-part='live-region'] {
87
+ position: absolute;
88
+ inline-size: 1px;
89
+ block-size: 1px;
90
+ padding: 0;
91
+ margin: -1px;
92
+ overflow: hidden;
93
+ clip-path: inset(50%);
94
+ white-space: nowrap;
95
+ border: 0;
96
+ }
97
+ /* 给了 display 的角色节点必须补这条:display 声明会盖掉 UA 的 [hidden]{display:none},
98
+ 不补的话作者给节点加 hidden 后它照样显示 */
99
+ [data-scope='sortable'][data-part='root'][hidden],
100
+ [data-scope='sortable'][data-part='item-handle'][hidden] {
101
+ display: none;
102
+ }
103
+ }
package/css/space.css CHANGED
@@ -8,7 +8,7 @@
8
8
  display: flex;
9
9
  flex-wrap: nowrap;
10
10
  /* 不写档位也按 md 留白,这是与裸弹性容器的分野;使用者槽位排在档位之前,写死一个值即盖过所有档 */
11
- gap: var(--xh-space-gap, var(--xh-space-3));
11
+ gap: var(--xh-space-gap, var(--xh-layout-gap-md));
12
12
  }
13
13
 
14
14
  /* 声明了 display 就盖掉了 UA 的 [hidden] 规则,这里还回去 */
@@ -96,22 +96,22 @@
96
96
  /* —— 间距档位 —— */
97
97
  /* 每一档指向一个间距令牌,折行时行与行之间也吃这份间距 */
98
98
  [data-scope='space'][data-part='root'][data-gap='xs'] {
99
- gap: var(--xh-space-gap, var(--xh-space-1));
99
+ gap: var(--xh-space-gap, var(--xh-layout-gap-xs));
100
100
  }
101
101
 
102
102
  [data-scope='space'][data-part='root'][data-gap='sm'] {
103
- gap: var(--xh-space-gap, var(--xh-space-2));
103
+ gap: var(--xh-space-gap, var(--xh-layout-gap-sm));
104
104
  }
105
105
 
106
106
  [data-scope='space'][data-part='root'][data-gap='md'] {
107
- gap: var(--xh-space-gap, var(--xh-space-3));
107
+ gap: var(--xh-space-gap, var(--xh-layout-gap-md));
108
108
  }
109
109
 
110
110
  [data-scope='space'][data-part='root'][data-gap='lg'] {
111
- gap: var(--xh-space-gap, var(--xh-space-4));
111
+ gap: var(--xh-space-gap, var(--xh-layout-gap-lg));
112
112
  }
113
113
 
114
114
  [data-scope='space'][data-part='root'][data-gap='xl'] {
115
- gap: var(--xh-space-gap, var(--xh-space-6));
115
+ gap: var(--xh-space-gap, var(--xh-layout-gap-xl));
116
116
  }
117
117
  }