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

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 (129) hide show
  1. package/CHANGELOG.md +527 -0
  2. package/README.md +1 -1
  3. package/css/accordion.css +61 -5
  4. package/css/affix.css +5 -0
  5. package/css/alert.css +35 -5
  6. package/css/anchor.css +12 -7
  7. package/css/avatar-group.css +8 -3
  8. package/css/avatar.css +8 -3
  9. package/css/back-top.css +21 -1
  10. package/css/badge.css +21 -2
  11. package/css/breadcrumb.css +29 -4
  12. package/css/button-group.css +19 -13
  13. package/css/button.css +57 -11
  14. package/css/calendar.css +124 -2
  15. package/css/card.css +10 -5
  16. package/css/carousel.css +41 -5
  17. package/css/cascader.css +188 -102
  18. package/css/checkbox-group.css +46 -19
  19. package/css/checkbox.css +59 -8
  20. package/css/clipboard.css +7 -1
  21. package/css/code-block.css +17 -7
  22. package/css/collapsible.css +47 -2
  23. package/css/color-picker.css +117 -46
  24. package/css/combobox.css +132 -52
  25. package/css/composer.css +10 -3
  26. package/css/context-menu.css +101 -75
  27. package/css/countdown.css +5 -0
  28. package/css/date-field.css +96 -14
  29. package/css/date-picker.css +281 -65
  30. package/css/descriptions.css +7 -2
  31. package/css/dialog.css +109 -22
  32. package/css/download-trigger.css +76 -0
  33. package/css/drawer.css +75 -23
  34. package/css/dynamic-input.css +73 -17
  35. package/css/editable.css +17 -10
  36. package/css/ellipsis.css +6 -1
  37. package/css/empty-state.css +12 -7
  38. package/css/field.css +14 -6
  39. package/css/fieldset.css +69 -0
  40. package/css/file-upload.css +50 -7
  41. package/css/flex.css +5 -0
  42. package/css/float-button.css +21 -1
  43. package/css/floating-panel.css +310 -0
  44. package/css/form.css +10 -5
  45. package/css/gradient-text.css +5 -0
  46. package/css/grid.css +5 -0
  47. package/css/heatmap.css +410 -0
  48. package/css/highlight.css +6 -1
  49. package/css/hotkeys.css +90 -0
  50. package/css/hover-card.css +58 -50
  51. package/css/icon-wrapper.css +5 -0
  52. package/css/icon.css +5 -0
  53. package/css/image-cropper.css +231 -0
  54. package/css/image-viewer.css +167 -22
  55. package/css/image.css +7 -2
  56. package/css/infinite-scroll.css +6 -1
  57. package/css/json-viewer.css +241 -0
  58. package/css/layout.css +11 -10
  59. package/css/list.css +13 -8
  60. package/css/listbox.css +25 -4
  61. package/css/loading-bar.css +12 -1
  62. package/css/log.css +6 -1
  63. package/css/marquee.css +14 -0
  64. package/css/masonry.css +63 -0
  65. package/css/mention.css +105 -32
  66. package/css/menu.css +131 -46
  67. package/css/menubar.css +150 -66
  68. package/css/navigation-menu.css +59 -29
  69. package/css/number-animation.css +8 -3
  70. package/css/number-field.css +178 -16
  71. package/css/overlay-arrow.css +51 -0
  72. package/css/page-header.css +10 -5
  73. package/css/pagination.css +18 -13
  74. package/css/password-input.css +356 -0
  75. package/css/pin-input.css +18 -10
  76. package/css/popconfirm.css +73 -16
  77. package/css/popover.css +88 -44
  78. package/css/popselect.css +201 -52
  79. package/css/progress.css +52 -7
  80. package/css/qr-code.css +6 -1
  81. package/css/radio-group.css +19 -8
  82. package/css/rating.css +7 -2
  83. package/css/reset.css +17 -0
  84. package/css/result.css +11 -6
  85. package/css/scroll-area.css +65 -94
  86. package/css/scrollbar.css +167 -0
  87. package/css/segmented.css +215 -0
  88. package/css/select.css +292 -124
  89. package/css/separator.css +7 -2
  90. package/css/side-nav.css +116 -19
  91. package/css/signature-pad.css +144 -0
  92. package/css/skeleton.css +12 -1
  93. package/css/slider.css +15 -10
  94. package/css/space.css +117 -0
  95. package/css/spinner.css +31 -11
  96. package/css/splitter.css +5 -0
  97. package/css/statistic.css +14 -9
  98. package/css/steps.css +30 -8
  99. package/css/switch.css +62 -13
  100. package/css/table.css +136 -37
  101. package/css/tabs.css +9 -4
  102. package/css/tag.css +177 -0
  103. package/css/tags-input.css +83 -40
  104. package/css/text-field.css +154 -36
  105. package/css/thread.css +6 -1
  106. package/css/time-field.css +102 -16
  107. package/css/time-picker.css +264 -69
  108. package/css/time.css +5 -0
  109. package/css/timeline.css +15 -10
  110. package/css/timer.css +119 -0
  111. package/css/toast.css +46 -21
  112. package/css/toaster.css +6 -1
  113. package/css/toggle-group.css +5 -0
  114. package/css/toggle.css +11 -6
  115. package/css/tone.css +10 -5
  116. package/css/toolbar.css +6 -1
  117. package/css/tooltip.css +54 -38
  118. package/css/tour.css +128 -63
  119. package/css/transfer.css +73 -17
  120. package/css/tree-select.css +203 -83
  121. package/css/tree.css +90 -1
  122. package/css/typography.css +9 -4
  123. package/css/undefined.css +11 -1
  124. package/css/virtualizer.css +8 -1
  125. package/css/watermark.css +6 -2
  126. package/index.css +17 -1
  127. package/index.unlayered.css +9394 -2883
  128. package/package.json +19 -4
  129. package/css/motion.css +0 -58
