@xihan-ui/styles 1.0.0-alpha.2 → 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (122) hide show
  1. package/CHANGELOG.md +2177 -0
  2. package/README.md +1 -1
  3. package/css/accordion.css +80 -6
  4. package/css/alert.css +43 -14
  5. package/css/anchor.css +8 -8
  6. package/css/avatar-group.css +7 -3
  7. package/css/avatar.css +9 -3
  8. package/css/back-top.css +22 -1
  9. package/css/badge.css +104 -32
  10. package/css/breadcrumb.css +25 -5
  11. package/css/button-group.css +18 -13
  12. package/css/button.css +48 -11
  13. package/css/calendar.css +150 -7
  14. package/css/card.css +20 -11
  15. package/css/carousel.css +36 -5
  16. package/css/cascader.css +211 -124
  17. package/css/checkbox-group.css +72 -22
  18. package/css/checkbox.css +70 -13
  19. package/css/clipboard.css +2 -1
  20. package/css/code-block.css +12 -7
  21. package/css/collapsible.css +49 -3
  22. package/css/color-picker.css +132 -46
  23. package/css/combobox.css +132 -60
  24. package/css/composer.css +5 -3
  25. package/css/context-menu.css +113 -74
  26. package/css/date-field.css +93 -16
  27. package/css/date-picker.css +293 -72
  28. package/css/descriptions.css +11 -5
  29. package/css/dialog.css +47 -14
  30. package/css/download-trigger.css +76 -0
  31. package/css/drawer.css +57 -16
  32. package/css/dynamic-input.css +75 -17
  33. package/css/editable.css +12 -10
  34. package/css/ellipsis.css +7 -1
  35. package/css/empty-state.css +22 -12
  36. package/css/field.css +16 -6
  37. package/css/fieldset.css +69 -0
  38. package/css/file-upload.css +46 -8
  39. package/css/flex.css +13 -7
  40. package/css/float-button.css +23 -1
  41. package/css/floating-panel.css +316 -0
  42. package/css/form.css +4 -4
  43. package/css/grid.css +11 -5
  44. package/css/heatmap.css +411 -0
  45. package/css/highlight.css +2 -2
  46. package/css/hotkeys.css +90 -0
  47. package/css/hover-card.css +43 -45
  48. package/css/image-cropper.css +233 -0
  49. package/css/image-viewer.css +155 -17
  50. package/css/image.css +2 -2
  51. package/css/infinite-scroll.css +1 -1
  52. package/css/json-viewer.css +274 -0
  53. package/css/layout.css +19 -15
  54. package/css/list.css +22 -13
  55. package/css/listbox.css +24 -6
  56. package/css/loading-bar.css +12 -5
  57. package/css/log.css +7 -3
  58. package/css/marquee.css +9 -0
  59. package/css/masonry.css +63 -0
  60. package/css/mention.css +100 -36
  61. package/css/menu.css +127 -50
  62. package/css/menubar.css +155 -61
  63. package/css/navigation-menu.css +56 -31
  64. package/css/notification.css +377 -0
  65. package/css/number-animation.css +3 -3
  66. package/css/number-field.css +182 -19
  67. package/css/overlay-arrow.css +51 -0
  68. package/css/page-header.css +12 -5
  69. package/css/pagination.css +171 -14
  70. package/css/password-input.css +356 -0
  71. package/css/pin-input.css +15 -12
  72. package/css/popconfirm.css +55 -12
  73. package/css/popover.css +73 -45
  74. package/css/popselect.css +207 -57
  75. package/css/progress.css +54 -8
  76. package/css/qr-code.css +1 -1
  77. package/css/radio-group.css +27 -10
  78. package/css/rating.css +4 -4
  79. package/css/reset.css +17 -0
  80. package/css/result.css +21 -11
  81. package/css/scroll-area.css +61 -89
  82. package/css/scrollbar.css +170 -0
  83. package/css/segmented.css +215 -0
  84. package/css/select.css +298 -131
  85. package/css/separator.css +2 -2
  86. package/css/side-nav.css +127 -24
  87. package/css/signature-pad.css +144 -0
  88. package/css/skeleton.css +7 -1
  89. package/css/slider.css +14 -12
  90. package/css/space.css +117 -0
  91. package/css/spinner.css +22 -10
  92. package/css/statistic.css +9 -9
  93. package/css/steps.css +29 -12
  94. package/css/switch.css +57 -8
  95. package/css/table.css +146 -44
  96. package/css/tabs.css +13 -5
  97. package/css/tag.css +179 -0
  98. package/css/tags-input.css +80 -42
  99. package/css/text-field.css +151 -38
  100. package/css/thread.css +11 -3
  101. package/css/time-field.css +99 -18
  102. package/css/time-picker.css +261 -71
  103. package/css/timeline.css +15 -15
  104. package/css/timer.css +119 -0
  105. package/css/toast.css +129 -55
  106. package/css/toggle-group.css +30 -4
  107. package/css/toggle.css +12 -6
  108. package/css/tone.css +57 -22
  109. package/css/toolbar.css +1 -1
  110. package/css/tooltip.css +40 -31
  111. package/css/tour.css +112 -61
  112. package/css/transfer.css +98 -21
  113. package/css/tree-select.css +215 -89
  114. package/css/tree.css +131 -5
  115. package/css/typography.css +5 -5
  116. package/css/undefined.css +12 -1
  117. package/css/virtualizer.css +3 -1
  118. package/css/watermark.css +1 -2
  119. package/index.css +18 -1
  120. package/index.unlayered.css +10356 -3255
  121. package/package.json +20 -4
  122. package/css/toaster.css +0 -74
