@xihan-ui/styles 1.0.0 → 2.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 (171) hide show
  1. package/CHANGELOG.md +5146 -6
  2. package/README.md +22 -2
  3. package/component-tokens.d.ts +4212 -0
  4. package/component-tokens.js +2 -0
  5. package/components.tokens.json +80116 -0
  6. package/css/accordion.css +131 -75
  7. package/css/affix.css +16 -1
  8. package/css/alert.css +114 -67
  9. package/css/anchor.css +99 -27
  10. package/css/approval.css +461 -0
  11. package/css/avatar-group.css +14 -6
  12. package/css/avatar.css +33 -9
  13. package/css/back-top.css +103 -48
  14. package/css/badge.css +42 -14
  15. package/css/bar-code.css +62 -0
  16. package/css/breadcrumb.css +40 -21
  17. package/css/button-group.css +146 -24
  18. package/css/button.css +116 -99
  19. package/css/calendar-picker.css +448 -0
  20. package/css/calendar-range-picker.css +517 -0
  21. package/css/card.css +54 -77
  22. package/css/carousel.css +412 -68
  23. package/css/cascader.css +429 -246
  24. package/css/checkbox-group.css +225 -77
  25. package/css/checkbox.css +174 -37
  26. package/css/clipboard.css +266 -47
  27. package/css/code-view.css +279 -0
  28. package/css/collapsible.css +108 -63
  29. package/css/color-field.css +158 -0
  30. package/css/color-picker.css +172 -184
  31. package/css/color-slider.css +274 -0
  32. package/css/color-swatch-picker.css +243 -0
  33. package/css/color-swatch.css +35 -0
  34. package/css/combobox.css +267 -273
  35. package/css/command.css +399 -0
  36. package/css/context-menu.css +183 -108
  37. package/css/date-field.css +94 -121
  38. package/css/date-picker.css +486 -249
  39. package/css/date-range-picker.css +559 -0
  40. package/css/description.css +51 -0
  41. package/css/descriptions.css +133 -87
  42. package/css/dialog.css +247 -68
  43. package/css/diff-view.css +428 -0
  44. package/css/download-trigger.css +155 -46
  45. package/css/drawer.css +194 -111
  46. package/css/editable.css +172 -152
  47. package/css/empty-state.css +80 -11
  48. package/css/field-array.css +190 -0
  49. package/css/field.css +84 -31
  50. package/css/fieldset.css +51 -18
  51. package/css/file-upload.css +134 -36
  52. package/css/flex.css +20 -1
  53. package/css/float-button.css +238 -57
  54. package/css/floating-panel.css +173 -92
  55. package/css/focus.css +46 -0
  56. package/css/forced-colors.css +93 -0
  57. package/css/form.css +254 -77
  58. package/css/gradient-text.css +34 -10
  59. package/css/grid.css +516 -5
  60. package/css/heatmap.css +87 -29
  61. package/css/highlight.css +20 -5
  62. package/css/hover-card.css +97 -47
  63. package/css/icon-wrapper.css +15 -3
  64. package/css/icon.css +74 -8
  65. package/css/image-cropper.css +143 -29
  66. package/css/image-viewer.css +150 -89
  67. package/css/image.css +30 -1
  68. package/css/infinite-scroll.css +51 -1
  69. package/css/input-group.css +277 -0
  70. package/css/json-viewer.css +102 -45
  71. package/css/kbd.css +72 -0
  72. package/css/label.css +78 -0
  73. package/css/layers.css +5 -0
  74. package/css/layout.css +175 -31
  75. package/css/list.css +24 -3
  76. package/css/listbox.css +208 -67
  77. package/css/loading-bar.css +52 -3
  78. package/css/log.css +144 -9
  79. package/css/markdown-stream.css +149 -0
  80. package/css/marquee.css +27 -1
  81. package/css/masonry.css +7 -0
  82. package/css/matrix-code.css +67 -0
  83. package/css/mention.css +234 -152
  84. package/css/menu.css +180 -83
  85. package/css/menubar.css +204 -136
  86. package/css/message-feed.css +197 -0
  87. package/css/navigation-menu.css +144 -90
  88. package/css/notification.css +178 -100
  89. package/css/number-animation.css +7 -0
  90. package/css/number-field.css +120 -277
  91. package/css/overlay-arrow.css +12 -7
  92. package/css/page-header.css +99 -14
  93. package/css/pagination.css +175 -135
  94. package/css/password-input.css +222 -219
  95. package/css/pin-input.css +101 -67
  96. package/css/pointer.css +36 -0
  97. package/css/popconfirm.css +185 -94
  98. package/css/popover.css +121 -77
  99. package/css/progress.css +60 -12
  100. package/css/prompt-input.css +224 -0
  101. package/css/question-flow.css +513 -0
  102. package/css/radio-group.css +147 -30
  103. package/css/rating.css +193 -43
  104. package/css/reasoning.css +336 -0
  105. package/css/reset.css +84 -6
  106. package/css/resizable.css +237 -0
  107. package/css/scroll-area.css +68 -7
  108. package/css/scrollbar.css +47 -13
  109. package/css/segmented.css +94 -29
  110. package/css/select.css +288 -274
  111. package/css/separator.css +101 -1
  112. package/css/side-nav.css +133 -75
  113. package/css/signature-pad.css +74 -54
  114. package/css/skeleton.css +84 -11
  115. package/css/slider.css +132 -39
  116. package/css/sortable.css +198 -0
  117. package/css/spinner.css +126 -12
  118. package/css/splitter.css +29 -8
  119. package/css/statistic.css +55 -0
  120. package/css/steps.css +206 -72
  121. package/css/switch.css +268 -36
  122. package/css/table.css +695 -118
  123. package/css/tabs.css +604 -42
  124. package/css/tag-group.css +219 -0
  125. package/css/tag.css +118 -28
  126. package/css/tags-input.css +156 -274
  127. package/css/text-field.css +101 -249
  128. package/css/time-field.css +100 -128
  129. package/css/time-picker.css +323 -252
  130. package/css/time-range-picker.css +719 -0
  131. package/css/timeline.css +202 -68
  132. package/css/timer.css +56 -52
  133. package/css/timestamp.css +34 -0
  134. package/css/toast.css +373 -144
  135. package/css/toggle-group.css +309 -76
  136. package/css/toggle.css +116 -85
  137. package/css/tone.css +47 -0
  138. package/css/tool-call.css +421 -0
  139. package/css/toolbar.css +181 -33
  140. package/css/tooltip.css +107 -36
  141. package/css/tour.css +183 -152
  142. package/css/transfer.css +351 -138
  143. package/css/tree-select.css +323 -216
  144. package/css/tree.css +294 -62
  145. package/css/truncate.css +65 -0
  146. package/css/typography.css +228 -5
  147. package/css/undefined.css +10 -1
  148. package/css/virtualizer.css +9 -10
  149. package/css/visually-hidden.css +7 -0
  150. package/css/watermark.css +7 -0
  151. package/family/action-control.css +487 -0
  152. package/family/collection-item.css +721 -0
  153. package/family/field-chrome.css +298 -0
  154. package/family/motion.css +166 -0
  155. package/family/swatch.css +59 -0
  156. package/index.css +41705 -126
  157. package/index.unlayered.css +33692 -17339
  158. package/package.json +51 -17
  159. package/css/calendar.css +0 -367
  160. package/css/code-block.css +0 -91
  161. package/css/composer.css +0 -134
  162. package/css/countdown.css +0 -26
  163. package/css/dynamic-input.css +0 -220
  164. package/css/ellipsis.css +0 -52
  165. package/css/hotkeys.css +0 -90
  166. package/css/popselect.css +0 -391
  167. package/css/qr-code.css +0 -55
  168. package/css/result.css +0 -119
  169. package/css/space.css +0 -117
  170. package/css/thread.css +0 -120
  171. package/css/time.css +0 -25
