@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
@@ -0,0 +1,190 @@
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
+ /* 定义 field array 样式。 */
7
+
8
+ /* FieldArray 独立皮肤同时传递引入把手的动作控件配方;full bundle 递归去重。 */
9
+ @import '../family/action-control.css';
10
+
11
+ @layer xihan.components {
12
+ /* 皮肤在场的标记:开发模式下按 scope 探一次,取不到就说明这份皮肤没被引入。 */
13
+ [data-scope='field-array'] {
14
+ --xh-field-array-skin: 1;
15
+ }
16
+
17
+ /* 一行一条,纵向堆叠;新增把手跟在最后一行下面 */
18
+ [data-scope='field-array'][data-part='root'] {
19
+ display: flex;
20
+ flex-direction: column;
21
+ gap: var(--xh-field-array-gap, var(--xh-space-2));
22
+ }
23
+
24
+ /* 声明了 display 就盖掉了 UA 的 [hidden]{display:none},收起态得自己还回去 */
25
+ [data-scope='field-array'][data-part='root'][hidden] {
26
+ display: none;
27
+ }
28
+
29
+ /* 内容在左、把手在右,把手那一列不随内容伸缩 */
30
+ [data-scope='field-array'][data-part='item'] {
31
+ display: flex;
32
+ align-items: center;
33
+ gap: var(--xh-field-array-item-gap, var(--xh-space-2));
34
+ padding: var(--xh-field-array-item-padding, var(--xh-space-0));
35
+ border-radius: var(--xh-field-array-item-radius, var(--xh-shape-surface));
36
+ }
37
+
38
+ [data-scope='field-array'][data-part='item'][hidden] {
39
+ display: none;
40
+ }
41
+
42
+ /* 行前的行号或名目:不参与分宽,弱一档前景把它与行里的内容分开 */
43
+ [data-scope='field-array'][data-part='item-label'] {
44
+ display: inline-flex;
45
+ flex: none;
46
+ align-items: center;
47
+ color: var(--xh-field-array-item-label-fg, var(--xh-fg-muted));
48
+ font-size: var(--xh-field-array-item-label-font-size, var(--xh-text-secondary-size));
49
+ line-height: var(--xh-leading-none);
50
+ white-space: nowrap;
51
+ }
52
+
53
+ [data-scope='field-array'][data-part='item-label'][hidden] {
54
+ display: none;
55
+ }
56
+
57
+ /* 行里放什么控件归作者,这里只给它一条能撑开也能收窄的轨道。
58
+ min-inline-size 归零:不写的话里面的输入框按 UA 默认宽度顶住,长内容会把整行撑破 */
59
+ [data-scope='field-array'][data-part='item-content'] {
60
+ display: flex;
61
+ flex: 1 1 auto;
62
+ align-items: center;
63
+ gap: var(--xh-field-array-content-gap, var(--xh-space-2));
64
+ min-inline-size: 0;
65
+ }
66
+
67
+ [data-scope='field-array'][data-part='item-action'] {
68
+ display: inline-flex;
69
+ flex: none;
70
+ align-items: center;
71
+ gap: var(--xh-field-array-action-gap, var(--xh-space-1));
72
+ }
73
+
74
+ /* —— 行内三个把手 ——
75
+ 只有字形的离散动作钮:盒几何、悬停 / 按下与 0.97 按压、粗指针热区、焦点环、禁用面全由 Action Control 的
76
+ icon ghost 档给(连接层投 xs:24px 正方盒,行级把手贴着一个控件高的行,取行内动作钮那一档),
77
+ 组件只映射既有使用者槽。静息透明,白底承载 hover 100 → pressed 200。
78
+ 按不动的把手由连接层同时打 aria-disabled 与 data-disabled,家族按后者收掉悬停与按下反馈 */
79
+ [data-scope='field-array'][data-part='item-delete-trigger'],
80
+ [data-scope='field-array'][data-part='move-up-trigger'],
81
+ [data-scope='field-array'][data-part='move-down-trigger'] {
82
+ --xh-action-visual-size: var(--xh-field-array-trigger-size, var(--xh-_action-profile-visual-size));
83
+ --xh-action-min-inline-size: var(--xh-field-array-trigger-size, var(--xh-_action-profile-visual-size));
84
+ --xh-action-radius: var(--xh-field-array-trigger-radius, var(--xh-shape-control));
85
+ --xh-action-bg-rest: var(--xh-field-array-trigger-bg, var(--xh-_action-variant-bg-rest));
86
+ --xh-action-bg-hover: var(--xh-field-array-trigger-bg-hover, var(--xh-_action-variant-bg-hover));
87
+ --xh-action-bg-pressed: var(--xh-field-array-trigger-bg-active, var(--xh-_action-variant-bg-pressed));
88
+ --xh-action-fg-rest: var(--xh-field-array-trigger-fg, var(--xh-fg-muted));
89
+ --xh-action-fg-hover: var(--xh-field-array-trigger-fg-hover, var(--xh-fg-default));
90
+ --xh-action-fg-pressed: var(--xh-field-array-trigger-fg-hover, var(--xh-fg-default));
91
+ --xh-action-border-rest: transparent;
92
+ --xh-action-highlight-rest: transparent;
93
+ --xh-action-shadow-rest: none;
94
+ --xh-action-shadow-hover: none;
95
+ --xh-action-shadow-pressed: none;
96
+ --xh-action-font-size: var(--xh-field-array-trigger-font-size, var(--xh-text-secondary-size));
97
+ /* 作者塞进把手的图标与皮肤画的兜底字形同一把尺:按档取字形尺寸。
98
+ 配方尚未把 profile 字形档灌进 --xh-icon-size,钮内字形先按 icon 档逐钮取值 */
99
+ --xh-icon-size: var(--xh-field-array-icon-size, var(--xh-_action-profile-glyph-size));
100
+
101
+ border-width: 0;
102
+ }
103
+
104
+ /* 不换序时连接层给换序把手写 hidden;家族那条 display 会把 UA 的 [hidden]{display:none}
105
+ 盖掉,少了这条把手还留在原地。删除把手同样声明了 display,作者自己收起它时要的是同一条 */
106
+ [data-scope='field-array'][data-part='item-delete-trigger'][hidden],
107
+ [data-scope='field-array'][data-part='move-up-trigger'][hidden],
108
+ [data-scope='field-array'][data-part='move-down-trigger'][hidden] {
109
+ display: none;
110
+ }
111
+
112
+ /* 删除把手悬停转危险色:它是这一行里唯一不可撤销的动作 */
113
+ [data-scope='field-array'][data-part='item-delete-trigger'] {
114
+ --xh-action-fg-hover: var(--xh-field-array-item-delete-fg-hover, var(--xh-fg-danger-hover));
115
+ --xh-action-fg-pressed: var(--xh-field-array-item-delete-fg-hover, var(--xh-fg-danger-hover));
116
+ }
117
+
118
+ /* —— 新增把手 ——
119
+ 带文案的离散动作钮,走 text outline 档(中性描边、透明底,hover 100 → pressed 200),高一个控件;
120
+ 虚线描边把它和行里的实心控件区分开:它加的是行,不是行里的值——家族只写 border-color,线型由这里给 */
121
+ [data-scope='field-array'][data-part='add-trigger'] {
122
+ --xh-action-visual-size: var(--xh-field-array-add-height, var(--xh-_action-profile-visual-size));
123
+ --xh-action-padding-inline: var(--xh-field-array-add-px, var(--xh-_action-profile-padding-inline));
124
+ --xh-action-gap: var(--xh-field-array-action-gap, var(--xh-space-1));
125
+ --xh-action-radius: var(--xh-field-array-add-radius, var(--xh-shape-control));
126
+ --xh-action-bg-rest: var(--xh-field-array-add-bg, var(--xh-_action-variant-bg-rest));
127
+ --xh-action-bg-hover: var(--xh-field-array-add-bg-hover, var(--xh-_action-variant-bg-hover));
128
+ --xh-action-bg-pressed: var(--xh-field-array-add-bg-active, var(--xh-_action-variant-bg-pressed));
129
+ --xh-action-fg-rest: var(--xh-field-array-add-fg, var(--xh-fg-brand));
130
+ --xh-action-fg-hover: var(--xh-field-array-add-fg, var(--xh-fg-brand));
131
+ --xh-action-fg-pressed: var(--xh-field-array-add-fg, var(--xh-fg-brand));
132
+ --xh-action-border-rest: var(--xh-field-array-add-border, var(--xh-_action-variant-border-rest));
133
+ --xh-action-border-hover: var(--xh-field-array-add-border-hover, var(--xh-_action-variant-border-hover));
134
+ --xh-action-border-disabled: var(--xh-field-array-add-border-disabled, var(--xh-_action-variant-border-disabled));
135
+ --xh-action-highlight-rest: transparent;
136
+ --xh-action-shadow-rest: none;
137
+ --xh-action-shadow-hover: none;
138
+ --xh-action-shadow-pressed: none;
139
+ --xh-action-font-size: var(--xh-field-array-add-font-size, var(--xh-text-label-size));
140
+ --xh-icon-size: var(--xh-field-array-icon-size, var(--xh-_action-profile-glyph-size));
141
+
142
+ align-self: flex-start;
143
+ border-style: dashed;
144
+ }
145
+
146
+ [data-scope='field-array'][data-part='add-trigger'][hidden] {
147
+ display: none;
148
+ }
149
+
150
+ /* 没写内容就由皮肤画兜底字形;作者往部件里塞了自己的图形,这几条即不命中 */
151
+ [data-scope='field-array'][data-part='move-up-trigger']:empty::before {
152
+ content: '';
153
+ display: inline-block;
154
+ inline-size: var(--xh-icon-size, var(--xh-glyph-size-text));
155
+ block-size: var(--xh-icon-size, var(--xh-glyph-size-text));
156
+ vertical-align: var(--xh-glyph-baseline-shift);
157
+ background-color: currentColor;
158
+ -webkit-mask: var(--xh-glyph-mark-chevron-up) center / contain no-repeat;
159
+ mask: var(--xh-glyph-mark-chevron-up) center / contain no-repeat;
160
+ }
161
+
162
+ [data-scope='field-array'][data-part='move-down-trigger']:empty::before {
163
+ content: '';
164
+ display: inline-block;
165
+ inline-size: var(--xh-icon-size, var(--xh-glyph-size-text));
166
+ block-size: var(--xh-icon-size, var(--xh-glyph-size-text));
167
+ vertical-align: var(--xh-glyph-baseline-shift);
168
+ background-color: currentColor;
169
+ -webkit-mask: var(--xh-glyph-mark-chevron-down) center / contain no-repeat;
170
+ mask: var(--xh-glyph-mark-chevron-down) center / contain no-repeat;
171
+ }
172
+
173
+ [data-scope='field-array'][data-part='item-delete-trigger']:empty::before {
174
+ content: '';
175
+ display: inline-block;
176
+ inline-size: var(--xh-icon-size, var(--xh-glyph-size-text));
177
+ block-size: var(--xh-icon-size, var(--xh-glyph-size-text));
178
+ vertical-align: var(--xh-glyph-baseline-shift);
179
+ background-color: currentColor;
180
+ -webkit-mask: var(--xh-glyph-mark-close) center / contain no-repeat;
181
+ mask: var(--xh-glyph-mark-close) center / contain no-repeat;
182
+ }
183
+
184
+ /* 声明过任何 display 就盖掉了 UA 的 [hidden]{display:none},收起态得自己还回去。
185
+ 写在文件末尾:兜底必须排在该部件所有 display 声明之后 */
186
+ [data-scope='field-array'][data-part='item-content'][hidden],
187
+ [data-scope='field-array'][data-part='item-action'][hidden] {
188
+ display: none;
189
+ }
190
+ }
package/css/field.css CHANGED
@@ -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
+ /* 定义 field 样式。 */
7
+
8
+ /* Field 独立皮肤同时传递引入字段视觉盒;full bundle 递归去重。 */
9
+ @import '../family/field-chrome.css';
10
+
1
11
  @layer xihan.components {
2
12
  /* 皮肤在场的标记:开发模式下按 scope 探一次,取不到就说明这份皮肤没被引入。 */
3
13
  [data-scope='field'] {
@@ -14,7 +24,7 @@
14
24
  整表据此对齐;描述与错误文案跟着控件走第二列 */
15
25
  [data-scope='form'][data-part='root'][data-layout='horizontal'] [data-scope='field'][data-part='root'] {
16
26
  display: grid;
17
- grid-template-columns: var(--xh-form-label-w) minmax(0, 1fr);
27
+ grid-template-columns: var(--xh-form-label-w, 30%) minmax(0, 1fr);
18
28
  column-gap: var(--xh-field-label-gap, var(--xh-space-3));
19
29
  align-items: start;
20
30
  }
@@ -22,9 +32,16 @@
22
32
  [data-scope='form'][data-part='root'][data-layout='horizontal'] [data-scope='field'][data-part='label'] {
23
33
  grid-column: 1;
24
34
  justify-self: end;
35
+ /* 横排下标签与控件是左右两列,间距归 --xh-field-label-gap 管,竖排那段补白在这儿清零 */
36
+ margin-block-end: 0;
25
37
  /* 与控件的首行文字对齐:行高保持正文行距(标签折行时每行不会撑成一个控件高),
26
38
  上下留白把单行文本盒撑到控件高度;配的是哪一档控件由 --xh-field-control-h 告诉它 */
27
39
  line-height: var(--xh-field-label-leading, var(--xh-leading-normal));
40
+ /* 级联兜底:先写一行的高度算式(标签字号 × 标签行距),再写 1lh。
41
+ 1lh 晚于本库声明的浏览器地板,取不到时旧引擎丢掉后一条、留下前一条。
42
+ 两条取的是同一组槽——字号来自本文件里标签那条 font-size、行距来自紧邻上一行,
43
+ 所以算出来是同一个数,使用者覆盖任一槽两条一起跟着走。 */
44
+ padding-block: calc((var(--xh-field-control-h, var(--xh-control-h-md)) - var(--xh-field-label-font-size, var(--xh-text-label-size)) * var(--xh-field-label-leading, var(--xh-leading-normal))) / 2);
28
45
  padding-block: calc((var(--xh-field-control-h, var(--xh-control-h-md)) - 1lh) / 2);
29
46
  }
30
47
 
@@ -36,69 +53,105 @@
36
53
  grid-column: 2;
37
54
  }
38
55
 
56
+ /* 横排下这一列是网格的自动流,占位块跟着控件走第二列(选择器不匹配伪元素,单列一条) */
57
+ [data-scope='form'][data-part='root'][data-layout='horizontal'] [data-scope='field'][data-part='root']::after {
58
+ grid-column: 2;
59
+ }
60
+
39
61
  [data-scope='field'][data-part='label'] {
62
+ /* 一段不带空格的长标识(字段名、英文标识符)在窄处从词内断开:
63
+ 横排表单里标签列是一段比例宽度,这行让标签在那一列里折行,而不是从列的左边顶出去 */
64
+ overflow-wrap: anywhere;
65
+ /* 竖排时标签与控件之间的距离:容器的 gap 之上补一段差值,
66
+ --xh-field-label-gap-block 给多少最终就是多少;不给时差值算成 0,
67
+ 这段距离仍由 --xh-field-gap 与描述、错误文案那两段同宽。 */
68
+ margin-block-end: calc(
69
+ var(--xh-field-label-gap-block, var(--xh-field-gap, var(--xh-space-1))) - var(--xh-field-gap, var(--xh-space-1))
70
+ );
40
71
  color: var(--xh-field-label-fg, var(--xh-fg-default));
41
72
  font-size: var(--xh-field-label-font-size, var(--xh-text-label-size));
42
73
  font-weight: var(--xh-field-label-font-weight, var(--xh-text-label-weight));
43
- line-height: var(--xh-leading-none);
44
74
  }
45
75
 
46
76
  [data-scope='field'][data-part='label'][data-disabled] {
47
77
  color: var(--xh-field-label-fg-disabled, var(--xh-fg-subtle));
48
78
  }
49
79
 
50
- /* 必填星号:跟着根上的 data-required 亮,选填不标 */
51
- [data-scope='field'][data-part='root'][data-required] [data-part='label']::after {
52
- content: var(--xh-glyph-mark-required);
53
- margin-inline-start: var(--xh-space-1);
80
+ /* 必填星号的字形、间距与默认色在 label.css 公共层;这里只把颜色接到本组件的覆盖槽上 */
81
+ [data-scope='field'][data-part='label'][data-required]::after {
54
82
  color: var(--xh-field-label-star, var(--xh-fg-danger));
55
83
  }
56
84
 
57
- /* control 是作者自己的输入控件,这里只给一套可被覆盖的基础皮肤 */
85
+ /* control 是作者自己的输入控件,它自身就是视觉盒:描边、底、影、圆角与悬停 / 聚焦 / 无效 /
86
+ 只读 / 禁用各态由 Field Chrome 家族配方按连接层投影的 data-xh-field-chrome 画,
87
+ 这里只把既有使用者槽映射到家族桥接槽。Field 没有 size 轴,尺寸私有槽按连接层固定投的 md 档取值。
88
+ 使用者槽与桥接槽同在 --xh-field- 前缀下:圆角那一位(--xh-field-control-radius)与家族读的桥接槽同名,
89
+ 使用者写它即被家族直接读到,无法再经映射中转,圆角在这里按同一槽同一缺省直接声明(与家族算出的值一致,
90
+ 只为把这一位使用者槽留在皮肤的消费位上);其余各位逐条对齐,不与桥接槽撞名 */
58
91
  [data-scope='field'][data-part='control'] {
92
+ --xh-field-control-height: var(--xh-field-control-h, var(--xh-_field-size-control-height));
93
+ --xh-field-control-padding-inline: var(--xh-field-control-px, var(--xh-_field-size-padding-inline));
94
+ --xh-field-bg-rest: var(--xh-field-control-bg, var(--xh-_field-variant-bg-rest));
95
+ --xh-field-bg-hover: var(--xh-field-control-bg-hover, var(--xh-_field-variant-bg-hover));
96
+ --xh-field-bg-read-only: var(--xh-field-control-bg-readonly, var(--xh-_field-variant-bg-read-only));
97
+ --xh-field-bg-disabled: var(--xh-field-control-bg-disabled, var(--xh-_field-variant-bg-disabled));
98
+ --xh-field-fg-rest: var(--xh-field-control-fg, var(--xh-fg-default));
99
+ --xh-field-border-rest: var(--xh-field-control-border, var(--xh-_field-variant-border-rest));
100
+ --xh-field-border-hover: var(--xh-field-control-border-hover, var(--xh-_field-variant-border-hover));
101
+ --xh-field-border-focus: var(--xh-field-control-border-focus, var(--xh-_field-variant-border-focus));
102
+ --xh-field-border-invalid: var(--xh-field-control-border-invalid, var(--xh-_field-variant-border-invalid));
103
+ /* 焦点环与家族同一支公共环,不再留逐组件的环色槽(§7.2.5 焦点边与环一律公共) */
104
+ --xh-field-ring-focus: var(--xh-ring-focus);
105
+ --xh-field-ring-invalid: var(--xh-ring-invalid);
106
+ --xh-field-shadow-rest: var(--xh-field-control-shadow, none);
107
+
59
108
  inline-size: 100%;
60
- block-size: var(--xh-field-control-h, var(--xh-control-h-md));
61
- padding-inline: var(--xh-field-control-px, var(--xh-control-px-md));
62
- border: var(--xh-stroke-thin) solid var(--xh-field-control-border, var(--xh-border-control));
63
109
  border-radius: var(--xh-field-control-radius, var(--xh-shape-control));
64
- background: var(--xh-field-control-bg, var(--xh-bg-canvas));
65
- color: var(--xh-field-control-fg, var(--xh-fg-default));
110
+ /* 家族 chrome 不设字号:控件自身就是盒,正文字号由这里给 */
66
111
  font-size: var(--xh-field-control-font-size, var(--xh-text-body-size));
67
112
  }
68
113
 
69
- [data-scope='field'][data-part='control']:focus-visible {
70
- border-color: var(--xh-field-control-border-focus, var(--xh-_tone, var(--xh-border-control-focus)));
71
- outline: var(--xh-ring-width) solid var(--xh-ring-focus);
72
- outline-offset: var(--xh-ring-offset);
73
- }
74
-
75
- [data-scope='field'][data-part='control'][data-invalid] {
76
- border-color: var(--xh-field-control-border-invalid, var(--xh-border-invalid));
77
- }
78
-
79
- /* 禁用由作者在控件上落原生 disabled,样式统一走 data-disabled */
80
- [data-scope='field'][data-part='control'][data-disabled] {
81
- background: var(--xh-field-control-bg-disabled, var(--xh-bg-subtle));
82
- color: var(--xh-fg-disabled);
83
- cursor: not-allowed;
114
+ /* 无效标签色的默认在 label.css 公共层;这里只把颜色接到本组件的覆盖槽上 */
115
+ [data-scope='field'][data-part='label'][data-invalid] {
116
+ color: var(--xh-field-label-fg-invalid, var(--xh-fg-danger));
84
117
  }
85
118
 
119
+ /* 说明与错误文案的角色(外边距、行距、默认字号与字色)在 description.css 公共层;
120
+ 这里只把字色与字号接到本组件的覆盖槽上 */
86
121
  [data-scope='field'][data-part='description'] {
87
- margin: 0;
88
122
  color: var(--xh-field-description-fg, var(--xh-fg-muted));
89
123
  font-size: var(--xh-field-description-font-size, var(--xh-text-secondary-size));
90
- line-height: var(--xh-leading-normal);
91
124
  }
92
125
 
93
126
  [data-scope='field'][data-part='description'][data-disabled] {
94
127
  color: var(--xh-field-description-fg-disabled, var(--xh-fg-subtle));
95
128
  }
96
129
 
97
- /* 不 invalid 时节点带 hidden:此处不声明 display,交给浏览器的 [hidden] 规则收起 */
98
130
  [data-scope='field'][data-part='error-text'] {
99
- margin: 0;
100
131
  color: var(--xh-field-error-fg, var(--xh-fg-danger));
101
132
  font-size: var(--xh-field-error-font-size, var(--xh-text-secondary-size));
133
+ }
134
+
135
+ /* 辅助文字那一行的占位:字段渲染了错误文案、当前又没在报错时,补一个与错误文案等高的空块。
136
+ 报错时这个空块让位给错误文案,字段的外框高度前后一样,表单不会因为一段错误文字重新排版,
137
+ 定高或限高的父级里也不会把控件挤出去。
138
+
139
+ 两个条件缺一不可:
140
+ 渲染了 error-text 且它带 hidden——没有错误文案可显示的字段不占这一行;
141
+ 没有在场的 description——描述已经占着这一行了,报错时由描述让位给错误文案(见 description.css)。
142
+
143
+ 高度按错误文案那一档的字号乘行距算,得到的正是它一行的高度。
144
+ 不写 1lh:那个单位晚于本库声明的浏览器地板,取不到时整条声明被丢弃、占位高退回 0,
145
+ 字段又会随报错撑高一次,而这种失效不报错。
146
+ 与前一块的距离由根的 gap 给,和错误文案顶上来时是同一段。 */
147
+ [data-scope='field'][data-part='root']:has(> [data-scope='field'][data-part='error-text'][hidden]):not(
148
+ :has(> [data-scope='field'][data-part='description']:not([hidden]))
149
+ )::after {
150
+ content: '';
151
+ block-size: calc(
152
+ var(--xh-field-error-font-size, var(--xh-text-secondary-size)) * var(--xh-leading-normal)
153
+ );
154
+ font-size: var(--xh-field-error-font-size, var(--xh-text-secondary-size));
102
155
  line-height: var(--xh-leading-normal);
103
156
  }
104
157
 
package/css/fieldset.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
+ /* 定义 fieldset 样式。 */
7
+
1
8
  @layer xihan.components {
2
9
  /* 皮肤在场的标记:开发模式下按 scope 探一次,取不到就说明这份皮肤没被引入。 */
3
10
  [data-scope='fieldset'] {
@@ -24,46 +31,72 @@
24
31
  [data-scope='fieldset'][data-part='legend'] {
25
32
  padding: 0;
26
33
  margin-block-end: var(--xh-fieldset-legend-gap, var(--xh-space-2));
27
- color: var(--xh-fieldset-legend-fg, var(--xh-fg-default));
34
+ /* 组标题是「一组字段的标题」,归集合标题角色(§6.4):fg-muted,与组 --xh-space-2,字号字重同字段标签 */
35
+ color: var(--xh-fieldset-legend-fg, var(--xh-fg-muted));
28
36
  font-size: var(--xh-fieldset-legend-font-size, var(--xh-text-label-size));
29
37
  font-weight: var(--xh-fieldset-legend-font-weight, var(--xh-text-label-weight));
30
38
  line-height: var(--xh-leading-tight);
39
+ /* 整组转无效或转禁用时组标题换色,两档之间接一段过渡 */
40
+ transition: color var(--xh-motion-duration-micro) var(--xh-motion-ease-enter);
31
41
  }
32
42
 
33
- /* 整组无效时组标题转警示色:没渲染错误文案的字段集上,这是屏幕上唯一变化的东西 */
34
- [data-scope='fieldset'][data-part='root'][data-invalid] > [data-scope='fieldset'][data-part='legend'] {
43
+ /* 整组无效时组标题转警示色:没渲染错误文案的字段集上,这是屏幕上唯一变化的东西。
44
+ 默认色在 label.css 公共层,这里只把颜色接到本组件的覆盖槽上 */
45
+ [data-scope='fieldset'][data-part='legend'][data-invalid] {
35
46
  color: var(--xh-fieldset-legend-fg-invalid, var(--xh-fg-danger));
36
47
  }
37
48
 
38
49
  /* 整组禁用时组标题跟着变淡;组内控件由原生 fieldset[disabled] 各自呈现禁用态。
39
- 选择器与上一条同权重且排在后面,禁用与无效同时为真时以禁用为准。 */
50
+ 选择器权重高于上一条且排在后面,禁用与无效同时为真时以禁用为准。 */
40
51
  [data-scope='fieldset'][data-part='root'] > [data-scope='fieldset'][data-part='legend'][data-disabled] {
41
52
  color: var(--xh-fieldset-legend-fg-disabled, var(--xh-fg-subtle));
42
53
  }
43
54
 
44
- /* 必填星号:跟着根上的 data-required 亮,选填不标 */
45
- [data-scope='fieldset'][data-part='root'][data-required] > [data-scope='fieldset'][data-part='legend']::after {
46
- content: var(--xh-glyph-mark-required);
47
- margin-inline-start: var(--xh-space-1);
55
+ /* 必填星号的字形、间距与默认色在 label.css 公共层;这里只把颜色接到本组件的覆盖槽上 */
56
+ [data-scope='fieldset'][data-part='legend'][data-required]::after {
48
57
  color: var(--xh-fieldset-legend-star, var(--xh-fg-danger));
49
58
  }
50
59
 
51
- [data-scope='fieldset'][data-part='helper-text'] {
52
- margin: 0;
53
- color: var(--xh-fieldset-helper-fg, var(--xh-fg-muted));
54
- font-size: var(--xh-fieldset-helper-font-size, var(--xh-text-secondary-size));
55
- line-height: var(--xh-leading-normal);
60
+ /* 说明与错误文案的角色(外边距、行距、默认字号与字色)在 description.css 公共层;
61
+ 这里只把字色与字号接到本组件的覆盖槽上 */
62
+ [data-scope='fieldset'][data-part='description'] {
63
+ color: var(--xh-fieldset-description-fg, var(--xh-fg-muted));
64
+ font-size: var(--xh-fieldset-description-font-size, var(--xh-text-secondary-size));
65
+ /* 与组标题同一档过渡:整组转禁用时两处一起变淡 */
66
+ transition: color var(--xh-motion-duration-micro) var(--xh-motion-ease-enter);
67
+ }
68
+
69
+ [data-scope='fieldset'][data-part='description'][data-disabled] {
70
+ color: var(--xh-fieldset-description-fg-disabled, var(--xh-fg-subtle));
71
+ }
72
+
73
+ /* 并排字段的一段:窄屏一列,够宽了按列宽自动分栏。列宽下限由槽给,作者按字段类型改 */
74
+ [data-scope='fieldset'][data-part='field-group'] {
75
+ display: grid;
76
+ grid-template-columns: repeat(auto-fit, minmax(var(--xh-fieldset-field-group-col-w, var(--xh-layout-col-min-sm)), 1fr));
77
+ gap: var(--xh-fieldset-field-group-gap, var(--xh-space-3));
78
+ align-items: start;
56
79
  }
57
80
 
58
- [data-scope='fieldset'][data-part='helper-text'][data-disabled] {
59
- color: var(--xh-fieldset-helper-fg-disabled, var(--xh-fg-subtle));
81
+ [data-scope='fieldset'][data-part='field-group'][hidden] {
82
+ display: none;
83
+ }
84
+
85
+ /* 组末尾那一行按钮:靠尾端排,窄屏换行 */
86
+ [data-scope='fieldset'][data-part='actions'] {
87
+ display: flex;
88
+ flex-wrap: wrap;
89
+ align-items: center;
90
+ justify-content: flex-end;
91
+ gap: var(--xh-fieldset-actions-gap, var(--xh-space-2));
92
+ }
93
+
94
+ [data-scope='fieldset'][data-part='actions'][hidden] {
95
+ display: none;
60
96
  }
61
97
 
62
- /* 不 invalid 时节点带 hidden:此处不声明 display,交给浏览器的 [hidden] 规则收起 */
63
98
  [data-scope='fieldset'][data-part='error-text'] {
64
- margin: 0;
65
99
  color: var(--xh-fieldset-error-fg, var(--xh-fg-danger));
66
100
  font-size: var(--xh-fieldset-error-font-size, var(--xh-text-secondary-size));
67
- line-height: var(--xh-leading-normal);
68
101
  }
69
102
  }