@@ -7,6 +7,9 @@
7
7
  /* 组容器:label、trigger、条目都是它的直接子节点,排布方式只能读 data-orientation——
8
8
  连接层明说了 role=group 不接受 aria-orientation,那个属性它根本没输出 */
9
9
  [data-scope='checkbox-group'][data-part='root'] {
10
+ /* 作者塞进指示符槽的图标跟着字号走,与皮肤画的兜底字形同一把尺 */
11
+ --xh-icon-size: var(--xh-checkbox-group-icon-size, var(--xh-glyph-size-text));
12
+
10
13
  display: flex;
11
14
  gap: var(--xh-checkbox-group-gap, var(--xh-stack-gap-md));
12
15
  }
@@ -62,7 +65,6 @@
62
65
  [data-scope='checkbox-group'][data-part='item'][data-disabled] {
63
66
  color: var(--xh-checkbox-group-item-fg-disabled, var(--xh-fg-disabled));
64
67
  cursor: not-allowed;
65
- opacity: var(--xh-state-disabled-opacity);
66
68
  }
67
69
 
68
70
  /* 只读整组都改不动,但不是禁用:颜色照常,只把"可点"这个暗示收回来。
@@ -81,13 +83,13 @@
81
83
  flex: none;
82
84
  align-items: center;
83
85
  justify-content: center;
84
- inline-size: var(--xh-checkbox-group-indicator-size, 16px);
85
- block-size: var(--xh-checkbox-group-indicator-size, 16px);
86
+ inline-size: var(--xh-checkbox-group-indicator-size, var(--xh-control-indicator-size));
87
+ block-size: var(--xh-checkbox-group-indicator-size, var(--xh-control-indicator-size));
86
88
  border: var(--xh-stroke-thin) solid var(--xh-checkbox-group-indicator-border, var(--xh-border-control));
87
- border-radius: var(--xh-checkbox-group-indicator-radius, var(--xh-radius-sm));
89
+ border-radius: var(--xh-checkbox-group-indicator-radius, var(--xh-shape-inset));
88
90
  background: var(--xh-checkbox-group-indicator-bg, var(--xh-bg-canvas));
89
91
  color: var(--xh-checkbox-group-indicator-fg, var(--xh-fg-on-brand));
90
- font-size: var(--xh-checkbox-group-indicator-font-size, 12px);
92
+ font-size: var(--xh-checkbox-group-indicator-font-size, calc(var(--xh-control-indicator-size) * 0.75));
91
93
  line-height: var(--xh-leading-none);
92
94
  transition:
93
95
  background var(--xh-motion-duration-micro) var(--xh-motion-ease-enter),
@@ -107,32 +109,79 @@
107
109
  border-color: var(--xh-checkbox-group-indicator-border-hover, var(--xh-border-control-hover));
108
110
  }
109
111
 
110
- /* 选中即填色:条目是二态,全选格三态里 allsome 都算"有值",共用同一副填色 */
112
+ /* 选中即填色:条目是二态,全选格三态里 checkedindeterminate 都算"有值",共用同一副填色 */
111
113
  [data-scope='checkbox-group'][data-part='indicator'][data-state='checked'],