package/css/accordion.css CHANGED
@@ -1,3 +1,15 @@
1
+ /*
2
+ * Copyright (c) 2021-Present XiHanFun and contributors.
3
+ * Licensed under the MIT License. See LICENSE in the project root for license information.
4
+ */
5
+
6
+ /* 定义 accordion 样式。 */
7
+
8
+ /* 共享关键帧由 family/motion.css 提供,本皮肤 @import 它,单独引入仍成立;
9
+ 独立皮肤同时传递引入标题栏的动作控件配方,full bundle 递归去重。 */
10
+ @import '../family/motion.css';
11
+ @import '../family/action-control.css';
12
+
1
13
  @layer xihan.components {
2
14
  /* 皮肤在场的标记:开发模式下按 scope 探一次,取不到就说明这份皮肤没被引入。 */
3
15
  [data-scope='accordion'] {
@@ -5,14 +17,12 @@
5
17
  }
6
18
 
7
19
  [data-scope='accordion'][data-part='root'] {
8
- /* 作者塞进指示符槽的图标跟着字号走,与皮肤画的兜底字形同一把尺 */
9
- --xh-icon-size: var(--xh-accordion-icon-size, var(--xh-glyph-size-text));
20
+ /* 作者塞进正文里的图标与皮肤画的兜底字形同一把尺:md 档(§6.5),标题栏上另按家族档取值 */
21
+ --xh-icon-size: var(--xh-accordion-icon-size, var(--xh-glyph-size-md));
10
22
 
11
- /* 尺寸档只换这四个私有槽,标题栏从 root 继承它们,换档不必给每个部件各写一条选择器 */
12
- --xh-_accordion-trigger-h: var(--xh-control-h-md);
13
- --xh-_accordion-trigger-px: var(--xh-control-px-md);
14
- --xh-_accordion-trigger-gap: var(--xh-control-gap-md);
15
- --xh-_accordion-trigger-font-size: var(--xh-control-font-md);
23
+ /* 尺寸档只换正文这两个私有槽,正文从 root 继承它们;标题栏的三档几何由家族 disclosure-trigger 档给 */
24
+ --xh-_accordion-content-px: var(--xh-space-4);
25
+ --xh-_accordion-content-pb: var(--xh-space-4);
16
26
 
17
27
  /* 语气落在展开着的标题上,指示器写在标题里、跟着继承这个色,不另立规则。
18
28
  没写 data-tone 时 --xh-_tone-fg 没被声明,退回原来的前景色。
@@ -22,6 +32,7 @@
22
32
  display: flex;
23
33
  flex-direction: column;
24
34
  inline-size: 100%;
35
+ contain: layout style;
25
36
  }
26
37
 
27
38
  [data-scope='accordion'][data-part='root'][data-orientation='horizontal'] {
@@ -31,20 +42,17 @@
31
42
  /* —— 尺寸 —— */
32
43
  /* 缺省档写在上面的基础规则里 */
33
44
  [data-scope='accordion'][data-part='root'][data-size='sm'] {
34
- --xh-_accordion-trigger-h: var(--xh-control-h-sm);
35
- --xh-_accordion-trigger-px: var(--xh-control-px-sm);
36
- --xh-_accordion-trigger-gap: var(--xh-control-gap-sm);
37
- --xh-_accordion-trigger-font-size: var(--xh-control-font-sm);
45
+ --xh-_accordion-content-px: var(--xh-space-3);
46
+ --xh-_accordion-content-pb: var(--xh-space-3);
38
47
  }
39
48
 
40
49
  [data-scope='accordion'][data-part='root'][data-size='lg'] {
41
- --xh-_accordion-trigger-h: var(--xh-control-h-lg);
42
- --xh-_accordion-trigger-px: var(--xh-control-px-lg);
43
- --xh-_accordion-trigger-gap: var(--xh-control-gap-lg);
44
- --xh-_accordion-trigger-font-size: var(--xh-control-font-lg);
50
+ --xh-_accordion-content-px: var(--xh-space-5);
51
+ --xh-_accordion-content-pb: var(--xh-space-5);
45
52
  }
46
53
 
47
54
  [data-scope='accordion'][data-part='item'] {
55
+ position: relative;
48
56
  min-inline-size: 0;
49
57
  }
50
58
 
@@ -64,46 +72,109 @@
64
72
  border-inline-start: var(--xh-stroke-thin) solid var(--xh-accordion-item-border, var(--xh-border-subtle));
65
73
  }
66
74
 
67
- [data-scope='accordion'][data-part='header'] {
75
+ /* 作者显式渲染的分隔线。渲染了它,上面那条 item + item 的相邻规则就不再命中,
76
+ 两条线不会同时出现 */
77
+ [data-scope='accordion'][data-part='item-separator'] {
78
+ flex: none;
79
+ block-size: var(--xh-stroke-thin);
80
+ border: 0;
68
81
  margin: 0;
69
- font: inherit;
82
+ background: var(--xh-accordion-item-border, var(--xh-border-subtle));
70
83
  }
71
84
 
72
- [data-scope='accordion'][data-part='trigger'] {
73
- display: inline-flex;
74
- align-items: center;
75
- justify-content: space-between;
76
- inline-size: 100%;
77
- gap: var(--xh-accordion-trigger-gap, var(--xh-_accordion-trigger-gap));
78
- block-size: var(--xh-accordion-trigger-h, var(--xh-_accordion-trigger-h));
79
- padding-inline: var(--xh-accordion-trigger-px, var(--xh-_accordion-trigger-px));
80
- border: 0;
81
- border-radius: var(--xh-accordion-trigger-radius, var(--xh-shape-control));
82
- background: var(--xh-accordion-trigger-bg, transparent);
83
- color: var(--xh-accordion-trigger-fg, var(--xh-fg-default));
84
- font-size: var(--xh-accordion-trigger-font-size, var(--xh-_accordion-trigger-font-size));
85
- font-weight: var(--xh-accordion-trigger-font-weight, var(--xh-text-label-weight));
86
- line-height: var(--xh-leading-none);
87
- cursor: pointer;
85
+ [data-scope='accordion'][data-part='item-separator'][hidden] {
86
+ display: none;
88
87
  }
89
88
 
90
- [data-scope='accordion'][data-part='trigger']:hover {
91
- background: var(--xh-accordion-trigger-bg-hover, var(--xh-bg-subtle));
89
+ [data-scope='accordion'][data-part='root'][data-orientation='horizontal']
90
+ > [data-scope='accordion'][data-part='item-separator'] {
91
+ block-size: auto;
92
+ inline-size: var(--xh-stroke-thin);
92
93
  }
93
94
 
94
- [data-scope='accordion'][data-part='trigger']:focus-visible {
95
- outline: var(--xh-ring-width) solid var(--xh-ring-focus);
96
- outline-offset: var(--xh-ring-offset);
95
+ /* —— 形态 —— */
96
+ /* ghost 档不在这儿:它就是上面那套基础取值,写不写 data-variant 都长一个样 */
97
+ /* 整份有了一块面,条与条之间就不再靠那条相邻边分开 */
98
+ [data-scope='accordion'][data-part='root']:is([data-variant='outline'], [data-variant='subtle'])
99
+ > [data-scope='accordion'][data-part='item']
100
+ + [data-scope='accordion'][data-part='item'] {
101
+ border-block-start: 0;
102
+ border-inline-start: 0;
97
103
  }
98
104
 
105
+ /* outline:一张静态内容面,--xh-border-default 描边 + surface 底 + 无影(§5.3 边界只由描边承担);
106
+ 根的外边走 --xh-accordion-border,与条与条之间的分隔线槽 --xh-accordion-item-border 各管各的 */
107
+ [data-scope='accordion'][data-part='root'][data-variant='outline'] {
108
+ border: var(--xh-stroke-thin) solid var(--xh-accordion-border, var(--xh-border-default));
109
+ border-radius: var(--xh-accordion-item-radius, var(--xh-shape-surface));
110
+ background: var(--xh-accordion-item-bg, var(--xh-bg-surface));
111
+ box-shadow: var(--xh-accordion-item-shadow, none);
112
+ overflow: clip;
113
+ }
114
+
115
+ /* subtle:同一块连续表面,底换成淡底,描边让位给底色但留住 1px 边位(三档几何一致);
116
+ 淡底承载面向标题栏下发 hover 200 → pressed 300(§7.2) */
117
+ [data-scope='accordion'][data-part='root'][data-variant='subtle'] {
118
+ --xh-action-host-bg-hover: var(--xh-bg-subtle-hover);
119
+ --xh-action-host-bg-pressed: var(--xh-bg-subtle-active);
120
+
121
+ border: var(--xh-stroke-thin) solid transparent;
122
+ border-radius: var(--xh-accordion-item-radius, var(--xh-shape-surface));
123
+ background: var(--xh-accordion-item-bg, var(--xh-bg-subtle));
124
+ box-shadow: var(--xh-accordion-item-shadow, none);
125
+ overflow: clip;
126
+ }
127
+
128
+ [data-scope='accordion'][data-part='root']:is([data-variant='outline'], [data-variant='subtle'])
129
+ > [data-scope='accordion'][data-part='item']:not(:last-child)::after {
130
+ content: '';
131
+ position: absolute;
132
+ inset-inline: 3%;
133
+ inset-block-end: 0;
134
+ block-size: var(--xh-stroke-thin);
135
+ background: var(--xh-accordion-item-border, var(--xh-border-subtle));
136
+ pointer-events: none;
137
+ }
138
+
139
+ [data-scope='accordion'][data-part='header'] {
140
+ margin: 0;
141
+ font: inherit;
142
+ }
143
+
144
+ /* 标题栏铺满一行,盒型、三档几何、悬停 / 按下 / 禁用面由 Action Control 的 disclosure-trigger 档给
145
+ (ghost 形态:白底承载 hover 100 → pressed 200,淡底容器由根下发 host 槽;按下只换面不缩放,§9.2);
146
+ 这里只把使用者槽映射到桥接槽:字色三态同值(家族的 hover / pressed 字色规则比皮肤更特定,不映射会被换回
147
+ 缺省字色),字形按标题栏自己的档位取 --xh-_action-profile-glyph-size;边归零贴住条目,几何与迁移前一致 */
148
+ [data-scope='accordion'][data-part='trigger'] {
149
+ --xh-action-gap: var(--xh-accordion-trigger-gap, var(--xh-_action-profile-gap));
150
+ --xh-action-visual-size: var(--xh-accordion-trigger-h, var(--xh-_action-profile-visual-size));
151
+ --xh-action-padding-block: var(--xh-accordion-trigger-py, var(--xh-_action-profile-padding-block));
152
+ --xh-action-padding-inline: var(--xh-accordion-trigger-px, var(--xh-_action-profile-padding-inline));
153
+ --xh-action-radius: var(--xh-accordion-trigger-radius, var(--xh-_action-profile-radius));
154
+ --xh-action-bg-rest: var(--xh-accordion-trigger-bg, var(--xh-_action-variant-bg-rest));
155
+ --xh-action-bg-hover: var(--xh-accordion-trigger-bg-hover, var(--xh-_action-variant-bg-hover));
156
+ --xh-action-fg-rest: var(--xh-accordion-trigger-fg, var(--xh-_action-variant-fg-rest));
157
+ --xh-action-fg-hover: var(--xh-accordion-trigger-fg, var(--xh-_action-variant-fg-hover));
158
+ --xh-action-fg-pressed: var(--xh-accordion-trigger-fg, var(--xh-_action-variant-fg-pressed));
159
+ --xh-action-font-size: var(--xh-accordion-trigger-font-size, var(--xh-_action-profile-font-size));
160
+ --xh-icon-size: var(--xh-accordion-icon-size, var(--xh-_action-profile-glyph-size));
161
+
162
+ border-width: 0;
163
+ font-weight: var(--xh-accordion-trigger-font-weight, var(--xh-text-label-weight));
164
+ }
165
+
166
+ /* 展开态自带一个槽:与常态共用一个的话,作者一改常态字色,
167
+ 展开那一档的语气高亮就跟着被抹平,再也分不开。悬停 / 按下的面与收起态同档(§7.3 open 与家族 hover 同档中性) */
99
168
  [data-scope='accordion'][data-part='trigger'][data-state='open'] {
100
- color: var(--xh-accordion-trigger-fg, var(--xh-_accordion-open-fg));
169
+ --xh-action-fg-rest: var(--xh-accordion-trigger-fg-open, var(--xh-_accordion-open-fg));
170
+ --xh-action-fg-hover: var(--xh-accordion-trigger-fg-open, var(--xh-_accordion-open-fg));
171
+ --xh-action-fg-pressed: var(--xh-accordion-trigger-fg-open, var(--xh-_accordion-open-fg));
101
172
  }
102
173
 
103
- /* 禁用条目走 aria-disabled,仍留在 Tab 序里,只是不可操作 */
174
+ /* 禁用条目走 aria-disabled,仍留在 Tab 序里,只是不可操作;前景换成禁用色,不靠 opacity 压暗
175
+ (家族按 data-disabled 给禁用面与指针,字色槽在这里保留优先) */
104
176
  [data-scope='accordion'][data-part='trigger'][data-disabled] {
105
- cursor: not-allowed;
106
- opacity: var(--xh-state-disabled-opacity);
177
+ --xh-action-fg-disabled: var(--xh-accordion-trigger-fg-disabled, var(--xh-_action-variant-fg-disabled));
107
178
  }
108
179
 
109
180
  [data-scope='accordion'][data-part='indicator'] {
@@ -111,16 +182,18 @@
111
182
  align-items: center;
112
183
  justify-content: center;
113
184
  flex: none;
185
+ color: var(--xh-accordion-indicator-fg, var(--xh-fg-muted));
114
186
  line-height: var(--xh-leading-none);
115
- transition: rotate var(--xh-motion-duration-micro) var(--xh-motion-ease-enter);
187
+ /* 指示器与正文同档转向(§9.4):正文 enter 档展开,箭头也用同一段时长翻过去 */
188
+ transition: rotate var(--xh-motion-duration-enter) var(--xh-motion-ease-enter-strong);
116
189
  }
117
190
 
118
191
  /* 没写内容就由皮肤画;作者往部件里塞了自己的图形,这条规则即不命中 */
119
192
  [data-scope='accordion'][data-part='indicator']:empty::before {
120
193
  content: '';
121
194
  display: inline-block;
122
- inline-size: var(--xh-icon-size, var(--xh-glyph-size-text));
123
- block-size: var(--xh-icon-size, var(--xh-glyph-size-text));
195
+ inline-size: var(--xh-icon-size, var(--xh-glyph-size-md));
196
+ block-size: var(--xh-icon-size, var(--xh-glyph-size-md));
124
197
  vertical-align: var(--xh-glyph-baseline-shift);
125
198
  background-color: currentColor;
126
199
  -webkit-mask: var(--xh-glyph-mark-chevron-down) center / contain no-repeat;
@@ -134,49 +207,32 @@
134
207
  /* 这里刻意没有 [data-part='content'][hidden] { display: none }:补了动画一帧都播不出来。
135
208
  收起由适配器在退场结束后写内联 display 落成,退场窗口内靠 connect 发的 inert 挡住焦点 */
136
209
  [data-scope='accordion'][data-part='content'] {
210
+ /* 行高与内缩同帧动的共享关键帧读这条槽:只有末端有内缩,起端不写、按 0 动 */
211
+ --xh-_disclosure-pb: var(--xh-accordion-content-pb, var(--xh-_accordion-content-pb));
212
+
137
213
  display: grid;
138
214
  grid-template-rows: 1fr;
139
215
  overflow: clip;
140
- padding-block: var(--xh-accordion-content-py, var(--xh-stack-gap-md));
141
- padding-inline: var(--xh-accordion-content-px, var(--xh-control-px-md));
142
- color: var(--xh-accordion-content-fg, var(--xh-fg-default));
216
+ padding-block-start: 0;
217
+ padding-block-end: var(--xh-accordion-content-pb, var(--xh-_accordion-content-pb));
218
+ padding-inline: var(--xh-accordion-content-px, var(--xh-_accordion-content-px));
219
+ color: var(--xh-accordion-content-fg, var(--xh-fg-muted));
220
+ font-size: var(--xh-accordion-content-font-size, var(--xh-text-secondary-size));
221
+ line-height: var(--xh-leading-normal);
143
222
  }
144
223
 
224
+ /* 展开那一档才提前备好行高这条通道:属性随 data-state 一起消失,收起后不长期占着 */
145
225
  [data-scope='accordion'][data-part='content'][data-state='open'] {
146
- animation: xh-accordion-expand var(--xh-motion-duration-enter) var(--xh-motion-ease-enter);
226
+ will-change: grid-template-rows;
227
+ animation: xh-disclosure-expand var(--xh-motion-duration-enter) var(--xh-motion-ease-enter-strong);
147
228
  }
148
229
 
149
230
  [data-scope='accordion'][data-part='content'][data-state='closed'] {
150
- animation: xh-accordion-collapse var(--xh-motion-duration-exit) var(--xh-motion-ease-exit) forwards;
231
+ animation: xh-disclosure-collapse var(--xh-motion-duration-exit) var(--xh-motion-ease-exit) forwards;
151
232
  }
152
233
  }
153
234
 
154
235
  @layer xihan.motion {
155
- /* 行高与内缩同帧动:内缩不归零的话,border-box 会把盒子钳在上下内缩之和上,收不干净 */
156
- @keyframes xh-accordion-expand {
157
- from {
158
- grid-template-rows: 0fr;
159
- padding-block: 0;
160
- }
161
-
162
- to {
163
- grid-template-rows: 1fr;
164
- padding-block: var(--xh-accordion-content-py, var(--xh-stack-gap-md));
165
- }
166
- }
167
-
168
- @keyframes xh-accordion-collapse {
169
- from {
170
- grid-template-rows: 1fr;
171
- padding-block: var(--xh-accordion-content-py, var(--xh-stack-gap-md));
172
- }
173
-
174
- to {
175
- grid-template-rows: 0fr;
176
- padding-block: 0;
177
- }
178
- }
179
-
180
236
  /* 声明过任何 display 就盖掉了 UA 的 [hidden]{display:none},收起态得自己还回去。
181
237
  写在文件末尾:兜底必须排在该部件所有 display 声明之后 */
182
238
  [data-scope='accordion'][data-part='root'][hidden],
package/css/affix.css CHANGED
@@ -1,3 +1,10 @@
1
+ /*
2
+ * Copyright (c) 2021-Present XiHanFun and contributors.
3
+ * Licensed under the MIT License. See LICENSE in the project root for license information.
4
+ */
5
+
6
+ /* 定义 affix 样式。 */
7
+
1
8
  @layer xihan.components {
2
9
  /* 皮肤在场的标记:开发模式下按 scope 探一次,取不到就说明这份皮肤没被引入。 */
3
10
  [data-scope='affix'] {
@@ -25,8 +32,16 @@
25
32
  * transform / filter / backdrop-filter / contain,包含块就被抢走,钉住的内容立刻贴错位置——
26
33
  * 所以别往覆盖钩子里加这几个属性。
27
34
  */
28
- [data-scope='affix'][data-part='content'][data-affixed] {
35
+ [data-scope='affix'][data-part='content'][data-fixed] {
29
36
  position: fixed;
30
37
  z-index: var(--xh-affix-layer, var(--xh-layer-sticky));
31
38
  }
39
+
40
+ @media print {
41
+ /* 打印:钉住的是作者自己的内容,不能收起;但保持 fixed 会让部分打印引擎每页重复一次,
42
+ 所以只把它放回正常流。 */
43
+ [data-scope='affix'][data-part='content'][data-fixed] {
44
+ position: static;
45
+ }
46
+ }
32
47
  }
package/css/alert.css CHANGED
@@ -1,29 +1,34 @@
1
+ /*
2
+ * Copyright (c) 2021-Present XiHanFun and contributors.
3
+ * Licensed under the MIT License. See LICENSE in the project root for license information.
4
+ */
5
+
6
+ /* 定义 alert 样式。 */
7
+
8
+ /* Alert 独立皮肤同时传递引入关闭钮的动作控件配方;full bundle 递归去重。 */
9
+ @import '../family/action-control.css';
10
+
1
11
  @layer xihan.components {
2
12
  /* 皮肤在场的标记:开发模式下按 scope 探一次,取不到就说明这份皮肤没被引入。 */
3
13
  [data-scope='alert'] {
4
14
  --xh-alert-skin: 1;
5
15
  }
6
16
 
17
+ /* 提示本体是一层中性 surface:边界由 --xh-border-default 描边承担、无影(§5.3 静态反馈面),
18
+ 语气只落到图标与标题,不会用整块彩底抢走正文层级。 */
7
19
  [data-scope='alert'][data-part='root'] {
8
- /* 作者塞进指示符槽的图标跟着字号走,与皮肤画的兜底字形同一把尺 */
9
- --xh-icon-size: var(--xh-alert-icon-size, var(--xh-glyph-size-text));
10
-
11
- /* 底色、描边、图标色一律取语气层派生好的槽:连接层给 alert 兜了 tone=info 的缺省,
12
- data-tone 恒在,语气层的槽也就恒被声明。此前这里自己又兑了一遍(12% / 32%),
13
- 与语气层的公式差一档,图标压上去只有 1.79–2.47 */
14
- --xh-_alert-tint: var(--xh-_tone-subtle);
15
- --xh-_alert-edge: var(--xh-_tone-border);
20
+ /* 作者塞进指示符槽的图标与皮肤画的兜底字形同一把尺:Feedback 指示符统一 md 档(§6.5) */
21
+ --xh-icon-size: var(--xh-alert-icon-size, var(--xh-glyph-size-md));
16
22
 
17
23
  display: flex;
18
- /* 说明用 flex: 1 1 100% 独占一行,容器不换行的话它只会挤在标题旁边 */
19
- flex-wrap: wrap;
20
24
  align-items: flex-start;
21
- gap: var(--xh-alert-gap, var(--xh-space-3));
22
- padding-block: var(--xh-alert-py, var(--xh-space-3));
23
- padding-inline: var(--xh-alert-px, var(--xh-space-4));
24
- border: var(--xh-stroke-thin) solid var(--xh-alert-border, var(--xh-_alert-edge));
25
+ gap: var(--xh-alert-gap, var(--xh-space-4));
26
+ padding-block: var(--xh-alert-py, var(--xh-surface-py-sm));
27
+ padding-inline: var(--xh-alert-px, var(--xh-surface-px-sm));
28
+ border: var(--xh-stroke-thin) solid var(--xh-alert-border, var(--xh-border-default));
25
29
  border-radius: var(--xh-alert-radius, var(--xh-shape-surface));
26
- background: var(--xh-alert-bg, var(--xh-_alert-tint));
30
+ background: var(--xh-alert-bg, var(--xh-bg-surface));
31
+ box-shadow: var(--xh-alert-shadow, none);
27
32
  color: var(--xh-alert-fg, var(--xh-fg-default));
28
33
  font-size: var(--xh-alert-font-size, var(--xh-text-body-size));
29
34
  line-height: var(--xh-alert-leading, var(--xh-leading-normal));
@@ -35,15 +40,40 @@
35
40
  display: none;
36
41
  }
37
42
 
38
- [data-scope='alert'][data-part='icon'] {
43
+ [data-scope='alert'][data-part='indicator'] {
39
44
  display: inline-flex;
40
45
  align-items: center;
41
46
  justify-content: center;
42
47
  flex: none;
43
- /* 与首行文字对齐:图标框高取一行正文的行高 */
44
- block-size: calc(var(--xh-text-body-size) * var(--xh-leading-normal));
45
- inline-size: var(--xh-alert-icon-box, var(--xh-control-indicator-size));
46
- color: var(--xh-alert-icon-fg, var(--xh-_tone-fg));
48
+ padding: var(--xh-alert-indicator-p, var(--xh-space-1));
49
+ color: var(--xh-alert-indicator-fg, var(--xh-_tone-fg));
50
+ }
51
+
52
+ /* 必需的文本列:标题与说明在这里排成一列。 */
53
+ [data-scope='alert'][data-part='content'] {
54
+ display: flex;
55
+ /* 伸缩基准取 0 而不是 auto:取 auto 时基准是这一列的 max-content——
56
+ 一段长说明就能把基准撑到比整行还宽,root 那条换行随即把图标、文本列、叉拆成三行 */
57
+ flex: 1 1 0;
58
+ flex-direction: column;
59
+ gap: var(--xh-alert-content-gap, var(--xh-space-1));
60
+ min-inline-size: 0;
61
+ }
62
+
63
+ /* 列里的两段文字不再参与 root 那一行的伸缩:宽度由列自己给 */
64
+ [data-scope='alert'][data-part='content'] [data-part='title'],
65
+ [data-scope='alert'][data-part='content'] [data-part='description'] {
66
+ flex: none;
67
+ }
68
+
69
+ /* 操作与关闭入口都留在尾端,不把说明挤到下一行。 */
70
+ [data-scope='alert'][data-part='action'] {
71
+ display: flex;
72
+ flex: none;
73
+ align-items: center;
74
+ align-self: center;
75
+ gap: var(--xh-alert-action-gap, var(--xh-space-2));
76
+ margin-inline-start: auto;
47
77
  }
48
78
 
49
79
  /* 标题与说明摞成一列,占满 root 剩下的横向空间,
@@ -55,15 +85,15 @@
55
85
  }
56
86
 
57
87
  [data-scope='alert'][data-part='title'] {
58
- flex: 1 1 auto;
59
- color: var(--xh-alert-title-fg, var(--xh-fg-default));
88
+ flex: none;
89
+ color: var(--xh-alert-title-fg, var(--xh-_tone-fg));
60
90
  font-size: var(--xh-alert-title-font-size, var(--xh-text-label-size));
61
91
  font-weight: var(--xh-alert-title-font-weight, var(--xh-font-weight-semibold));
62
92
  line-height: var(--xh-alert-title-leading, var(--xh-leading-tight));
63
93
  }
64
94
 
65
95
  [data-scope='alert'][data-part='description'] {
66
- flex: 1 1 100%;
96
+ flex: none;
67
97
  color: var(--xh-alert-description-fg, var(--xh-fg-muted));
68
98
  font-size: var(--xh-alert-description-font-size, var(--xh-text-secondary-size));
69
99
  }
@@ -73,53 +103,36 @@
73
103
  display: none;
74
104
  }
75
105
 
106
+ /* 关闭钮是只有字形的离散动作钮:盒几何、悬停 / 按下与 0.97 按压、粗指针热区、焦点环、禁用面全由
107
+ Action Control 的 icon ghost 档给(连接层投 sm:与此前 --xh-control-h-sm 同尺寸),组件只映射既有使用者槽。
108
+ 静息透明;提示本体是白底承载,hover 100 → pressed 200,写了语气时悬停底跟着语气走(--xh-_tone-subtle)。
109
+ closable=false 时连接层同时给 hidden 与 disabled / data-disabled,家族按后者收掉反馈 */
76
110
  [data-scope='alert'][data-part='close-trigger'] {
77
- flex: none;
78
- /* 前面没有标题时也把叉推到行尾 */
79
- margin-inline-start: auto;
80
- display: inline-flex;
81
- align-items: center;
82
- justify-content: center;
83
- block-size: var(--xh-alert-close-size, var(--xh-control-h-sm));
84
- inline-size: var(--xh-alert-close-size, var(--xh-control-h-sm));
85
- border: 0;
86
- border-radius: var(--xh-alert-close-radius, var(--xh-shape-control));
87
- background: transparent;
88
- color: var(--xh-alert-close-fg, var(--xh-fg-muted));
89
- /* 按钮不继承字族字号,不接回来的话提示里会突然冒出一段系统 UI 字体 */
90
- font: inherit;
91
- line-height: var(--xh-leading-none);
92
- cursor: pointer;
93
- transition:
94
- background var(--xh-motion-duration-micro) var(--xh-motion-ease-enter),
95
- color var(--xh-motion-duration-micro) var(--xh-motion-ease-enter),
96
- scale var(--xh-motion-duration-micro) var(--xh-motion-ease-enter);
97
- }
98
-
99
- /* closable=false 时连接层同时给了 hidden 与 disabled,这条是它真正收起的那一半 */
100
- [data-scope='alert'][data-part='close-trigger'][hidden] {
101
- display: none;
102
- }
103
-
104
- /* 悬停与按下的底色跟着语气走:提示本体已是该语气的淡底,叉的底色在同一色系里再深两档 */
105
- [data-scope='alert'][data-part='close-trigger']:hover:not(:disabled) {
106
- background: var(--xh-alert-close-bg-hover, var(--xh-_tone-subtle-hover, var(--xh-bg-subtle-hover)));
107
- color: var(--xh-alert-close-fg-hover, var(--xh-fg-default));
108
- }
111
+ --xh-action-visual-size: var(--xh-alert-close-size, var(--xh-_action-profile-visual-size));
112
+ --xh-action-min-inline-size: var(--xh-alert-close-size, var(--xh-_action-profile-visual-size));
113
+ --xh-action-radius: var(--xh-alert-close-radius, var(--xh-shape-control));
114
+ --xh-action-bg-hover: var(--xh-alert-close-bg-hover, var(--xh-_action-variant-bg-hover));
115
+ --xh-action-bg-pressed: var(--xh-alert-close-bg-active, var(--xh-_action-variant-bg-pressed));
116
+ --xh-action-fg-rest: var(--xh-alert-close-fg, var(--xh-fg-muted));
117
+ --xh-action-fg-hover: var(--xh-alert-close-fg-hover, var(--xh-fg-default));
118
+ --xh-action-fg-pressed: var(--xh-alert-close-fg-hover, var(--xh-fg-default));
119
+ --xh-action-border-rest: transparent;
120
+ --xh-action-highlight-rest: transparent;
121
+ --xh-action-shadow-rest: none;
122
+ --xh-action-shadow-hover: none;
123
+ --xh-action-shadow-pressed: none;
124
+ /* 叉的字形按钮档取值(sm → 16px),与 root 上给指示符的 md 档分开 */
125
+ --xh-icon-size: var(--xh-alert-icon-size, var(--xh-_action-profile-glyph-size));
109
126
 
110
- [data-scope='alert'][data-part='close-trigger']:active {
111
- background: var(--xh-alert-close-bg-active, var(--xh-_tone-subtle-active, var(--xh-bg-subtle-active)));
112
- scale: var(--xh-motion-scale-press);
113
- }
114
-
115
- [data-scope='alert'][data-part='close-trigger']:disabled {
116
- color: var(--xh-fg-disabled);
117
- cursor: not-allowed;
127
+ flex: none;
128
+ align-self: center;
129
+ border-width: 0;
118
130
  }
119
131
 
120
- [data-scope='alert'][data-part='close-trigger']:focus-visible {
121
- outline: var(--xh-ring-width) solid var(--xh-ring-focus);
122
- outline-offset: var(--xh-ring-offset);
132
+ /* closable=false 时连接层同时给了 hidden 与 disabled,这条是它真正收起的那一半;
133
+ 家族那条 display 会把 UA 的 [hidden]{display:none} 盖掉 */
134
+ [data-scope='alert'][data-part='close-trigger'][hidden] {
135
+ display: none;
123
136
  }
124
137
 
125
138
  /* 没写内容就由皮肤画兜底字形;作者往部件里塞了自己的图形,这几条即不命中 */
@@ -134,9 +147,43 @@
134
147
  mask: var(--xh-glyph-mark-close) center / contain no-repeat;
135
148
  }
136
149
 
150
+ /*
151
+ * 打印:底色被丢掉,六档语气那层淡底一起没了,剩下的描边兑了 40% 的底色,在纸上几乎印不出。
152
+ * 描边换成正文色把这块提示框出来,标题加重一档——纸上分得出「这是一段提示」,
153
+ * 靠的是框与字重这两条无色通道,不是那层底。
154
+ * 关闭钮在纸上按不动,一并收起。
155
+ */
156
+ @media print {
157
+ [data-scope='alert'][data-part='root'] {
158
+ border-color: currentColor;
159
+ }
160
+
161
+ [data-scope='alert'][data-part='title'] {
162
+ font-weight: var(--xh-font-weight-bold);
163
+ }
164
+
165
+ [data-scope='alert'][data-part='close-trigger'] {
166
+ display: none;
167
+ }
168
+ }
169
+
170
+ @media (forced-colors: active) {
171
+ [data-scope='alert'][data-part='root'] {
172
+ border-color: CanvasText;
173
+ }
174
+ }
175
+
137
176
  /* 声明过任何 display 就盖掉了 UA 的 [hidden]{display:none},收起态得自己还回去。
138
177
  写在文件末尾:兜底必须排在该部件所有 display 声明之后 */
139
- [data-scope='alert'][data-part='icon'][hidden] {
178
+ [data-scope='alert'][data-part='indicator'][hidden] {
179
+ display: none;
180
+ }
181
+
182
+ [data-scope='alert'][data-part='content'][hidden] {
183
+ display: none;
184
+ }
185
+
186
+ [data-scope='alert'][data-part='action'][hidden] {
140
187
  display: none;
141
188
  }
142
189
  }