package/css/checkbox.css CHANGED
@@ -1,8 +1,16 @@
1
1
  @layer xihan.components {
2
+ /* 皮肤在场的标记:开发模式下按 scope 探一次,取不到就说明这份皮肤没被引入。 */
3
+ [data-scope='checkbox'] {
4
+ --xh-checkbox-skin: 1;
5
+ }
6
+
2
7
  [data-scope='checkbox'][data-part='root'] {
8
+ /* 作者塞进指示符槽的图标跟着字号走,与皮肤画的兜底字形同一把尺 */
9
+ --xh-icon-size: var(--xh-checkbox-icon-size, var(--xh-glyph-size-text));
10
+
3
11
  /* 尺寸档只换方框边长这一个私有槽,勾的字号按边长的比例跟着走;
4
12
  指示器从 root 继承这两个槽,换档不必给每个部件各写一条选择器 */
5
- --xh-_checkbox-box: var(--xh-space-4);
13
+ --xh-_checkbox-box: var(--xh-control-indicator-size);
6
14
  --xh-_checkbox-glyph: calc(var(--xh-_checkbox-box) * 0.75);
7
15
 
8
16
  /* 选中态的底与描边随语气走。没写 data-tone 时 --xh-_tone 没被声明,退回原来的品牌色 */
@@ -18,8 +26,8 @@
18
26
  inline-size: var(--xh-_checkbox-box);
19
27
  block-size: var(--xh-_checkbox-box);
20
28
  padding: 0;
21
- border: 1px solid var(--xh-checkbox-border, var(--xh-border-control));
22
- border-radius: var(--xh-radius-sm);
29
+ border: var(--xh-stroke-thin) solid var(--xh-checkbox-border, var(--xh-border-control));
30
+ border-radius: var(--xh-shape-inset);
23
31
  background: var(--xh-checkbox-bg, var(--xh-bg-canvas));
24
32
  color: var(--xh-checkbox-fg, var(--xh-_checkbox-on-accent));
25
33
  cursor: pointer;
@@ -36,6 +44,20 @@
36
44
  background: var(--xh-checkbox-bg-checked, var(--xh-_checkbox-accent));
37
45
  }
38
46
 
47
+ /* 校验失败:方框描边转警示色。未勾时只有描边,勾上后填充仍走语气色,
48
+ 两者不打架——描边压在 checked 规则之后,选择器同特指度靠书写顺序取胜 */
49
+ [data-scope='checkbox'][data-part='root'][data-invalid],
50
+ [data-scope='checkbox'][data-part='root'][data-state='checked'][data-invalid],
51
+ [data-scope='checkbox'][data-part='root'][data-state='indeterminate'][data-invalid] {
52
+ border-color: var(--xh-checkbox-border-invalid, var(--xh-border-invalid));
53
+ }
54
+
55
+ /* 文字随方框一起转警示色:给了默认插槽时外层是 <label>,方框自己的描边够不到那段文字 */
56
+ [data-scope='checkbox'][data-part='label'][data-invalid],
57
+ [data-scope='checkbox'][data-part='text'][data-invalid] {
58
+ color: var(--xh-checkbox-fg-invalid, var(--xh-fg-danger));
59
+ }
60
+
39
61
  [data-scope='checkbox'][data-part='root'][data-disabled] {
40
62
  cursor: not-allowed;
41
63
  opacity: var(--xh-state-disabled-opacity);
@@ -49,11 +71,11 @@
49
71
  /* —— 尺寸 —— */
50
72
  /* 缺省档写在上面的基础规则里 */
51
73
  [data-scope='checkbox'][data-part='root'][data-size='sm'] {
52
- --xh-_checkbox-box: var(--xh-space-3);
74
+ --xh-_checkbox-box: calc(var(--xh-control-indicator-size) - var(--xh-space-1));
53
75
  }
54
76
 
55
77
  [data-scope='checkbox'][data-part='root'][data-size='lg'] {
56
- --xh-_checkbox-box: var(--xh-space-5);
78
+ --xh-_checkbox-box: calc(var(--xh-control-indicator-size) + var(--xh-space-1));
57
79
  }
58
80
 
59
81
  [data-scope='checkbox'][data-part='indicator'] {
@@ -66,8 +88,16 @@
66
88
  font-size: var(--xh-_checkbox-glyph);
67
89
  }
68
90
 
69
- [data-scope='checkbox'][data-part='indicator']::before {
70
- content: '✓';
91
+ /* 没写内容就由皮肤画;作者往部件里塞了自己的图形,这条规则即不命中 */
92
+ [data-scope='checkbox'][data-part='indicator']:empty::before {
93
+ content: '';
94
+ display: inline-block;
95
+ inline-size: var(--xh-icon-size, var(--xh-glyph-size-text));
96
+ block-size: var(--xh-icon-size, var(--xh-glyph-size-text));
97
+ vertical-align: var(--xh-glyph-baseline-shift);
98
+ background-color: currentColor;
99
+ -webkit-mask: var(--xh-glyph-mark-check) center / contain no-repeat;
100
+ mask: var(--xh-glyph-mark-check) center / contain no-repeat;
71
101
  }
72
102
 
73
103
  [data-scope='checkbox'][data-part='indicator'][data-state='unchecked'] {
@@ -84,8 +114,29 @@
84
114
  position: absolute;
85
115
  inline-size: 60%;
86
116
  block-size: var(--xh-stroke-thick);
87
- border-radius: var(--xh-radius-full);
117
+ border-radius: var(--xh-shape-pill);
88
118
  background: var(--xh-checkbox-indicator-fg, var(--xh-_checkbox-on-accent));
89
119
  content: '';
90
120
  }
121
+
122
+ /* —— 带文字的整行:<label> 包住控件与文字,与 checkbox-group 的条目同一副样子 —— */
123
+ [data-scope='checkbox'][data-part='label'] {
124
+ display: inline-flex;
125
+ align-items: center;
126
+ gap: var(--xh-checkbox-label-gap, var(--xh-control-gap-md));
127
+ color: var(--xh-checkbox-label-fg, var(--xh-fg-default));
128
+ font-size: var(--xh-checkbox-label-font-size, var(--xh-text-label-size));
129
+ line-height: var(--xh-leading-none);
130
+ cursor: pointer;
131
+ }
132
+
133
+ [data-scope='checkbox'][data-part='label'][data-disabled] {
134
+ color: var(--xh-checkbox-label-fg-disabled, var(--xh-fg-disabled));
135
+ cursor: not-allowed;
136
+ }
137
+
138
+ [data-scope='checkbox'][data-part='text'] {
139
+ color: inherit;
140
+ user-select: none;
141
+ }
91
142
  }
package/css/clipboard.css CHANGED
@@ -1,4 +1,9 @@
1
1
  @layer xihan.components {
2
+ /* 皮肤在场的标记:开发模式下按 scope 探一次,取不到就说明这份皮肤没被引入。 */
3
+ [data-scope='clipboard'] {
4
+ --xh-clipboard-skin: 1;
5
+ }
6
+
2
7
  /* 与文本框同一套堆叠:标签一行、输入行一行 */
3
8
  [data-scope='clipboard'][data-part='root'] {
4
9
  display: inline-flex;
@@ -34,7 +39,7 @@
34
39
  }
35
40
 
36
41
  [data-scope='clipboard'][data-part='input'] {
37
- min-inline-size: var(--xh-clipboard-input-min-w, 12rem);
42
+ min-inline-size: var(--xh-clipboard-input-min-w, var(--xh-control-min-w));
38
43
  block-size: var(--xh-clipboard-input-h, var(--xh-control-h-md));
39
44
  padding-inline: var(--xh-clipboard-input-px, var(--xh-control-px-md));
40
45
  padding-block: 0;
@@ -53,6 +58,7 @@
53
58
  }
54
59
 
55
60
  [data-scope='clipboard'][data-part='input']:focus-visible {
61
+ border-color: var(--xh-clipboard-input-border-focus, var(--xh-_tone, var(--xh-border-control-focus)));
56
62
  outline: var(--xh-ring-width) solid var(--xh-ring-focus);
57
63
  outline-offset: var(--xh-ring-offset);
58
64
  }
@@ -1,4 +1,9 @@
1
1
  @layer xihan.components {
2
+ /* 皮肤在场的标记:开发模式下按 scope 探一次,取不到就说明这份皮肤没被引入。 */
3
+ [data-scope='code-block'] {
4
+ --xh-code-block-skin: 1;
5
+ }
6
+
2
7
  /* overflow: hidden 让内部 <pre> 的滚动内容沿圆角收边;不设 display,排布由作者决定 */
3
8
  [data-scope='code-block'][data-part='root'] {
4
9
  overflow: hidden;
@@ -45,15 +50,20 @@
45
50
  white-space: pre;
46
51
  }
47
52
 
48
- /* 语法配色。令牌集里没有语法色这一类,所以就地声明成可覆盖的变量:
49
- 注释与标点复用既有语义色,只有三种真需要色相的走 light-dark()。
50
- 浏览器不认 light-dark() 时这几条整体失效,退化成单色代码,读起来照常。 */
53
+ /* 开了换行:pre-wrap 仍保留缩进与连续空白,只是允许行尾折下来;
54
+ anywhere 让没有空格的长串(url、base64)也能断,否则照样撑出横向滚动 */
55
+ [data-scope='code-block'][data-part='code'][data-wrap] {
56
+ white-space: pre-wrap;
57
+ overflow-wrap: anywhere;
58
+ }
59
+
60
+ /* 语法配色:注释与标点复用既有语义色,三种真需要色相的走 --xh-syntax-* 语法令牌(随主题明暗切换)。 */
51
61
  [data-scope='code-block'][data-part='root'] {
52
62
  --xh-code-block-comment-fg: var(--xh-fg-muted);
53
63
  --xh-code-block-punctuation-fg: var(--xh-fg-subtle);
54
- --xh-code-block-string-fg: light-dark(#0a7f5f, #7ee2b8);
55
- --xh-code-block-number-fg: light-dark(#9a5b00, #f0b866);
56
- --xh-code-block-keyword-fg: light-dark(#8250df, #d2a8ff);
64
+ --xh-code-block-string-fg: var(--xh-syntax-string);
65
+ --xh-code-block-number-fg: var(--xh-syntax-number);
66
+ --xh-code-block-keyword-fg: var(--xh-syntax-keyword);
57
67
  }
58
68
 
59
69
  /* 记号本身不带任何布局,只上色:它是 <code> 里的行内片段,多一点盒模型都会破坏对齐 */
@@ -72,7 +82,7 @@
72
82
 
73
83
  [data-scope='code-block'][data-part='token'][data-kind='keyword'] {
74
84
  color: var(--xh-code-block-keyword-fg);
75
- font-weight: var(--xh-code-block-keyword-weight, 600);
85
+ font-weight: var(--xh-code-block-keyword-weight, var(--xh-font-weight-semibold));
76
86
  }
77
87
 
78
88
  [data-scope='code-block'][data-part='token'][data-kind='punctuation'] {
@@ -1,4 +1,9 @@
1
1
  @layer xihan.components {
2
+ /* 皮肤在场的标记:开发模式下按 scope 探一次,取不到就说明这份皮肤没被引入。 */
3
+ [data-scope='collapsible'] {
4
+ --xh-collapsible-skin: 1;
5
+ }
6
+
2
7
  /* 根容器自己不排版,这条只声明尺寸档的私有槽:触发按钮从 root 继承它们,
3
8
  换档不必给部件各写一条选择器 */
4
9
  [data-scope='collapsible'][data-part='root'] {
@@ -14,14 +19,14 @@
14
19
  --xh-_collapsible-trigger-h: var(--xh-control-h-sm);
15
20
  --xh-_collapsible-trigger-px: var(--xh-control-px-sm);
16
21
  --xh-_collapsible-trigger-gap: var(--xh-control-gap-sm);
17
- --xh-_collapsible-trigger-font-size: var(--xh-font-size-sm);
22
+ --xh-_collapsible-trigger-font-size: var(--xh-control-font-sm);
18
23
  }
19
24
 
20
25
  [data-scope='collapsible'][data-part='root'][data-size='lg'] {
21
26
  --xh-_collapsible-trigger-h: var(--xh-control-h-lg);
22
27
  --xh-_collapsible-trigger-px: var(--xh-control-px-lg);
23
28
  --xh-_collapsible-trigger-gap: var(--xh-control-gap-lg);
24
- --xh-_collapsible-trigger-font-size: var(--xh-font-size-lg);
29
+ --xh-_collapsible-trigger-font-size: var(--xh-control-font-lg);
25
30
  }
26
31
 
27
32
  [data-scope='collapsible'][data-part='trigger'] {
@@ -56,8 +61,48 @@
56
61
  opacity: var(--xh-state-disabled-opacity);
57
62
  }
58
63
 
64
+ /* 这里刻意没有 [data-part='content'][hidden] { display: none }:补了动画一帧都播不出来。
65
+ 收起由适配器在退场结束后写内联 display 落成,退场窗口内靠 connect 发的 inert 挡住焦点 */
59
66
  [data-scope='collapsible'][data-part='content'] {
67
+ display: grid;
68
+ grid-template-rows: 1fr;
69
+ overflow: clip;
60
70
  padding-block: var(--xh-collapsible-content-py, var(--xh-stack-gap-md));
61
71
  color: var(--xh-collapsible-content-fg, var(--xh-fg-default));
62
72
  }
73
+
74
+ [data-scope='collapsible'][data-part='content'][data-state='open'] {
75
+ animation: xh-collapsible-expand var(--xh-motion-duration-enter) var(--xh-motion-ease-enter);
76
+ }
77
+
78
+ [data-scope='collapsible'][data-part='content'][data-state='closed'] {
79
+ animation: xh-collapsible-collapse var(--xh-motion-duration-exit) var(--xh-motion-ease-exit) forwards;
80
+ }
81
+ }
82
+
83
+ @layer xihan.motion {
84
+ /* 行高与内缩同帧动:内缩不归零的话,border-box 会把盒子钳在上下内缩之和上,收不干净 */
85
+ @keyframes xh-collapsible-expand {
86
+ from {
87
+ grid-template-rows: 0fr;
88
+ padding-block: 0;
89
+ }
90
+
91
+ to {
92
+ grid-template-rows: 1fr;
93
+ padding-block: var(--xh-collapsible-content-py, var(--xh-stack-gap-md));
94
+ }
95
+ }
96
+
97
+ @keyframes xh-collapsible-collapse {
98
+ from {
99
+ grid-template-rows: 1fr;
100
+ padding-block: var(--xh-collapsible-content-py, var(--xh-stack-gap-md));
101
+ }
102
+
103
+ to {
104
+ grid-template-rows: 0fr;
105
+ padding-block: 0;
106
+ }
107
+ }
63
108
  }
@@ -1,8 +1,8 @@
1
1
  @layer xihan.motion {
2
- @keyframes xh-color-picker-fade-in {
2
+ @keyframes xh-pop-in {
3
3
  from {
4
4
  opacity: 0;
5
- scale: 0.98;
5
+ scale: var(--xh-motion-scale-enter);
6
6
  }
7
7
 
8
8
  to {
@@ -10,23 +10,49 @@
10
10
  scale: 1;
11
11
  }
12
12
  }
13
+ @keyframes xh-pop-out {
14
+ from {
15
+ opacity: 1;
16
+ scale: 1;
17
+ }
18
+
19
+ to {
20
+ opacity: 0;
21
+ scale: var(--xh-motion-scale-enter);
22
+ }
23
+ }
13
24
  }
14
25
 
15
26
  @layer xihan.components {
27
+ /* 皮肤在场的标记:开发模式下按 scope 探一次,取不到就说明这份皮肤没被引入。 */
28
+ [data-scope='color-picker'] {
29
+ --xh-color-picker-skin: 1;
30
+ }
31
+
16
32
  /* 定位分工:取色区拇指的两条轴(inset-inline-start / inset-block-start)、
17
33
  通道拇指的主轴(inset-inline-start)、浮层坐标、取色区底色、透明度轨道的渐变,
18
34
  全都由连接层每帧写进内联样式。这份皮肤一个都不碰:内联优先级高于样式表,
19
35
  写了不但是死声明,还会跟连接层抢位置。皮肤只管尺寸、颜色、圆角与状态表现。 */
20
36
 
37
+ /* 标签一行、盒一行的两行堆叠 */
21
38
  [data-scope='color-picker'][data-part='root'] {
39
+ /* 盒的度量与标签字号走私有槽中转,与同族的下拉选择一处对一处 */
40
+ --xh-_color-picker-h: var(--xh-control-h-md);
41
+ --xh-_color-picker-px: var(--xh-control-px-md);
42
+ --xh-_color-picker-gap: var(--xh-control-gap-md);
43
+ --xh-_color-picker-label-font-size: var(--xh-text-label-size);
44
+
45
+ /* 聚焦环恒用固定环色 */
46
+ --xh-_color-picker-ring: var(--xh-ring-focus);
47
+
22
48
  display: inline-flex;
23
49
  flex-direction: column;
24
- gap: var(--xh-color-picker-gap, var(--xh-stack-gap-md));
50
+ gap: var(--xh-color-picker-gap, var(--xh-space-1));
25
51
  }
26
52
 
27
53
  [data-scope='color-picker'][data-part='label'] {
28
- color: var(--xh-color-picker-label-fg, var(--xh-fg-muted));
29
- font-size: var(--xh-color-picker-label-font-size, var(--xh-text-label-size));
54
+ color: var(--xh-color-picker-label-fg, var(--xh-fg-default));
55
+ font-size: var(--xh-color-picker-label-font-size, var(--xh-_color-picker-label-font-size));
30
56
  font-weight: var(--xh-color-picker-label-font-weight, var(--xh-text-label-weight));
31
57
  line-height: var(--xh-leading-none);
32
58
  }
@@ -35,44 +61,74 @@
35
61
  color: var(--xh-fg-subtle);
36
62
  }
37
63
 
38
- /* 画成一个框的是 trigger:里面的色块与值文本要看起来是一体的 */
39
- [data-scope='color-picker'][data-part='trigger'] {
64
+ /* 盒:描边、底色、控件高度与行内内衬都落在这一层 */
65
+ [data-scope='color-picker'][data-part='control'] {
40
66
  display: inline-flex;
41
67
  align-items: center;
42
- gap: var(--xh-color-picker-trigger-gap, var(--xh-control-gap-md));
43
- min-inline-size: var(--xh-color-picker-trigger-min-w, 9rem);
44
- block-size: var(--xh-color-picker-trigger-h, var(--xh-control-h-md));
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-control));
47
- border-radius: var(--xh-color-picker-trigger-radius, var(--xh-shape-control));
48
- background: var(--xh-color-picker-trigger-bg, var(--xh-bg-canvas));
49
- color: var(--xh-color-picker-trigger-fg, var(--xh-fg-default));
50
- font-family: inherit;
51
- font-size: var(--xh-color-picker-trigger-font-size, var(--xh-text-body-size));
52
- line-height: var(--xh-leading-none);
68
+ gap: var(--xh-color-picker-control-gap, var(--xh-_color-picker-gap));
69
+ min-inline-size: var(--xh-color-picker-control-min-w, var(--xh-control-min-w));
70
+ block-size: var(--xh-color-picker-control-h, var(--xh-_color-picker-h));
71
+ padding-inline: var(--xh-color-picker-control-px, var(--xh-_color-picker-px));
72
+ border: var(--xh-stroke-thin) solid var(--xh-color-picker-control-border, var(--xh-border-control));
73
+ border-radius: var(--xh-color-picker-control-radius, var(--xh-shape-control));
74
+ background: var(--xh-color-picker-control-bg, var(--xh-bg-canvas));
75
+ color: var(--xh-color-picker-control-fg, var(--xh-fg-default));
53
76
  cursor: pointer;
54
77
  transition: border-color var(--xh-motion-duration-micro) var(--xh-motion-ease-enter);
55
78
  }
56
79
 
57
- [data-scope='color-picker'][data-part='trigger']:hover:not(:disabled) {
58
- border-color: var(--xh-color-picker-trigger-border-hover, var(--xh-border-control-hover));
80
+ [data-scope='color-picker'][data-part='control'][hidden] {
81
+ display: none;
59
82
  }
60
83
 
61
- [data-scope='color-picker'][data-part='trigger']:focus-visible {
62
- outline: var(--xh-ring-width) solid var(--xh-ring-focus);
84
+ [data-scope='color-picker'][data-part='control']:hover:not([data-disabled]) {
85
+ border-color: var(--xh-color-picker-control-border-hover, var(--xh-border-control-hover));
86
+ }
87
+
88
+ /* Tab 停靠点是盒里的 trigger,环画在盒上 */
89
+ [data-scope='color-picker'][data-part='control']:focus-within:not([data-disabled]) {
90
+ border-color: var(--xh-color-picker-control-border-focus, var(--xh-_tone, var(--xh-border-control-focus)));
91
+ outline: var(--xh-ring-width) solid var(--xh-_color-picker-ring);
63
92
  outline-offset: var(--xh-ring-offset);
64
93
  }
65
94
 
66
- /* 单体控件用原生 disabled(预设色板那些格子也是原生按钮,同一条规矩) */
67
- [data-scope='color-picker'][data-part='trigger']:disabled {
68
- background: var(--xh-color-picker-trigger-bg-disabled, var(--xh-bg-subtle));
95
+ [data-scope='color-picker'][data-part='control'][data-disabled] {
96
+ background: var(--xh-color-picker-control-bg-disabled, var(--xh-bg-subtle));
69
97
  color: var(--xh-fg-disabled);
70
98
  cursor: not-allowed;
71
99
  }
72
100
 
73
101
  /* 只读仍可聚焦、浮层照开,只是改不动:不置灰,只把底色压下去 */
74
- [data-scope='color-picker'][data-part='trigger'][data-readonly] {
75
- background: var(--xh-color-picker-trigger-bg-readonly, var(--xh-bg-subtle));
102
+ [data-scope='color-picker'][data-part='control'][data-readonly] {
103
+ background: var(--xh-color-picker-control-bg-readonly, var(--xh-bg-subtle));
104
+ }
105
+
106
+ /* 盒内那颗可聚焦的按钮:不画描边不铺底也不自带高度,只占满剩余宽度、排布色块与值文本 */
107
+ [data-scope='color-picker'][data-part='trigger'] {
108
+ display: inline-flex;
109
+ flex: 1 1 auto;
110
+ align-items: center;
111
+ gap: var(--xh-color-picker-trigger-gap, var(--xh-_color-picker-gap));
112
+ min-inline-size: 0;
113
+ padding: 0;
114
+ border: 0;
115
+ background: transparent;
116
+ color: var(--xh-color-picker-trigger-fg, var(--xh-fg-default));
117
+ font-family: inherit;
118
+ font-size: var(--xh-color-picker-trigger-font-size, var(--xh-text-body-size));
119
+ line-height: var(--xh-leading-none);
120
+ text-align: start;
121
+ cursor: pointer;
122
+ }
123
+
124
+ [data-scope='color-picker'][data-part='trigger'][hidden] {
125
+ display: none;
126
+ }
127
+
128
+ /* 单体控件用原生 disabled(预设色板那些格子也是原生按钮,同一条规矩) */
129
+ [data-scope='color-picker'][data-part='trigger']:disabled {
130
+ color: var(--xh-fg-disabled);
131
+ cursor: not-allowed;
76
132
  }
77
133
 
78
134
  /* 当前颜色的色块。背景由连接层内联给(含透明度),这里只给形状与描边。
@@ -81,15 +137,17 @@
81
137
  [data-scope='color-picker'][data-part='swatch'] {
82
138
  display: inline-block;
83
139
  flex: none;
84
- inline-size: var(--xh-color-picker-swatch-size, 1.125rem);
85
- block-size: var(--xh-color-picker-swatch-size, 1.125rem);
140
+ inline-size: var(--xh-color-picker-swatch-size, 18px);
141
+ block-size: var(--xh-color-picker-swatch-size, 18px);
86
142
  border: var(--xh-stroke-thin) solid var(--xh-color-picker-swatch-border, var(--xh-border-default));
87
- border-radius: var(--xh-color-picker-swatch-radius, var(--xh-radius-sm));
143
+ border-radius: var(--xh-color-picker-swatch-radius, var(--xh-shape-inset));
88
144
  }
89
145
 
146
+ /* 值串可能很长,必须能截断;框宽由盒定,这里得允许自己被压缩 */
90
147
  [data-scope='color-picker'][data-part='value-text'] {
91
148
  overflow: hidden;
92
- flex: 1;
149
+ flex: 1 1 auto;
150
+ min-inline-size: 0;
93
151
  color: var(--xh-color-picker-value-fg, var(--xh-fg-default));
94
152
  font-size: var(--xh-color-picker-value-font-size, var(--xh-text-body-size));
95
153
  text-align: start;
@@ -99,8 +157,12 @@
99
157
 
100
158
  /* 坐标由定位引擎写进 style(inset-inline-start / inset-block-start),这里只定位模式与层级 */
101
159
  [data-scope='color-picker'][data-part='positioner'] {
160
+ /* 落定那一侧的可用高度,由定位引擎经内联自定义属性写进来,内容层继承它限高;
161
+ 引擎没算(尚未落位 / 无引擎 / 贴边归零)时不额外限高 */
162
+ --xh-_color-picker-available-h: 100vh;
163
+
102
164
  position: fixed;
103
- z-index: var(--xh-layer-popover);
165
+ z-index: var(--xh-color-picker-layer, var(--xh-layer-popover));
104
166
  /* 空壳不吃指针,交互只发生在 content 上 */
105
167
  pointer-events: none;
106
168
  }
@@ -114,18 +176,27 @@
114
176
  display: flex;
115
177
  flex-direction: column;
116
178
  gap: var(--xh-color-picker-content-gap, var(--xh-space-3));
117
- inline-size: var(--xh-color-picker-content-w, 15rem);
118
- padding: var(--xh-color-picker-content-p, var(--xh-space-3));
179
+ inline-size: var(--xh-color-picker-content-w, var(--xh-overlay-min-w));
180
+ padding-block: var(--xh-color-picker-content-py, var(--xh-space-3));
181
+ padding-inline: var(--xh-color-picker-content-px, var(--xh-space-3));
182
+ max-block-size: min(var(--xh-color-picker-max-h, var(--xh-viewport-h-md)), var(--xh-_color-picker-available-h));
183
+ overflow-y: auto;
119
184
  border: var(--xh-stroke-thin) solid var(--xh-color-picker-content-border, var(--xh-border-default));
120
185
  border-radius: var(--xh-color-picker-content-radius, var(--xh-shape-surface));
121
186
  background: var(--xh-color-picker-content-bg, var(--xh-bg-surface));
122
187
  color: var(--xh-color-picker-content-fg, var(--xh-fg-default));
123
- box-shadow: var(--xh-color-picker-content-shadow, var(--xh-elevation-2));
188
+ box-shadow: var(--xh-color-picker-content-shadow, var(--xh-elevation-floating));
124
189
  pointer-events: auto;
125
190
  }
126
191
 
127
192
  [data-scope='color-picker'][data-part='content'][data-state='open'] {
128
- animation: xh-color-picker-fade-in var(--xh-motion-duration-enter) var(--xh-motion-ease-enter);
193
+ animation: xh-pop-in var(--xh-motion-duration-enter) var(--xh-motion-ease-enter);
194
+ }
195
+
196
+ /* 退场:收起那一帧 hidden 由退场闸门押后,这里才播得出来。forwards 把末态钉住,
197
+ 免得动画结束到真收起之间闪一下原样 */
198
+ [data-scope='color-picker'][data-part='content'][data-state='closed'] {
199
+ animation: xh-pop-out var(--xh-motion-duration-exit) var(--xh-motion-ease-exit) forwards;
129
200
  }
130
201
 
131
202
  /* 浮层本身只是个容器(tabindex=-1 是焦点域的兜底落点),落焦时不画环 */
@@ -142,7 +213,7 @@
142
213
  position: relative;
143
214
  display: block;
144
215
  block-size: var(--xh-color-picker-area-h, 9rem);
145
- border-radius: var(--xh-color-picker-area-radius, var(--xh-radius-md));
216
+ border-radius: var(--xh-color-picker-area-radius, var(--xh-shape-control));
146
217
  cursor: crosshair;
147
218
  }
148
219
 
@@ -189,7 +260,7 @@
189
260
  border: var(--xh-stroke-thick) solid var(--xh-color-picker-thumb-border, var(--xh-color-neutral-0));
190
261
  border-radius: var(--xh-color-picker-thumb-radius, var(--xh-shape-pill));
191
262
  background: transparent;
192
- box-shadow: var(--xh-color-picker-thumb-shadow, var(--xh-elevation-1));
263
+ box-shadow: var(--xh-color-picker-thumb-shadow, var(--xh-elevation-raised));
193
264
  cursor: grab;
194
265
  transition: scale var(--xh-motion-duration-micro) var(--xh-motion-ease-enter);
195
266
  }
@@ -215,7 +286,7 @@
215
286
  放大用 scale 而不是改尺寸:变换绕自身中心发生,圆心不动,负外边距的算式不用跟着改 */
216
287
  [data-scope='color-picker'][data-part='area-thumb'][data-dragging],
217
288
  [data-scope='color-picker'][data-part='channel-slider-thumb'][data-dragging] {
218
- scale: var(--xh-color-picker-thumb-scale-dragging, 1.15);
289
+ scale: var(--xh-color-picker-thumb-scale-dragging, var(--xh-motion-scale-drag));
219
290
  cursor: grabbing;
220
291
  }
221
292
 
@@ -307,12 +378,12 @@
307
378
  color: inherit;
308
379
  /* 表单控件不继承页面字体,只给字号会让输入框用 UA 默认字族,与周围文本对不上 */
309
380
  font-family: inherit;
310
- font-size: var(--xh-color-picker-input-font-size, var(--xh-font-size-sm));
381
+ font-size: var(--xh-color-picker-input-font-size, var(--xh-text-secondary-size));
311
382
  text-align: center;
312
383
  }
313
384
 
314
385
  [data-scope='color-picker'][data-part='channel-input']:focus-visible {
315
- border-color: var(--xh-color-picker-input-border-focus, var(--xh-ring-focus));
386
+ border-color: var(--xh-color-picker-input-border-focus, var(--xh-_tone, var(--xh-border-control-focus)));
316
387
  outline: var(--xh-ring-width) solid var(--xh-ring-focus);
317
388
  /* 往内收一道发丝:输入框贴着面板边排,环画在外沿会压到相邻通道 */
318
389
  outline-offset: calc(-1 * var(--xh-stroke-thin));
@@ -320,7 +391,7 @@
320
391
 
321
392
  /* 打到一半的串:框里留着草稿,但值没动——描边提示"这串还没被收下" */
322
393
  [data-scope='color-picker'][data-part='channel-input'][data-invalid] {
323
- border-color: var(--xh-color-picker-input-border-invalid, var(--xh-color-danger-500));
394
+ border-color: var(--xh-color-picker-input-border-invalid, var(--xh-border-invalid));
324
395
  }
325
396
 
326
397
  [data-scope='color-picker'][data-part='channel-input'][data-readonly] {
@@ -338,15 +409,15 @@
338
409
  flex: none;
339
410
  align-items: center;
340
411
  justify-content: center;
341
- inline-size: var(--xh-color-picker-action-size, 1.75rem);
342
- block-size: var(--xh-color-picker-action-size, 1.75rem);
412
+ inline-size: var(--xh-color-picker-action-size, var(--xh-control-action-size));
413
+ block-size: var(--xh-color-picker-action-size, var(--xh-control-action-size));
343
414
  padding: 0;
344
415
  border: var(--xh-stroke-thin) solid var(--xh-color-picker-action-border, var(--xh-border-control));
345
416
  border-radius: var(--xh-color-picker-action-radius, var(--xh-shape-control));
346
417
  background: var(--xh-color-picker-action-bg, transparent);
347
418
  color: var(--xh-color-picker-action-fg, var(--xh-fg-muted));
348
419
  font-family: inherit;
349
- font-size: var(--xh-color-picker-action-font-size, var(--xh-font-size-sm));
420
+ font-size: var(--xh-color-picker-action-font-size, var(--xh-text-secondary-size));
350
421
  line-height: var(--xh-leading-none);
351
422
  cursor: pointer;
352
423
  user-select: none;
@@ -386,7 +457,7 @@
386
457
  block-size: var(--xh-color-picker-swatch-item-size, 1.25rem);
387
458
  padding: 0;
388
459
  border: var(--xh-stroke-thin) solid var(--xh-color-picker-swatch-border, var(--xh-border-control));
389
- border-radius: var(--xh-color-picker-swatch-radius, var(--xh-radius-sm));
460
+ border-radius: var(--xh-color-picker-swatch-radius, var(--xh-shape-inset));
390
461
  cursor: pointer;
391
462
  }
392
463