112
- [data-scope='checkbox-group'][data-part='trigger']:is([data-state='all'], [data-state='some'])::before {
114
+ [data-scope='checkbox-group'][data-part='trigger']:is([data-state='checked'], [data-state='indeterminate'])::before {
113
115
  border-color: var(--xh-checkbox-group-indicator-border-checked, var(--xh-bg-brand));
114
116
  background: var(--xh-checkbox-group-indicator-bg-checked, var(--xh-bg-brand));
115
117
  }
116
118
 
117
119
  /* 勾号由皮肤补,作者不必自己往 indicator 里塞字符 */
118
- [data-scope='checkbox-group'][data-part='indicator'][data-state='checked']::before {
119
- content: '';
120
- }
121
-
122
- /* 全选格的三态:all 打勾、some 打横杠、none 留空。
123
- some 就是读屏听到的 aria-checked=mixed,两者同源,样式只认 data-state */
124
- [data-scope='checkbox-group'][data-part='trigger'][data-state='all']::before {
125
- content: '✓';
126
- }
127
-
128
- [data-scope='checkbox-group'][data-part='trigger'][data-state='some']::before {
129
- content: '−';
120
+ [data-scope='checkbox-group'][data-part='indicator'][data-state='checked']:empty::before {
121
+ content: '';
122
+ display: inline-block;
123
+ inline-size: var(--xh-icon-size, var(--xh-glyph-size-text));
124
+ block-size: var(--xh-icon-size, var(--xh-glyph-size-text));
125
+ vertical-align: var(--xh-glyph-baseline-shift);
126
+ background-color: currentColor;
127
+ -webkit-mask: var(--xh-glyph-mark-check) center / contain no-repeat;
128
+ mask: var(--xh-glyph-mark-check) center / contain no-repeat;
129
+ }
130
+
131
+ /* 全选格的三态:checked 打勾、indeterminate 打横杠、unchecked 留空。
132
+ indeterminate 就是读屏听到的 aria-checked=mixed,两者同源,样式只认 data-state。
133
+
134
+ 字形走 ::after 而不是画方框的那颗 ::before:mask 会把所在元素的描边与底色一并裁成
135
+ 字形的轮廓,写在 ::before 上就等于把方框本身裁没了,只剩一枚白勾。条目那一侧是
136
+ 真实节点当方框、它的 ::before 当字形的两层结构,这里 anatomy 到 trigger 为止、
137
+ 没有第二个节点,只能用第二个伪元素补上那一层。
138
+ 方框是行首那颗 ::before、宽度即指示符尺寸,所以字形按「盒与字形的宽度差之半」
139
+ 内推即落在圆心;纵向靠 inset-block: 0 + margin-block: auto 居中。
140
+ font-size 与 ::before 同值,--xh-icon-size 的 1em 兜底才和条目那侧量得一样大 */
141
+ [data-scope='checkbox-group'][data-part='trigger'][data-state='checked']::after {
142
+ content: '';
143
+ position: absolute;
144
+ inset-block: 0;
145
+ inset-inline-start: 0;
146
+ margin-block: auto;
147
+ margin-inline-start: calc(
148
+ (
149
+ var(--xh-checkbox-group-indicator-size, var(--xh-control-indicator-size)) -
150
+ var(--xh-icon-size, var(--xh-glyph-size-text))
151
+ ) / 2
152
+ );
153
+ inline-size: var(--xh-icon-size, var(--xh-glyph-size-text));
154
+ block-size: var(--xh-icon-size, var(--xh-glyph-size-text));
155
+ background-color: var(--xh-checkbox-group-indicator-fg, var(--xh-fg-on-brand));
156
+ font-size: var(--xh-checkbox-group-indicator-font-size, calc(var(--xh-control-indicator-size) * 0.75));
157
+ -webkit-mask: var(--xh-glyph-mark-check) center / contain no-repeat;
158
+ mask: var(--xh-glyph-mark-check) center / contain no-repeat;
159
+ }
160
+
161
+ [data-scope='checkbox-group'][data-part='trigger'][data-state='indeterminate']::after {
162
+ content: '';
163
+ position: absolute;
164
+ inset-block: 0;
165
+ inset-inline-start: 0;
166
+ margin-block: auto;
167
+ margin-inline-start: calc(
168
+ (
169
+ var(--xh-checkbox-group-indicator-size, var(--xh-control-indicator-size)) -
170
+ var(--xh-icon-size, var(--xh-glyph-size-text))
171
+ ) / 2
172
+ );
173
+ inline-size: var(--xh-icon-size, var(--xh-glyph-size-text));
174
+ block-size: var(--xh-icon-size, var(--xh-glyph-size-text));
175
+ background-color: var(--xh-checkbox-group-indicator-fg, var(--xh-fg-on-brand));
176
+ font-size: var(--xh-checkbox-group-indicator-font-size, calc(var(--xh-control-indicator-size) * 0.75));
177
+ -webkit-mask: var(--xh-glyph-mark-minus) center / contain no-repeat;
178
+ mask: var(--xh-glyph-mark-minus) center / contain no-repeat;
130
179
  }
131
180
 
132
181
  /* 校验失败标在每个方框上:root 上的 data-invalid 是唯一出处,条目自己不带这个属性 */
133
182
  [data-scope='checkbox-group'][data-part='root'][data-invalid]
134
183
  [data-scope='checkbox-group'][data-part='indicator'] {
135
- border-color: var(--xh-checkbox-group-indicator-border-invalid, var(--xh-color-danger-500));
184
+ border-color: var(--xh-checkbox-group-indicator-border-invalid, var(--xh-border-invalid));
136
185
  }
137
186
 
138
187
  [data-scope='checkbox-group'][data-part='item-text'] {
@@ -141,8 +190,10 @@
141
190
  }
142
191
 
143
192
  /* 全选格与条目同形,但字重加一档,读起来才不像又一个普通选项。
144
- 它是普通元素而非原生控件(三态只有非原生控件表达得出),禁用态同样只能读 data-disabled */
193
+ 它是普通元素而非原生控件(三态只有非原生控件表达得出),禁用态同样只能读 data-disabled
194
+ position 是给叠在方框上的那颗字形 ::after 当定位基准 */
145
195
  [data-scope='checkbox-group'][data-part='trigger'] {
196
+ position: relative;
146
197
  display: inline-flex;
147
198
  align-items: center;
148
199
  gap: var(--xh-checkbox-group-trigger-gap, var(--xh-control-gap-md));
@@ -163,7 +214,6 @@
163
214
  [data-scope='checkbox-group'][data-part='trigger'][data-disabled] {
164
215
  color: var(--xh-checkbox-group-trigger-fg-disabled, var(--xh-fg-disabled));
165
216
  cursor: not-allowed;
166
- opacity: var(--xh-state-disabled-opacity);
167
217
  }
168
218
 
169
219
  /* 只读与禁用会同时出现在 trigger 上(连接层两个属性各写各的),
package/css/checkbox.css CHANGED
@@ -5,9 +5,12 @@
5
5
  }
6
6
 
7
7
  [data-scope='checkbox'][data-part='root'] {
8
+ /* 作者塞进指示符槽的图标跟着字号走,与皮肤画的兜底字形同一把尺 */
9
+ --xh-icon-size: var(--xh-checkbox-icon-size, var(--xh-glyph-size-text));
10
+
8
11
  /* 尺寸档只换方框边长这一个私有槽,勾的字号按边长的比例跟着走;
9
12
  指示器从 root 继承这两个槽,换档不必给每个部件各写一条选择器 */
10
- --xh-_checkbox-box: var(--xh-space-4);
13
+ --xh-_checkbox-box: var(--xh-control-indicator-md);
11
14
  --xh-_checkbox-glyph: calc(var(--xh-_checkbox-box) * 0.75);
12
15
 
13
16
  /* 选中态的底与描边随语气走。没写 data-tone 时 --xh-_tone 没被声明,退回原来的品牌色 */
@@ -23,8 +26,8 @@
23
26
  inline-size: var(--xh-_checkbox-box);
24
27
  block-size: var(--xh-_checkbox-box);
25
28
  padding: 0;
26
- border: 1px solid var(--xh-checkbox-border, var(--xh-border-control));
27
- 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-checkbox-radius, var(--xh-shape-inset));
28
31
  background: var(--xh-checkbox-bg, var(--xh-bg-canvas));
29
32
  color: var(--xh-checkbox-fg, var(--xh-_checkbox-on-accent));
30
33
  cursor: pointer;
@@ -34,13 +37,27 @@
34
37
  }
35
38
 
36
39
  /* 半选与全选同样是「有值」,方框都得填上:
37
- 只填全选的话,半选那条横杠是实心底上的前景色(白),压在白画布上等于没画 */
40
+ 只填全选的话,半选那条横杠是实心底上的前景色,压在同色画布上等于没画 */
38
41
  [data-scope='checkbox'][data-part='root'][data-state='checked'],
39
42
  [data-scope='checkbox'][data-part='root'][data-state='indeterminate'] {
40
43
  border-color: var(--xh-checkbox-border-checked, var(--xh-_checkbox-accent));
41
44
  background: var(--xh-checkbox-bg-checked, var(--xh-_checkbox-accent));
42
45
  }
43
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
+
44
61
  [data-scope='checkbox'][data-part='root'][data-disabled] {
45
62
  cursor: not-allowed;
46
63
  opacity: var(--xh-state-disabled-opacity);
@@ -54,11 +71,11 @@
54
71
  /* —— 尺寸 —— */
55
72
  /* 缺省档写在上面的基础规则里 */
56
73
  [data-scope='checkbox'][data-part='root'][data-size='sm'] {
57
- --xh-_checkbox-box: var(--xh-space-3);
74
+ --xh-_checkbox-box: var(--xh-control-indicator-sm);
58
75
  }
59
76
 
60
77
  [data-scope='checkbox'][data-part='root'][data-size='lg'] {
61
- --xh-_checkbox-box: var(--xh-space-5);
78
+ --xh-_checkbox-box: var(--xh-control-indicator-lg);
62
79
  }
63
80
 
64
81
  [data-scope='checkbox'][data-part='indicator'] {
@@ -71,15 +88,25 @@
71
88
  font-size: var(--xh-_checkbox-glyph);
72
89
  }
73
90
 
74
- [data-scope='checkbox'][data-part='indicator']::before {
75
- 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;
76
101
  }
77
102
 
78
103
  [data-scope='checkbox'][data-part='indicator'][data-state='unchecked'] {
79
104
  display: none;
80
105
  }
81
106
 
82
- /* 半选画一条横杠盖住勾:aria-checked=mixed 在视觉上也得与「全选」分得开 */
107
+ /* 半选换一枚横杠字形盖住勾:aria-checked=mixed 在视觉上也得与「全选」分得开。
108
+ 横杠与勾同走字形令牌,作者换掉标记时两态一起换;此前这条是手画的几何盒
109
+ (60% × stroke-thick),同一页上会出现两种横杠 */
83
110
  [data-scope='checkbox'][data-part='indicator'][data-state='indeterminate'] {
84
111
  position: relative;
85
112
  color: transparent;
@@ -87,10 +114,40 @@
87
114
 
88
115
  [data-scope='checkbox'][data-part='indicator'][data-state='indeterminate']::after {
89
116
  position: absolute;
90
- inline-size: 60%;
91
- block-size: var(--xh-stroke-thick);
92
- border-radius: var(--xh-radius-full);
93
- background: var(--xh-checkbox-indicator-fg, var(--xh-_checkbox-on-accent));
117
+ inline-size: var(--xh-icon-size, var(--xh-glyph-size-text));
118
+ block-size: var(--xh-icon-size, var(--xh-glyph-size-text));
119
+ background-color: var(--xh-checkbox-indicator-fg, var(--xh-_checkbox-on-accent));
94
120
  content: '';
121
+ -webkit-mask: var(--xh-glyph-mark-minus) center / contain no-repeat;
122
+ mask: var(--xh-glyph-mark-minus) center / contain no-repeat;
123
+ }
124
+
125
+ /* —— 带文字的整行:<label> 包住控件与文字,与 checkbox-group 的条目同一副样子 —— */
126
+ [data-scope='checkbox'][data-part='label'] {
127
+ display: inline-flex;
128
+ align-items: center;
129
+ gap: var(--xh-checkbox-label-gap, var(--xh-control-gap-md));
130
+ color: var(--xh-checkbox-label-fg, var(--xh-fg-default));
131
+ font-size: var(--xh-checkbox-label-font-size, var(--xh-text-label-size));
132
+ line-height: var(--xh-leading-none);
133
+ cursor: pointer;
134
+ }
135
+
136
+ [data-scope='checkbox'][data-part='label'][data-disabled] {
137
+ color: var(--xh-checkbox-label-fg-disabled, var(--xh-fg-disabled));
138
+ cursor: not-allowed;
139
+ }
140
+
141
+ [data-scope='checkbox'][data-part='text'] {
142
+ color: inherit;
143
+ user-select: none;
144
+ }
145
+
146
+ /* 声明过任何 display 就盖掉了 UA 的 [hidden]{display:none},收起态得自己还回去。
147
+ 写在文件末尾:兜底必须排在该部件所有 display 声明之后 */
148
+ [data-scope='checkbox'][data-part='root'][hidden],
149
+ [data-scope='checkbox'][data-part='indicator'][hidden],
150
+ [data-scope='checkbox'][data-part='label'][hidden] {
151
+ display: none;
95
152
  }
96
153
  }
package/css/clipboard.css CHANGED
@@ -39,7 +39,7 @@
39
39
  }
40
40
 
41
41
  [data-scope='clipboard'][data-part='input'] {
42
- 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));
43
43
  block-size: var(--xh-clipboard-input-h, var(--xh-control-h-md));
