@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/editable.css CHANGED
@@ -1,17 +1,58 @@
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
+ /* Editable 独立皮肤同时传递引入字段视觉盒与字段内动作;full bundle 递归去重。 */
7
+ @import '../family/field-chrome.css';
8
+ @import '../family/action-control.css';
9
+
1
10
  @layer xihan.components {
2
11
  /* 皮肤在场的标记:开发模式下按 scope 探一次,取不到就说明这份皮肤没被引入。 */
3
12
  [data-scope='editable'] {
4
13
  --xh-editable-skin: 1;
5
14
  }
6
15
 
7
- /* 就地编辑是"一行文字里的一处可改内容":标题、显示区与按钮天然同行,
8
- 所以根是一条横向的行,而不是文本框那种"标题一行、控件一行"的竖排。
9
- 要竖排的作者把 flex-direction 覆盖掉即可,其余尺寸都长在各自的角色节点上 */
16
+ /* 与 NumberField 同构:标题独占一行,control 是下面唯一的视觉盒;
17
+ 预览/输入占据盒内左侧,编辑或确认/取消动作收在同一盒的逻辑末端。
18
+ 组件层只把既有公开槽映射到家族合同;形态三档由家族按 control 上的 data-variant 生成,皮肤不再声明。 */
10
19
  [data-scope='editable'][data-part='root'] {
20
+ --xh-icon-size: var(--xh-editable-icon-size, var(--xh-glyph-size-md));
21
+
22
+ /* 尺寸档只换这三个私有槽,预览区、输入框与动作钮都从 root 继承它们,
23
+ 换档不必给每个部件各写一条选择器。 */
24
+ --xh-_editable-h: var(--xh-control-h-md);
25
+ --xh-_editable-px: var(--xh-control-px-md);
26
+ --xh-_editable-font-size: var(--xh-control-font-md);
27
+ --xh-_editable-control-gap: 0;
28
+
29
+ /* 盒内那道分隔线的长度:取钮高的一半,线的上下各留一截空白,不与钮等高 */
30
+ --xh-_editable-divider-h: 50%;
31
+
11
32
  display: inline-flex;
12
- flex-wrap: wrap;
13
- align-items: center;
14
- gap: var(--xh-editable-gap, var(--xh-space-2));
33
+ flex-direction: column;
34
+ gap: var(--xh-editable-gap, var(--xh-space-1));
35
+ /* 不传尺寸时一律这么宽,宽度不随内容走;父容器给不出这么宽时整件跟着收,地板同步让步,不越出父容器。
36
+ 地板不高过缺省宽:使用者把缺省宽钉到底线以下时不必再放开底线 */
37
+ inline-size: var(--xh-editable-control-w, var(--xh-control-w));
38
+ min-inline-size: min(var(--xh-editable-control-w, var(--xh-control-w)), var(--xh-editable-control-min-w, var(--xh-control-min-w)), 100%);
39
+ max-inline-size: 100%;
40
+ }
41
+
42
+ /* —— 尺寸 —— */
43
+ /* 缺省档写在上面的基础规则里 */
44
+ [data-scope='editable'][data-part='root'][data-size='sm'] {
45
+ --xh-icon-size: var(--xh-editable-icon-size, var(--xh-glyph-size-sm));
46
+ --xh-_editable-h: var(--xh-control-h-sm);
47
+ --xh-_editable-px: var(--xh-control-px-sm);
48
+ --xh-_editable-font-size: var(--xh-control-font-sm);
49
+ }
50
+
51
+ [data-scope='editable'][data-part='root'][data-size='lg'] {
52
+ --xh-icon-size: var(--xh-editable-icon-size, var(--xh-glyph-size-lg));
53
+ --xh-_editable-h: var(--xh-control-h-lg);
54
+ --xh-_editable-px: var(--xh-control-px-lg);
55
+ --xh-_editable-font-size: var(--xh-control-font-lg);
15
56
  }
16
57
 
17
58
  /* 只要声明了 display 就盖掉了 UA 的 [hidden]{display:none},收起态得自己还回去 */
@@ -23,7 +64,6 @@
23
64
  color: var(--xh-editable-label-fg, var(--xh-fg-default));
24
65
  font-size: var(--xh-editable-label-font-size, var(--xh-text-label-size));
25
66
  font-weight: var(--xh-editable-label-font-weight, var(--xh-text-label-weight));
26
- line-height: var(--xh-leading-none);
27
67
  /* 点标题会把人送进编辑态(预览态下 for 指着的输入框是收起的,点了没反应),
28
68
  所以光标要说明它可点 */
29
69
  cursor: pointer;
@@ -31,34 +71,24 @@
31
71
 
32
72
  [data-scope='editable'][data-part='label'][data-disabled] {
33
73
  color: var(--xh-editable-label-fg-disabled, var(--xh-fg-subtle));
34
- cursor: not-allowed;
35
- }
36
-
37
- /* 预览区与输入框轮流上场,两者在同一处落脚:area 给这一处定最小宽高 */
38
- [data-scope='editable'][data-part='area'] {
39
- display: inline-flex;
40
- align-items: center;
41
- min-block-size: var(--xh-editable-area-min-h, var(--xh-control-h-md));
42
- min-inline-size: var(--xh-editable-area-min-w, 6ch);
43
- }
44
-
45
- [data-scope='editable'][data-part='area'][hidden] {
46
- display: none;
47
74
  }
48
75
 
49
- /* 预览区的高度、内边距与边框都和输入框取同一档,只有描边是透明的:
50
- 单行值定在控件档上,多行值才往下长 */
76
+ /* 预览区只是 control 里的内容段,不再自成一只带圆角的盒子。 */
51
77
  [data-scope='editable'][data-part='preview'] {
52
78
  display: inline-flex;
79
+ flex: 1 1 auto;
53
80
  align-items: center;
54
- inline-size: 100%;
55
- min-block-size: var(--xh-editable-preview-min-h, var(--xh-control-h-md));
56
- padding-inline: var(--xh-editable-preview-px, var(--xh-control-px-md));
81
+ inline-size: auto;
82
+ min-inline-size: 0;
83
+ min-block-size: var(--xh-editable-preview-min-h, var(--xh-_editable-h));
84
+ padding-inline: var(--xh-editable-preview-px, var(--xh-_editable-px));
57
85
  padding-block: 0;
58
- border: var(--xh-stroke-thin) solid transparent;
59
- border-radius: var(--xh-editable-preview-radius, var(--xh-shape-control));
86
+ border: 0;
87
+ border-radius: 0;
88
+ background: transparent;
89
+ box-shadow: none;
60
90
  color: var(--xh-editable-preview-fg, var(--xh-fg-default));
61
- font-size: var(--xh-editable-preview-font-size, var(--xh-text-body-size));
91
+ font-size: var(--xh-editable-preview-font-size, var(--xh-_editable-font-size));
62
92
  line-height: var(--xh-leading-normal);
63
93
  /* 值里的换行与连续空格照原样显示,过长的行断开而不撑破弹性行 */
64
94
  white-space: pre-wrap;
@@ -80,14 +110,6 @@
80
110
  cursor: text;
81
111
  }
82
112
 
83
- [data-scope='editable'][data-part='preview']:not(
84
- [data-activation-mode='none'],
85
- [data-disabled],
86
- [data-readonly]
87
- ):hover {
88
- background: var(--xh-editable-preview-bg-hover, var(--xh-bg-subtle-hover));
89
- }
90
-
91
113
  /* 显示的是占位文字而不是真值,压淡以示区别 */
92
114
  [data-scope='editable'][data-part='preview'][data-placeholder] {
93
115
  color: var(--xh-editable-placeholder-fg, var(--xh-fg-subtle));
@@ -95,32 +117,24 @@
95
117
 
96
118
  [data-scope='editable'][data-part='preview'][data-disabled] {
97
119
  color: var(--xh-fg-disabled);
98
- cursor: not-allowed;
99
- }
100
-
101
- /* 预览区是可聚焦节点(focus 模式下还占 Tab 位),焦点环不能省 */
102
- [data-scope='editable'][data-part='preview']:focus-visible {
103
- outline: var(--xh-ring-width) solid var(--xh-ring-focus);
104
- outline-offset: var(--xh-ring-offset);
105
120
  }
106
121
 
122
+ /* 盒内 input:无边框无底无圆角无落影由家族重置,hover、focus 与 invalid 全交给 control;
123
+ 行内内衬留给它自己(control 不给内衬),占位与自动填充的颜色经桥接槽下发 */
107
124
  [data-scope='editable'][data-part='input'] {
108
- inline-size: 100%;
109
- block-size: var(--xh-editable-input-h, var(--xh-control-h-md));
110
- padding-inline: var(--xh-editable-input-px, var(--xh-control-px-md));
111
- padding-block: 0;
112
- border: var(--xh-stroke-thin) solid var(--xh-editable-input-border, var(--xh-border-control));
113
- border-radius: var(--xh-editable-input-radius, var(--xh-shape-control));
114
- background: var(--xh-editable-input-bg, var(--xh-bg-canvas));
115
- color: var(--xh-editable-input-fg, var(--xh-fg-default));
116
- /* 表单控件不继承页面字体,只给字号会让输入框用 UA 默认字族,与预览区的文字对不上 */
117
- font-family: inherit;
118
- font-size: var(--xh-editable-input-font-size, var(--xh-text-body-size));
119
- line-height: var(--xh-leading-normal);
120
- transition: border-color var(--xh-motion-duration-micro) var(--xh-motion-ease-enter);
125
+ --xh-field-input-fg: var(--xh-editable-input-fg, var(--xh-fg-default));
126
+ --xh-field-input-font-size: var(--xh-editable-input-font-size, var(--xh-_editable-font-size));
127
+ --xh-field-placeholder-fg: var(--xh-editable-placeholder-fg, var(--xh-fg-subtle));
128
+ --xh-field-autofill-bg: var(--xh-editable-input-autofill-bg, var(--xh-bg-canvas));
129
+ --xh-field-autofill-fg: var(--xh-editable-input-autofill-fg, var(--xh-fg-default));
130
+
131
+ flex: 1 1 auto;
132
+ inline-size: auto;
133
+ min-inline-size: 0;
134
+ padding-inline: var(--xh-editable-input-px, var(--xh-_editable-px));
121
135
  }
122
136
 
123
- /* 预览态由连接层给 hidden;上面给了 inline-size block-size 但没给 display,
137
+ /* 预览态由连接层给 hidden;家族给了 display 以外的盒声明但没给 display,
124
138
  UA 的 [hidden]{display:none} 仍然管用——这里补一条是防作者层另给 display */
125
139
  [data-scope='editable'][data-part='input'][hidden] {
126
140
  display: none;
@@ -128,129 +142,135 @@
128
142
 
129
143
  /* 宽度跟着内容走时交给原生 size 说了算,别再用 100% 把它撑满 */
130
144
  [data-scope='editable'][data-part='input'][data-auto-resize] {
145
+ flex: 0 1 auto;
131
146
  inline-size: auto;
132
147
  }
133
148
 
134
- [data-scope='editable'][data-part='input']::placeholder {
135
- color: var(--xh-editable-placeholder-fg, var(--xh-fg-subtle));
136
- }
137
-
138
- /* hover 只在中性态换描边:invalid 正拿边框颜色说事,被 hover 盖掉那条信息就没了 */
139
- [data-scope='editable'][data-part='input']:hover:not(:disabled, [data-invalid]) {
140
- border-color: var(--xh-editable-input-border-hover, var(--xh-border-control-hover));
141
- }
142
-
143
- [data-scope='editable'][data-part='input']:focus-visible {
144
- border-color: var(--xh-editable-input-border-focus, var(--xh-_tone, var(--xh-border-control-focus)));
145
- outline: var(--xh-ring-width) solid var(--xh-ring-focus);
146
- outline-offset: var(--xh-ring-offset);
147
- }
148
-
149
- [data-scope='editable'][data-part='input'][data-invalid] {
150
- border-color: var(--xh-editable-input-border-invalid, var(--xh-border-invalid));
151
- }
152
-
153
- /* 只读仍可聚焦、可复制,不置灰,只把底色压下去表示"改不动" */
154
- [data-scope='editable'][data-part='input'][readonly] {
155
- background: var(--xh-editable-input-bg-readonly, var(--xh-bg-subtle));
156
- }
157
-
158
- /* 输入框是单体表单控件,禁用走原生 disabled */
159
- [data-scope='editable'][data-part='input']:disabled {
160
- background: var(--xh-editable-input-bg-disabled, var(--xh-bg-subtle));
161
- color: var(--xh-fg-disabled);
162
- cursor: not-allowed;
163
- }
164
-
149
+ /* 唯一视觉盒:描边、底色、圆角、聚焦环、五态与悬停由 Field Chrome 家族画在 control 上;
150
+ 预览/输入和右侧动作只是盒内分段。控件不给内衬:内衬走预览区、input 与钮各自的盒。
151
+ 不写 overflow: hidden——家族的粗指针热区伪元素会被它裁掉,且钮已不贴控件边 */
165
152
  [data-scope='editable'][data-part='control'] {
166
- display: inline-flex;
167
- flex: none;
168
- align-items: center;
169
- gap: var(--xh-editable-control-gap, var(--xh-space-1));
153
+ --xh-field-control-height: var(--xh-editable-control-h, var(--xh-_editable-h));
154
+ --xh-field-control-padding-inline: var(--xh-editable-control-px, 0);
155
+ --xh-field-control-gap: var(--xh-editable-control-gap, var(--xh-_editable-control-gap));
156
+ --xh-field-control-min-inline-size: var(--xh-editable-control-min-w, var(--xh-control-min-w));
157
+ --xh-field-control-radius: var(--xh-editable-control-radius, var(--xh-shape-control));
158
+ --xh-field-bg-rest: var(--xh-editable-control-bg, var(--xh-_field-variant-bg-rest));
159
+ --xh-field-bg-hover: var(--xh-editable-control-bg-hover, var(--xh-_field-variant-bg-hover));
160
+ --xh-field-bg-read-only: var(--xh-editable-control-bg-readonly, var(--xh-_field-variant-bg-read-only));
161
+ --xh-field-bg-disabled: var(--xh-editable-control-bg-disabled, var(--xh-_field-variant-bg-disabled));
162
+ --xh-field-fg-rest: var(--xh-editable-control-fg, var(--xh-fg-default));
163
+ --xh-field-border-rest: var(--xh-editable-control-border, var(--xh-_field-variant-border-rest));
164
+ --xh-field-border-hover: var(--xh-editable-control-border-hover, var(--xh-_field-variant-border-hover));
165
+ --xh-field-border-focus: var(--xh-editable-control-border-focus, var(--xh-_field-variant-border-focus));
166
+ --xh-field-border-invalid: var(--xh-editable-control-border-invalid, var(--xh-_field-variant-border-invalid));
167
+ --xh-field-border-disabled: var(--xh-editable-control-border-disabled, var(--xh-_field-variant-border-disabled));
168
+ --xh-field-ring-focus: var(--xh-ring-focus);
169
+ --xh-field-ring-invalid: var(--xh-ring-invalid);
170
+ --xh-field-shadow-rest: var(--xh-editable-control-shadow, none);
171
+ /* 家族 chrome 会重写 --xh-icon-size,使用者图标槽必须经桥接槽下发才能在盒内生效 */
172
+ --xh-field-glyph-size: var(--xh-editable-icon-size, var(--xh-_field-size-glyph-size));
173
+
174
+ position: relative;
175
+ inline-size: 100%;
170
176
  }
171
177
 
172
178
  [data-scope='editable'][data-part='control'][hidden] {
173
179
  display: none;
174
180
  }
175
181
 
176
- /* 三颗按钮共用一份皮肤:它们是同一种东西,只是干的活不同,
177
- 分开写迟早会改了一颗忘了另外两颗 */
182
+ /* 三颗动作与 NumberField 的加减钮一样是 control 内部的分段:正方视觉盒、inset 圆角、
183
+ 悬停 100 / 按下 200 与 0.97 按压、粗指针热区、:focus-visible 关环与禁用面全由 Action Control 的
184
+ field-inset ghost 档给,组件只映射既有覆盖槽。常态只剩符号,悬停与按下才浮出底色 */
178
185
  [data-scope='editable'][data-part='edit-trigger'],
179
186
  [data-scope='editable'][data-part='submit-trigger'],
180
187
  [data-scope='editable'][data-part='cancel-trigger'] {
181
- display: inline-flex;
182
- flex: none;
183
- align-items: center;
184
- justify-content: center;
185
- block-size: var(--xh-editable-trigger-h, var(--xh-control-h-sm));
186
- padding-inline: var(--xh-editable-trigger-px, var(--xh-control-px-sm));
187
- padding-block: 0;
188
- border: var(--xh-stroke-thin) solid var(--xh-editable-trigger-border, var(--xh-border-control));
189
- border-radius: var(--xh-editable-trigger-radius, var(--xh-shape-control));
190
- background: var(--xh-editable-trigger-bg, var(--xh-bg-subtle));
191
- color: var(--xh-editable-trigger-fg, var(--xh-fg-default));
192
- font-family: inherit;
193
- font-size: var(--xh-editable-trigger-font-size, var(--xh-text-secondary-size));
194
- line-height: var(--xh-leading-none);
195
- white-space: nowrap;
196
- cursor: pointer;
197
- user-select: none;
198
- transition: background var(--xh-motion-duration-micro) var(--xh-motion-ease-enter);
188
+ --xh-action-visual-size: var(--xh-editable-trigger-size, var(--xh-_action-profile-visual-size));
189
+ --xh-action-min-inline-size: var(--xh-editable-trigger-size, var(--xh-_action-profile-visual-size));
190
+ --xh-action-radius: var(--xh-editable-trigger-radius, var(--xh-shape-inset));
191
+ /* 底色阶梯由 ghost 档给(透明 → 100 → 200),使用者槽只作覆盖入口 */
192
+ --xh-action-bg-rest: var(--xh-editable-trigger-bg, var(--xh-_action-variant-bg-rest));
193
+ --xh-action-bg-hover: var(--xh-editable-trigger-bg-hover, var(--xh-_action-variant-bg-hover));
194
+ --xh-action-bg-pressed: var(--xh-editable-trigger-bg-active, var(--xh-_action-variant-bg-pressed));
195
+ --xh-action-bg-disabled: var(--xh-editable-trigger-bg-disabled, var(--xh-_action-variant-bg-disabled));
196
+ --xh-action-fg-rest: var(--xh-editable-trigger-fg, var(--xh-fg-default));
197
+ --xh-action-fg-hover: var(--xh-editable-trigger-fg-hover, var(--xh-fg-default));
198
+ --xh-action-border-rest: transparent;
199
+ --xh-action-highlight-rest: transparent;
200
+ --xh-action-shadow-rest: none;
201
+ --xh-action-shadow-hover: none;
202
+ --xh-action-shadow-pressed: none;
203
+ --xh-action-font-size: var(--xh-editable-trigger-font-size, var(--xh-text-secondary-size));
204
+ /* 配方尚未把 profile 字形档灌进 --xh-icon-size,钮内字形先按 field-inset 档逐钮取值 */
205
+ --xh-icon-size: var(--xh-_action-profile-glyph-size);
206
+
207
+ border-width: 0;
208
+ }
209
+
210
+ /* 每个状态的第一颗动作把整组推到逻辑末端;取消钮紧跟确认钮。 */
211
+ [data-scope='editable'][data-part='edit-trigger'],
212
+ [data-scope='editable'][data-part='submit-trigger'] {
213
+ margin-inline-start: auto;
199
214
  }
200
215
 
201
- /* 三颗按钮按形态轮流收起,连接层给的是 hidden 属性;
202
- 上面那条 display 已把 UA 规则盖掉,少了这里三条按钮就一直杵着 */
203
- [data-scope='editable'][data-part='edit-trigger'][hidden],
204
- [data-scope='editable'][data-part='submit-trigger'][hidden],
205
- [data-scope='editable'][data-part='cancel-trigger'][hidden] {
206
- display: none;
216
+ /* 三颗动作默认是纯图标按钮;作者放了自己的图标后 :empty 不命中,不会叠两层。 */
217
+ [data-scope='editable']:is([data-part='edit-trigger'], [data-part='submit-trigger'], [data-part='cancel-trigger']):empty::before {
218
+ content: '';
219
+ display: inline-block;
220
+ inline-size: var(--xh-icon-size, var(--xh-glyph-size-md));
221
+ block-size: var(--xh-icon-size, var(--xh-glyph-size-md));
222
+ background-color: currentColor;
223
+ -webkit-mask: var(--xh-_editable-trigger-glyph) center / contain no-repeat;
224
+ mask: var(--xh-_editable-trigger-glyph) center / contain no-repeat;
207
225
  }
208
226
 
209
- [data-scope='editable'][data-part='edit-trigger']:hover:not(:disabled),
210
- [data-scope='editable'][data-part='submit-trigger']:hover:not(:disabled),
211
- [data-scope='editable'][data-part='cancel-trigger']:hover:not(:disabled) {
212
- border-color: var(--xh-editable-trigger-border-hover, var(--xh-border-control-hover));
213
- background: var(--xh-editable-trigger-bg-hover, var(--xh-bg-subtle-hover));
227
+ [data-scope='editable'][data-part='edit-trigger'] {
228
+ --xh-_editable-trigger-glyph: var(--xh-glyph-mark-edit);
214
229
  }
215
230
 
216
- [data-scope='editable'][data-part='edit-trigger']:active:not(:disabled),
217
- [data-scope='editable'][data-part='submit-trigger']:active:not(:disabled),
218
- [data-scope='editable'][data-part='cancel-trigger']:active:not(:disabled) {
219
- background: var(--xh-editable-trigger-bg-active, var(--xh-bg-subtle-active));
231
+ [data-scope='editable'][data-part='submit-trigger'] {
232
+ --xh-_editable-trigger-glyph: var(--xh-glyph-mark-check);
220
233
  }
221
234
 
222
- [data-scope='editable'][data-part='edit-trigger']:focus-visible,
223
- [data-scope='editable'][data-part='submit-trigger']:focus-visible,
224
- [data-scope='editable'][data-part='cancel-trigger']:focus-visible {
225
- outline: var(--xh-ring-width) solid var(--xh-ring-focus);
226
- outline-offset: var(--xh-ring-offset);
235
+ [data-scope='editable'][data-part='cancel-trigger'] {
236
+ --xh-_editable-trigger-glyph: var(--xh-glyph-mark-close);
227
237
  }
228
238
 
229
- /* 单体控件用 :disabled(不是集合条目那套 [data-disabled]):
230
- 禁用与只读时编辑钮置灰,收起态的提交/取消也一并落到这条上 */
231
- [data-scope='editable'][data-part='edit-trigger']:disabled,
232
- [data-scope='editable'][data-part='submit-trigger']:disabled,
233
- [data-scope='editable'][data-part='cancel-trigger']:disabled {
234
- border-color: var(--xh-editable-trigger-border-disabled, var(--xh-border-subtle));
235
- background: var(--xh-editable-trigger-bg-disabled, var(--xh-bg-muted));
236
- color: var(--xh-fg-disabled);
237
- cursor: not-allowed;
239
+ /* 动作组第一颗与内容段之间只有一道短分隔线;确认与取消之间不再拼第二个按钮框。
240
+ 线不画在钮的边框上:边框会跟着钮的圆角与悬停底走,而这道线要独立于钮的各态,长度也短于钮自己。
241
+ ::before 已被兜底字形占着,::after 在粗指针下是家族给的 44px 热区,几何只能落在
242
+ background-image 上:一条 1px × 半高的渐变贴在逻辑起始侧,底色换态时它仍叠在上层。
243
+ background-position 是物理轴,RTL 另给一条换边 */
244
+ [data-scope='editable'][data-part='edit-trigger'],
245
+ [data-scope='editable'][data-part='submit-trigger'] {
246
+ background-image: linear-gradient(
247
+ var(--xh-editable-trigger-divider, var(--xh-material-soft-separator)),
248
+ var(--xh-editable-trigger-divider, var(--xh-material-soft-separator))
249
+ );
250
+ background-repeat: no-repeat;
251
+ background-position: 0 50%;
252
+ background-size: var(--xh-stroke-thin) var(--xh-editable-trigger-divider-h, var(--xh-_editable-divider-h));
238
253
  }
239
254
 
240
- /* 提交按钮是这一组里的主操作,给它一层实心底色区分开 */
241
- [data-scope='editable'][data-part='submit-trigger']:not(:disabled) {
242
- border-color: var(--xh-editable-submit-border, var(--xh-bg-brand));
243
- background: var(--xh-editable-submit-bg, var(--xh-bg-brand));
244
- color: var(--xh-editable-submit-fg, var(--xh-fg-on-brand));
255
+ [dir='rtl'] [data-scope='editable'][data-part='edit-trigger'],
256
+ [dir='rtl'] [data-scope='editable'][data-part='submit-trigger'] {
257
+ background-position: 100% 50%;
245
258
  }
246
259
 
247
- [data-scope='editable'][data-part='submit-trigger']:hover:not(:disabled) {
248
- border-color: var(--xh-editable-submit-border-hover, var(--xh-editable-submit-bg-hover, var(--xh-bg-brand-hover)));
249
- background: var(--xh-editable-submit-bg-hover, var(--xh-bg-brand-hover));
260
+ /* 三颗按钮按形态轮流收起,连接层给的是 hidden 属性;
261
+ 家族那条 display 已把 UA 规则盖掉,少了这里三条按钮就一直杵着 */
262
+ [data-scope='editable'][data-part='edit-trigger'][hidden],
263
+ [data-scope='editable'][data-part='submit-trigger'][hidden],
264
+ [data-scope='editable'][data-part='cancel-trigger'][hidden] {
265
+ display: none;
250
266
  }
251
267
 
252
- [data-scope='editable'][data-part='submit-trigger']:active:not(:disabled) {
253
- border-color: var(--xh-editable-submit-border-active, var(--xh-editable-submit-bg-active, var(--xh-bg-brand-active)));
254
- background: var(--xh-editable-submit-bg-active, var(--xh-bg-brand-active));
268
+ /* 高对比档整层丢弃 background-image,分隔线改用系统色重画,并关掉这两颗钮的强制换色 */
269
+ @media (forced-colors: active) {
270
+ [data-scope='editable'][data-part='edit-trigger'],
271
+ [data-scope='editable'][data-part='submit-trigger'] {
272
+ background-image: linear-gradient(ButtonText, ButtonText);
273
+ forced-color-adjust: none;
274
+ }
255
275
  }
256
276
  }
@@ -1,3 +1,13 @@
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
+ /* 定义 empty state 样式。 */
7
+
8
+ /* 共享关键帧由 family/motion.css 提供,本皮肤 @import 它,单独引入仍成立。 */
9
+ @import '../family/motion.css';
10
+
1
11
  @layer xihan.components {
2
12
  /* 皮肤在场的标记:开发模式下按 scope 探一次,取不到就说明这份皮肤没被引入。 */
3
13
  [data-scope='empty-state'] {
@@ -10,9 +20,10 @@
10
20
  --xh-_empty-state-gap: var(--xh-stack-gap-md);
11
21
  --xh-_empty-state-py: var(--xh-section-py-md);
12
22
  --xh-_empty-state-icon-size: var(--xh-glyph-size-2xl);
13
- --xh-_empty-state-title-size: var(--xh-control-font-lg);
14
- /* 说明的读行宽度:整句话不收窄就会拉成一条难读的长行 */
15
- --xh-_empty-state-measure: 32rem;
23
+ /* 标题走 Surface / Feedback 标题档 14/600(§6.4);sm 同档只缩图形与留白,lg 升到页面级 heading-3 */
24
+ --xh-_empty-state-title-size: var(--xh-text-label-size);
25
+ /* 图标区的强调色:由 data-status(状态码)或 data-tone(语气)换掉;两样都没写就退成中性 */
26
+ --xh-_empty-state-accent: var(--xh-fg-subtle);
16
27
 
17
28
  display: flex;
18
29
  flex-direction: column;
@@ -34,7 +45,6 @@
34
45
  --xh-_empty-state-gap: var(--xh-stack-gap-sm);
35
46
  --xh-_empty-state-py: var(--xh-section-py-sm);
36
47
  --xh-_empty-state-icon-size: var(--xh-glyph-size-xl);
37
- --xh-_empty-state-title-size: var(--xh-control-font-md);
38
48
  }
39
49
 
40
50
  [data-scope='empty-state'][data-part='root'][data-size='lg'] {
@@ -44,7 +54,43 @@
44
54
  --xh-_empty-state-title-size: var(--xh-text-heading-3-size);
45
55
  }
46
56
 
47
- [data-scope='empty-state'][data-part='icon'] {
57
+ /* —— 状态码 —— */
58
+ /* 三个状态码各并进最接近的一族:找不到=提示,没权限=警示,服务出错=危险。
59
+ 用 500 档而不是 600:500 是装饰性强调档,600 是给实心底与文字用的。
60
+ 成功 / 警示 / 出错 / 提示这类通用结果不在这儿:那是语气,走下面的 data-tone */
61
+ [data-scope='empty-state'][data-part='root'][data-status='403'] {
62
+ --xh-_empty-state-accent: var(--xh-color-warning-500);
63
+ }
64
+
65
+ [data-scope='empty-state'][data-part='root'][data-status='500'] {
66
+ --xh-_empty-state-accent: var(--xh-color-danger-500);
67
+ }
68
+
69
+ [data-scope='empty-state'][data-part='root'][data-status='404'] {
70
+ --xh-_empty-state-accent: var(--xh-color-info-500);
71
+ }
72
+
73
+ /* 语气轴:写了 tone 就把强调色接到语气层派生好的前景档上。
74
+ 排在状态码之后:两者都写时以显式的语气为准;不写 tone 时上面几条一字不变 */
75
+ [data-scope='empty-state'][data-part='root'][data-tone] {
76
+ --xh-_empty-state-accent: var(--xh-_tone-fg);
77
+ }
78
+
79
+ /*
80
+ * 插画槽。它与图标槽二选一,尺寸另走一档:插画塞进按字形量的图标槽会被压到 40px 以下,
81
+ * 而空状态的插画通常是这个尺度的两倍。默认由图标档翻一倍派生,跟着三个尺寸档一起走。
82
+ */
83
+ [data-scope='empty-state'][data-part='media'] {
84
+ display: inline-flex;
85
+ align-items: center;
86
+ justify-content: center;
87
+ flex: none;
88
+ max-inline-size: 100%;
89
+ block-size: var(--xh-empty-state-media-size, calc(var(--xh-_empty-state-icon-size) * 2));
90
+ color: var(--xh-empty-state-media-fg, var(--xh-_empty-state-accent));
91
+ }
92
+
93
+ [data-scope='empty-state'][data-part='indicator'] {
48
94
  display: inline-flex;
49
95
  align-items: center;
50
96
  justify-content: center;
@@ -54,9 +100,9 @@
54
100
 
55
101
  block-size: var(--xh-empty-state-icon-size, var(--xh-_empty-state-icon-size));
56
102
  inline-size: var(--xh-empty-state-icon-size, var(--xh-_empty-state-icon-size));
57
- color: var(--xh-empty-state-icon-fg, var(--xh-fg-subtle));
103
+ color: var(--xh-empty-state-indicator-fg, var(--xh-_empty-state-accent));
58
104
  /* 图标常是一个字形,字号跟着图标框走,line-height 不再另占高度 */
59
- font-size: var(--xh-empty-state-icon-font-size, var(--xh-_empty-state-icon-size));
105
+ font-size: var(--xh-empty-state-indicator-font-size, var(--xh-_empty-state-icon-size));
60
106
  line-height: var(--xh-leading-none);
61
107
  }
62
108
 
@@ -70,10 +116,10 @@
70
116
 
71
117
  [data-scope='empty-state'][data-part='description'] {
72
118
  margin: 0;
73
- max-inline-size: var(--xh-empty-state-description-max-w, var(--xh-_empty-state-measure));
119
+ max-inline-size: var(--xh-empty-state-description-max-w, var(--xh-measure-prose));
74
120
  color: var(--xh-empty-state-description-fg, var(--xh-fg-muted));
75
- font-size: var(--xh-empty-state-description-font-size, var(--xh-text-body-size));
76
- line-height: var(--xh-empty-state-description-leading, var(--xh-text-body-leading));
121
+ font-size: var(--xh-empty-state-description-font-size, var(--xh-text-secondary-size));
122
+ line-height: var(--xh-empty-state-description-leading, var(--xh-leading-normal));
77
123
  }
78
124
 
79
125
  [data-scope='empty-state'][data-part='action'] {
@@ -84,9 +130,32 @@
84
130
  gap: var(--xh-empty-state-action-gap, var(--xh-space-2));
85
131
  }
86
132
 
133
+ /* 图标、标题、说明、动作按次序开幕,间隔由交错步长派生。
134
+ backwards 不能省:等待期间起帧不生效的话,后三段会先露一下再跳回去 */
135
+ [data-scope='empty-state'][data-part='media'],
136
+ [data-scope='empty-state'][data-part='indicator'],
137
+ [data-scope='empty-state'][data-part='title'],
138
+ [data-scope='empty-state'][data-part='description'],
139
+ [data-scope='empty-state'][data-part='action'] {
140
+ animation: xh-rise-in var(--xh-motion-duration-enter) var(--xh-motion-ease-enter-strong) backwards;
141
+ }
142
+
143
+ [data-scope='empty-state'][data-part='title'] {
144
+ animation-delay: calc(var(--xh-motion-stagger-step) * 1);
145
+ }
146
+
147
+ [data-scope='empty-state'][data-part='description'] {
148
+ animation-delay: calc(var(--xh-motion-stagger-step) * 2);
149
+ }
150
+
151
+ [data-scope='empty-state'][data-part='action'] {
152
+ animation-delay: calc(var(--xh-motion-stagger-step) * 3);
153
+ }
154
+
87
155
  /* 声明过任何 display 就盖掉了 UA 的 [hidden]{display:none},收起态得自己还回去。
88
156
  写在文件末尾:兜底必须排在该部件所有 display 声明之后 */
89
- [data-scope='empty-state'][data-part='icon'][hidden],
157
+ [data-scope='empty-state'][data-part='media'][hidden],
158
+ [data-scope='empty-state'][data-part='indicator'][hidden],
90
159
  [data-scope='empty-state'][data-part='action'][hidden] {
91
160
  display: none;
92
161
  }