44
44
  padding-inline: var(--xh-clipboard-input-px, var(--xh-control-px-md));
45
45
  padding-block: 0;
@@ -58,6 +58,7 @@
58
58
  }
59
59
 
60
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)));
61
62
  outline: var(--xh-ring-width) solid var(--xh-ring-focus);
62
63
  outline-offset: var(--xh-ring-offset);
63
64
  }
@@ -50,15 +50,20 @@
50
50
  white-space: pre;
51
51
  }
52
52
 
53
- /* 语法配色。令牌集里没有语法色这一类,所以就地声明成可覆盖的变量:
54
- 注释与标点复用既有语义色,只有三种真需要色相的走 light-dark()。
55
- 浏览器不认 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-* 语法令牌(随主题明暗切换)。 */
56
61
  [data-scope='code-block'][data-part='root'] {
57
62
  --xh-code-block-comment-fg: var(--xh-fg-muted);
58
63
  --xh-code-block-punctuation-fg: var(--xh-fg-subtle);
59
- --xh-code-block-string-fg: light-dark(#0a7f5f, #7ee2b8);
60
- --xh-code-block-number-fg: light-dark(#9a5b00, #f0b866);
61
- --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);
62
67
  }
63
68
 
64
69
  /* 记号本身不带任何布局,只上色:它是 <code> 里的行内片段,多一点盒模型都会破坏对齐 */
@@ -77,7 +82,7 @@
77
82
 
78
83
  [data-scope='code-block'][data-part='token'][data-kind='keyword'] {
79
84
  color: var(--xh-code-block-keyword-fg);
80
- font-weight: var(--xh-code-block-keyword-weight, 600);
85
+ font-weight: var(--xh-code-block-keyword-weight, var(--xh-font-weight-semibold));
81
86
  }
82
87
 
83
88
  [data-scope='code-block'][data-part='token'][data-kind='punctuation'] {
@@ -10,7 +10,7 @@
10
10
  --xh-_collapsible-trigger-h: var(--xh-control-h-md);
11
11
  --xh-_collapsible-trigger-px: var(--xh-control-px-md);
12
12
  --xh-_collapsible-trigger-gap: var(--xh-control-gap-md);
13
- --xh-_collapsible-trigger-font-size: var(--xh-text-label-size);
13
+ --xh-_collapsible-trigger-font-size: var(--xh-control-font-md);
14
14
  }
15
15
 
16
16
  /* —— 尺寸 —— */
@@ -19,14 +19,14 @@
19
19
  --xh-_collapsible-trigger-h: var(--xh-control-h-sm);
20
20
  --xh-_collapsible-trigger-px: var(--xh-control-px-sm);
21
21
  --xh-_collapsible-trigger-gap: var(--xh-control-gap-sm);
22
- --xh-_collapsible-trigger-font-size: var(--xh-font-size-sm);
22
+ --xh-_collapsible-trigger-font-size: var(--xh-control-font-sm);
23
23
  }
24
24
 
25
25
  [data-scope='collapsible'][data-part='root'][data-size='lg'] {
26
26
  --xh-_collapsible-trigger-h: var(--xh-control-h-lg);
27
27
  --xh-_collapsible-trigger-px: var(--xh-control-px-lg);
28
28
  --xh-_collapsible-trigger-gap: var(--xh-control-gap-lg);
29
- --xh-_collapsible-trigger-font-size: var(--xh-font-size-lg);
29
+ --xh-_collapsible-trigger-font-size: var(--xh-control-font-lg);
30
30
  }
31
31
 
32
32
  [data-scope='collapsible'][data-part='trigger'] {
@@ -61,8 +61,54 @@
61
61
  opacity: var(--xh-state-disabled-opacity);
62
62
  }
63
63
 
64
+ /* 这里刻意没有 [data-part='content'][hidden] { display: none }:补了动画一帧都播不出来。
65
+ 收起由适配器在退场结束后写内联 display 落成,退场窗口内靠 connect 发的 inert 挡住焦点 */
64
66
  [data-scope='collapsible'][data-part='content'] {
67
+ display: grid;
68
+ grid-template-rows: 1fr;
69
+ overflow: clip;
65
70
  padding-block: var(--xh-collapsible-content-py, var(--xh-stack-gap-md));
66
71
  color: var(--xh-collapsible-content-fg, var(--xh-fg-default));
67
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
+ }
108
+
109
+ /* 声明过任何 display 就盖掉了 UA 的 [hidden]{display:none},收起态得自己还回去。
110
+ 写在文件末尾:兜底必须排在该部件所有 display 声明之后 */
111
+ [data-scope='collapsible'][data-part='trigger'][hidden] {
112
+ display: none;
113
+ }
68
114
  }