@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
@@ -1,3 +1,12 @@
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
+ /* NumberField 独立皮肤同时传递引入字段视觉盒与字段内动作;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='number-field'] {
@@ -5,43 +14,33 @@
5
14
  }
6
15
 
7
16
  /* 与文本框同一套堆叠:标签一行、输入行一行。
8
- 输入框与加减钮放进 control 部件即得一体式:视觉盒画在 control 上,
9
- 减在左、加在右、输入框居中,前后缀图标/文字可直接流式插在框内。
10
- 不写 control 时退回旧式三件并排的观感(下方 input / 按钮的基础规则原样生效) */
17
+ control 是必需的唯一视觉盒,输入框、加减钮与前后缀都放在里面;
18
+ 输入与前后缀在左,减、加两颗动作依次收在逻辑末端。
19
+ 组件层只把既有公开槽映射到家族合同;形态三档由家族按 control 上的 data-variant 生成,皮肤不再声明。 */
11
20
  [data-scope='number-field'][data-part='root'] {
12
21
  /* 作者塞进来的图标跟着控件的尺寸档走;它自己写了 size 时仍以作者的为准 */
13
22
  --xh-icon-size: var(--xh-number-field-icon-size, var(--xh-glyph-size-md));
14
23
 
15
- /* 尺寸档只换这几个私有槽,标题、输入框与加减钮都从 root 继承它们,
24
+ /* 尺寸档只换这几个私有槽,输入框与加减钮都从 root 继承它们,
16
25
  换档不必给每个部件各写一条选择器 */
17
26
  --xh-_number-field-h: var(--xh-control-h-md);
18
27
  --xh-_number-field-px: var(--xh-control-px-md);
19
- --xh-_number-field-gap: var(--xh-control-gap-md);
28
+ --xh-_number-field-gap: 0;
20
29
  --xh-_number-field-font-size: var(--xh-control-font-md);
21
- --xh-_number-field-label-font-size: var(--xh-control-font-md);
22
30
  --xh-_number-field-trigger-font-size: var(--xh-control-font-md);
23
31
 
24
- /* 盒子的圆角 */
25
- --xh-_number-field-radius: var(--xh-number-field-input-radius, var(--xh-shape-control));
26
-
27
- /* 形态档只换这几个私有槽:输入框的底与描边,加减钮的底与描边 */
28
- --xh-_number-field-bg: var(--xh-bg-canvas);
29
- --xh-_number-field-border: var(--xh-border-control);
30
- --xh-_number-field-border-hover: var(--xh-border-control-hover);
31
- --xh-_number-field-trigger-bg: var(--xh-bg-subtle);
32
- --xh-_number-field-trigger-bg-hover: var(--xh-bg-subtle-hover);
33
- --xh-_number-field-trigger-bg-active: var(--xh-bg-subtle-active);
34
- --xh-_number-field-trigger-border: var(--xh-border-control);
35
- --xh-_number-field-trigger-border-hover: var(--xh-border-control-hover);
36
-
37
- /* 语气只落在聚焦这一处:环与聚焦态描边。框里的数字不归它管。
38
- 没写 data-tone 时 --xh-_tone 没被声明,退回原来的聚焦环色与常态描边 */
39
- --xh-_number-field-ring: var(--xh-ring-focus);
40
- --xh-_number-field-border-focus: var(--xh-number-field-input-border, var(--xh-_tone, var(--xh-border-control-focus)));
32
+ /* 盒内那道分隔线的长度:取钮高的一半,线的上下各留一截空白,不与钮等高 */
33
+ --xh-_number-field-divider-h: 50%;
41
34
 
42
35
  display: inline-flex;
43
36
  flex-direction: column;
44
37
  gap: var(--xh-number-field-gap, var(--xh-space-1));
38
+
39
+ /* 不传尺寸时一律这么宽,宽度不随内容走;父容器给不出这么宽时整件跟着收,地板同步让步,不越出父容器。
40
+ 地板不高过缺省宽:使用者把缺省宽钉到底线以下时不必再放开底线 */
41
+ inline-size: var(--xh-number-field-control-w, var(--xh-control-w));
42
+ min-inline-size: min(var(--xh-number-field-control-w, var(--xh-control-w)), var(--xh-number-field-control-min-w, var(--xh-control-min-w)), 100%);
43
+ max-inline-size: 100%;
45
44
  }
46
45
 
47
46
  /* 声明了 display 就盖掉了 UA 的 [hidden]{display:none},收起态得自己还回去 */
@@ -55,9 +54,7 @@
55
54
  --xh-icon-size: var(--xh-number-field-icon-size, var(--xh-glyph-size-sm));
56
55
  --xh-_number-field-h: var(--xh-control-h-sm);
57
56
  --xh-_number-field-px: var(--xh-control-px-sm);
58
- --xh-_number-field-gap: var(--xh-control-gap-sm);
59
57
  --xh-_number-field-font-size: var(--xh-control-font-sm);
60
- --xh-_number-field-label-font-size: var(--xh-control-font-sm);
61
58
  --xh-_number-field-trigger-font-size: var(--xh-control-font-sm);
62
59
  }
63
60
 
@@ -65,59 +62,14 @@
65
62
  --xh-icon-size: var(--xh-number-field-icon-size, var(--xh-glyph-size-lg));
66
63
  --xh-_number-field-h: var(--xh-control-h-lg);
67
64
  --xh-_number-field-px: var(--xh-control-px-lg);
68
- --xh-_number-field-gap: var(--xh-control-gap-lg);
69
65
  --xh-_number-field-font-size: var(--xh-control-font-lg);
70
- --xh-_number-field-label-font-size: var(--xh-control-font-lg);
71
66
  --xh-_number-field-trigger-font-size: var(--xh-control-font-lg);
72
67
  }
73
68
 
74
- /* —— 形态 —— */
75
- /* 形态只决定底与描边怎么画;用哪族颜色由 data-tone 决定。
76
- 输入框没有实心档:填满一个要往里打字的框,字与底就没法同时读 */
77
- [data-scope='number-field'][data-part='root'][data-variant='outline'] {
78
- --xh-_number-field-bg: var(--xh-bg-canvas);
79
- --xh-_number-field-border: var(--xh-border-control);
80
- --xh-_number-field-border-hover: var(--xh-border-control-hover);
81
- --xh-_number-field-trigger-bg: var(--xh-bg-subtle);
82
- --xh-_number-field-trigger-bg-hover: var(--xh-bg-subtle-hover);
83
- --xh-_number-field-trigger-bg-active: var(--xh-bg-subtle-active);
84
- --xh-_number-field-trigger-border: var(--xh-border-control);
85
- --xh-_number-field-trigger-border-hover: var(--xh-border-control-hover);
86
- --xh-_number-field-border-focus: var(--xh-number-field-input-border, var(--xh-_tone, var(--xh-border-control-focus)));
87
- }
88
-
89
- /* 填充式:底色顶替描边表达边界。描边只退成透明而不去掉,1px 的位置留着,
90
- 与 outline 档并排时基线对得上、聚焦画描边也不引起跳动 */
91
- [data-scope='number-field'][data-part='root'][data-variant='subtle'] {
92
- --xh-_number-field-bg: var(--xh-_tone-subtle, var(--xh-bg-subtle));
93
- --xh-_number-field-border: transparent;
94
- --xh-_number-field-border-hover: var(--xh-_tone-border, var(--xh-border-control-hover));
95
- --xh-_number-field-trigger-bg: var(--xh-_tone-subtle, var(--xh-bg-subtle));
96
- --xh-_number-field-trigger-bg-hover: var(--xh-_tone-subtle-hover, var(--xh-bg-subtle-hover));
97
- --xh-_number-field-trigger-bg-active: var(--xh-_tone-subtle-active, var(--xh-bg-subtle-active));
98
- --xh-_number-field-trigger-border: transparent;
99
- --xh-_number-field-trigger-border-hover: var(--xh-_tone-border, var(--xh-border-control-hover));
100
- --xh-_number-field-border-focus: var(--xh-_tone, var(--xh-border-control-focus));
101
- }
102
-
103
- /* 无框:底与常态描边透明,悬停与聚焦浮出描边 */
104
- [data-scope='number-field'][data-part='root'][data-variant='ghost'] {
105
- --xh-_number-field-bg: transparent;
106
- --xh-_number-field-border: transparent;
107
- --xh-_number-field-border-hover: var(--xh-_tone-border, var(--xh-border-control-hover));
108
- --xh-_number-field-trigger-bg: transparent;
109
- --xh-_number-field-trigger-bg-hover: var(--xh-_tone-subtle, var(--xh-bg-subtle-hover));
110
- --xh-_number-field-trigger-bg-active: var(--xh-_tone-subtle-active, var(--xh-bg-subtle-active));
111
- --xh-_number-field-trigger-border: transparent;
112
- --xh-_number-field-trigger-border-hover: var(--xh-_tone-border, var(--xh-border-control-hover));
113
- --xh-_number-field-border-focus: var(--xh-_tone, var(--xh-border-control-focus));
114
- }
115
-
116
69
  [data-scope='number-field'][data-part='label'] {
117
70
  color: var(--xh-number-field-label-fg, var(--xh-fg-default));
118
- font-size: var(--xh-number-field-label-font-size, var(--xh-_number-field-label-font-size));
71
+ font-size: var(--xh-number-field-label-font-size, var(--xh-text-label-size));
119
72
  font-weight: var(--xh-number-field-label-font-weight, var(--xh-text-label-weight));
120
- line-height: var(--xh-leading-none);
121
73
  }
122
74
 
123
75
  [data-scope='number-field'][data-part='label'][data-disabled] {
@@ -125,239 +77,122 @@
125
77
  }
126
78
 
127
79
  /* —— 一体式 control:输入框与加减钮同框 —— */
128
- /* control 是唯一的视觉盒:描边、底色、圆角、聚焦环全画在它身上,盒内三件都退成透明分段,
129
- 整枚控件从头到尾只有这一道描边。减钮在前、input 居中、加钮在后(作者在模板里的顺序决定),
130
- 前后缀内容直接流式插在框里。
131
- focus-within 而不是 :focus 上的聚焦态:按钮也能触发聚焦环 */
80
+ /* control 是唯一的视觉盒:描边、底色、圆角、聚焦环、五态与悬停由 Field Chrome 家族画,
81
+ 盒内三件都退成透明分段,整枚控件从头到尾只有这一道描边。
82
+ 外观槽按所在部件取名 --xh-number-field-control-*;--xh-number-field-input-* 只管
83
+ input 自己的字色与内衬。控件不给内衬:内衬走 input 与钮各自的盒。 */
132
84
  [data-scope='number-field'][data-part='control'] {
133
- position: relative;
134
- display: inline-flex;
135
- /* 居中而不是拉伸:作者插在框里的前后缀是一行文字,被拉满整框高度后字会贴着框顶 */
136
- align-items: center;
137
- gap: var(--xh-number-field-control-gap, var(--xh-_number-field-gap));
138
- min-inline-size: var(--xh-number-field-control-min-w, var(--xh-control-min-w));
139
- block-size: var(--xh-number-field-control-h, var(--xh-_number-field-h));
140
- padding-inline: var(--xh-number-field-control-px, var(--xh-_number-field-px));
141
- border: var(--xh-stroke-thin) solid var(--xh-number-field-input-border, var(--xh-_number-field-border));
142
- border-radius: var(--xh-_number-field-radius);
143
- background: var(--xh-number-field-input-bg, var(--xh-_number-field-bg));
144
- transition: border-color var(--xh-motion-duration-micro) var(--xh-motion-ease-enter);
145
- }
146
-
147
- [data-scope='number-field'][data-part='control']:hover:not([data-disabled], [data-invalid]) {
148
- border-color: var(--xh-number-field-input-border-hover, var(--xh-_number-field-border-hover));
149
- }
85
+ --xh-field-control-height: var(--xh-number-field-control-h, var(--xh-_number-field-h));
86
+ --xh-field-control-padding-inline: var(--xh-number-field-control-px, 0);
87
+ --xh-field-control-gap: var(--xh-number-field-control-gap, var(--xh-_number-field-gap));
88
+ --xh-field-control-min-inline-size: var(--xh-number-field-control-min-w, var(--xh-control-min-w));
89
+ --xh-field-control-radius: var(--xh-number-field-control-radius, var(--xh-shape-control));
90
+ --xh-field-bg-rest: var(--xh-number-field-control-bg, var(--xh-_field-variant-bg-rest));
91
+ --xh-field-bg-hover: var(--xh-number-field-control-bg-hover, var(--xh-_field-variant-bg-hover));
92
+ --xh-field-bg-read-only: var(--xh-number-field-control-bg-readonly, var(--xh-_field-variant-bg-read-only));
93
+ --xh-field-bg-disabled: var(--xh-number-field-control-bg-disabled, var(--xh-_field-variant-bg-disabled));
94
+ --xh-field-fg-rest: var(--xh-number-field-control-fg, var(--xh-fg-default));
95
+ --xh-field-border-rest: var(--xh-number-field-control-border, var(--xh-_field-variant-border-rest));
96
+ --xh-field-border-hover: var(--xh-number-field-control-border-hover, var(--xh-_field-variant-border-hover));
97
+ --xh-field-border-focus: var(--xh-number-field-control-border-focus, var(--xh-_field-variant-border-focus));
98
+ --xh-field-border-invalid: var(--xh-number-field-control-border-invalid, var(--xh-_field-variant-border-invalid));
99
+ --xh-field-ring-focus: var(--xh-ring-focus);
100
+ --xh-field-ring-invalid: var(--xh-ring-invalid);
101
+ --xh-field-shadow-rest: var(--xh-number-field-control-shadow, none);
102
+ /* 家族 chrome 会重写 --xh-icon-size,使用者图标槽必须经桥接槽下发才能在盒内生效 */
103
+ --xh-field-glyph-size: var(--xh-number-field-icon-size, var(--xh-_field-size-glyph-size));
150
104
 
151
- [data-scope='number-field'][data-part='control']:focus-within:not([data-disabled]) {
152
- border-color: var(--xh-number-field-input-border-focus, var(--xh-_number-field-border-focus));
153
- outline: var(--xh-ring-width) solid var(--xh-_number-field-ring);
154
- outline-offset: var(--xh-ring-offset);
155
- }
156
-
157
- [data-scope='number-field'][data-part='control'][data-invalid] {
158
- border-color: var(--xh-number-field-input-border-invalid, var(--xh-border-invalid));
159
-
160
- /* 校验失败时环也跟着变红:两圈等宽相邻却一红一蓝,读的人不知道哪个才是当前状态 */
161
- --xh-_number-field-ring: var(--xh-ring-invalid);
105
+ position: relative;
162
106
  }
163
107
 
164
- [data-scope='number-field'][data-part='control'][data-readonly] {
165
- background: var(--xh-number-field-input-bg-readonly, var(--xh-bg-subtle));
108
+ /* 装饰段:货币符、单位、图标。与输入框同框,不参与分宽,弱一档前景把它与数字分开 */
109
+ [data-scope='number-field'][data-part='prefix'],
110
+ [data-scope='number-field'][data-part='suffix'] {
111
+ --xh-field-affix-fg: var(--xh-number-field-affix-fg, var(--xh-fg-muted));
112
+ --xh-field-affix-fg-disabled: var(--xh-number-field-affix-fg-disabled, var(--xh-fg-disabled));
113
+ --xh-field-affix-font-size: var(--xh-number-field-affix-font-size, var(--xh-_number-field-font-size));
166
114
  }
167
115
 
168
- [data-scope='number-field'][data-part='control'][data-disabled] {
169
- background: var(--xh-number-field-input-bg-disabled, var(--xh-bg-subtle));
170
- color: var(--xh-fg-disabled);
171
- cursor: not-allowed;
116
+ [data-scope='number-field'][data-part='prefix'][hidden],
117
+ [data-scope='number-field'][data-part='suffix'][hidden] {
118
+ display: none;
172
119
  }
173
120
 
174
- /* 盒内 input:无边框无底无圆角,观感全归 control;行内内衬也归 control,
175
- 这里再留一份就是框内套了一圈空白。数字居中排在两个按钮之间;
121
+ /* 盒内 input:无边框无底无圆角无落影由家族重置,观感全归 control
122
+ 数字居中排在两个按钮之间,行内内衬留给它自己(control 不给内衬);
176
123
  前后缀图标/文字直接流式排在 input 两侧,不用再绝对定位 */
177
124
  [data-scope='number-field'][data-part='control'] [data-part='input'] {
178
- flex: 1 1 auto;
125
+ --xh-field-input-fg: var(--xh-number-field-input-fg, var(--xh-fg-default));
126
+ --xh-field-input-font-size: var(--xh-number-field-input-font-size, var(--xh-_number-field-font-size));
127
+ --xh-field-placeholder-fg: var(--xh-number-field-placeholder-fg, var(--xh-fg-subtle));
128
+ --xh-field-autofill-bg: var(--xh-number-field-input-autofill-bg, var(--xh-bg-canvas));
129
+ --xh-field-autofill-fg: var(--xh-number-field-input-autofill-fg, var(--xh-fg-default));
130
+
179
131
  inline-size: var(--xh-number-field-input-w, 5em);
180
- min-inline-size: 0;
181
- block-size: 100%;
182
- padding-inline: 0;
183
- border: 0;
184
- border-radius: 0;
185
- background: transparent;
132
+ padding-inline: var(--xh-number-field-input-px, var(--xh-_number-field-px));
133
+ font-variant-numeric: tabular-nums;
186
134
  text-align: var(--xh-number-field-input-align, center);
187
135
  }
188
136
 
189
- /* 盒内 input 不再自己画各态,全部交还 control。hover 这条带上与基础规则同样的
190
- :not 条件:基础 hover 的特异度里有它们,不带就打不过 */
191
- [data-scope='number-field'][data-part='control'] [data-part='input']:hover:not(:disabled, [data-invalid]) {
192
- border-color: transparent;
193
- }
194
-
195
- [data-scope='number-field'][data-part='control'] [data-part='input']:focus-visible {
196
- border-color: transparent;
197
- outline: none;
198
- }
199
-
200
- [data-scope='number-field'][data-part='control'] [data-part='input'][data-invalid] {
201
- border-color: transparent;
202
- }
203
-
204
- [data-scope='number-field'][data-part='control'] [data-part='input']:disabled,
205
- [data-scope='number-field'][data-part='control'] [data-part='input'][readonly] {
206
- background: transparent;
207
- }
208
-
209
- /* 盒内按钮:尺寸与圆角走基础规则那枚行内动作方钮,这里只把底与描边交还 control——
210
- 按钮自带一块底色就会把一个盒子读成三块拼起来的;
211
- 常态只剩符号,符号取次级前景,悬停与按下才浮出底色 */
137
+ /* 盒内按钮:正方视觉盒、inset 圆角、悬停 100 / 按下 200 与 0.97 按压、粗指针热区与
138
+ :focus-visible 关环全由 Action Control 的 field-inset ghost 档给,组件只映射既有覆盖槽。
139
+ 常态只剩符号,符号取默认前景,悬停与按下才浮出底色 */
212
140
  [data-scope='number-field'][data-part='control'] [data-part='increment-trigger'],
213
141
  [data-scope='number-field'][data-part='control'] [data-part='decrement-trigger'] {
214
- margin: 0;
215
- border: 0;
216
- background: transparent;
217
- color: var(--xh-number-field-trigger-fg, var(--xh-fg-muted));
218
- }
219
-
220
- /* 悬停只在分段自己身上浮出一块底色与更实的符号,盒子的描边纹丝不动 */
221
- [data-scope='number-field'][data-part='control'] [data-part='increment-trigger']:hover:not(:disabled),
222
- [data-scope='number-field'][data-part='control'] [data-part='decrement-trigger']:hover:not(:disabled) {
223
- background: var(--xh-number-field-trigger-bg-hover, var(--xh-_number-field-trigger-bg-hover));
224
- color: var(--xh-number-field-trigger-fg-hover, var(--xh-fg-default));
225
- }
226
-
227
- [data-scope='number-field'][data-part='control'] [data-part='increment-trigger']:active:not(:disabled),
228
- [data-scope='number-field'][data-part='control'] [data-part='decrement-trigger']:active:not(:disabled) {
229
- background: var(--xh-number-field-trigger-bg-active, var(--xh-_number-field-trigger-bg-active));
230
- }
231
-
232
- /* 焦点落到盒内按钮时 control 已经 focus-within 起了环,按钮自己再画一圈就是框里套框 */
233
- [data-scope='number-field'][data-part='control'] [data-part='increment-trigger']:focus-visible,
234
- [data-scope='number-field'][data-part='control'] [data-part='decrement-trigger']:focus-visible {
235
- outline: none;
236
- }
237
-
238
- /* 贴住 min / max 的那一侧只把符号压灰,不铺一块灰底:铺了底就又成了框上贴着的一个方块 */
239
- [data-scope='number-field'][data-part='control'] [data-part='increment-trigger']:disabled,
240
- [data-scope='number-field'][data-part='control'] [data-part='decrement-trigger']:disabled {
241
- background: transparent;
242
- color: var(--xh-fg-disabled);
243
- }
244
-
245
- [data-scope='number-field'][data-part='input'] {
246
- block-size: var(--xh-number-field-input-h, var(--xh-_number-field-h));
247
- padding-inline: var(--xh-number-field-input-px, var(--xh-_number-field-px));
248
- padding-block: 0;
249
- border: var(--xh-stroke-thin) solid var(--xh-number-field-input-border, var(--xh-_number-field-border));
250
- border-radius: var(--xh-_number-field-radius);
251
- background: var(--xh-number-field-input-bg, var(--xh-_number-field-bg));
252
- color: var(--xh-number-field-input-fg, var(--xh-fg-default));
253
- /* 表单控件不继承页面字体,只给字号会让输入框用 UA 默认字族 */
254
- font-family: inherit;
255
- font-size: var(--xh-number-field-input-font-size, var(--xh-_number-field-font-size));
256
- /* 等宽数字:按住加减钮连发时字宽一变,框里的数字就会左右抖 */
257
- font-variant-numeric: tabular-nums;
258
- line-height: var(--xh-leading-normal);
259
- transition: border-color var(--xh-motion-duration-micro) var(--xh-motion-ease-enter);
260
- }
261
-
262
- [data-scope='number-field'][data-part='input']::placeholder {
263
- color: var(--xh-number-field-placeholder-fg, var(--xh-fg-subtle));
264
- }
265
-
266
- /* hover 只在中性态换描边:invalid 正拿边框颜色说事,被 hover 盖掉那条信息就没了 */
267
- [data-scope='number-field'][data-part='input']:hover:not(:disabled, [data-invalid]) {
268
- border-color: var(--xh-number-field-input-border-hover, var(--xh-_number-field-border-hover));
269
- }
270
-
271
- /* 聚焦态描边与环共用一族语气色。这条特异度低于上面的 hover、也低于下面的 invalid,
272
- 两者仍按原来的次序赢过它 */
273
- [data-scope='number-field'][data-part='input']:focus-visible {
274
- border-color: var(--xh-number-field-input-border-focus, var(--xh-_number-field-border-focus));
275
- outline: var(--xh-ring-width) solid var(--xh-_number-field-ring);
276
- outline-offset: var(--xh-ring-offset);
277
- }
278
-
279
- [data-scope='number-field'][data-part='input'][data-invalid] {
280
- border-color: var(--xh-number-field-input-border-invalid, var(--xh-border-invalid));
281
-
282
- /* 校验失败时环也跟着变红:两圈等宽相邻却一红一蓝,读的人不知道哪个才是当前状态 */
283
- --xh-_number-field-ring: var(--xh-ring-invalid);
284
- }
285
-
286
- /* 只读仍可聚焦、可复制,不置灰,只把底色压下去表示"改不动" */
287
- [data-scope='number-field'][data-part='input'][readonly] {
288
- background: var(--xh-number-field-input-bg-readonly, var(--xh-bg-subtle));
289
- }
290
-
291
- /* input 是单体表单控件,禁用走原生 disabled */
292
- [data-scope='number-field'][data-part='input']:disabled {
293
- background: var(--xh-number-field-input-bg-disabled, var(--xh-bg-subtle));
294
- color: var(--xh-fg-disabled);
295
- cursor: not-allowed;
142
+ --xh-action-visual-size: var(--xh-number-field-trigger-size, var(--xh-_action-profile-visual-size));
143
+ --xh-action-min-inline-size: var(--xh-number-field-trigger-size, var(--xh-_action-profile-visual-size));
144
+ --xh-action-radius: var(--xh-number-field-trigger-radius, var(--xh-shape-inset));
145
+ /* 底色阶梯由 ghost 档给(透明 → 100 → 200),使用者槽只作覆盖入口 */
146
+ --xh-action-bg-pressed: var(--xh-number-field-trigger-bg-active, var(--xh-_action-variant-bg-pressed));
147
+ --xh-action-fg-rest: var(--xh-number-field-trigger-fg, var(--xh-fg-default));
148
+ --xh-action-fg-hover: var(--xh-number-field-trigger-fg-hover, var(--xh-fg-default));
149
+ --xh-action-border-rest: transparent;
150
+ --xh-action-highlight-rest: transparent;
151
+ --xh-action-shadow-rest: none;
152
+ --xh-action-shadow-hover: none;
153
+ --xh-action-shadow-pressed: none;
154
+ --xh-action-font-size: var(--xh-number-field-trigger-font-size, var(--xh-_number-field-trigger-font-size));
155
+ /* 配方尚未把 profile 字形档灌进 --xh-icon-size,钮内字形先按 field-inset 档逐钮取值 */
156
+ --xh-icon-size: var(--xh-_action-profile-glyph-size);
157
+
158
+ border-width: 0;
159
+ }
160
+
161
+ /* DOM 顺序不承担视觉位置:既有用法即使把减钮写在 input 前面,默认仍统一收进右侧动作组。 */
162
+ [data-scope='number-field'][data-part='control'] [data-part='decrement-trigger'] {
163
+ order: 1;
296
164
  }
297
165
 
298
- /* 两个方向共用一份皮肤:加减钮是同一种东西,只是朝向不同,
299
- 分开写迟早会一边改了另一边忘了 */
300
- [data-scope='number-field'][data-part='increment-trigger'],
301
- [data-scope='number-field'][data-part='decrement-trigger'] {
302
- display: inline-flex;
303
- flex: none;
304
- align-items: center;
305
- justify-content: center;
306
- inline-size: var(--xh-number-field-trigger-size, var(--xh-control-action-size));
307
- block-size: var(--xh-number-field-trigger-size, var(--xh-control-action-size));
308
- padding: 0;
309
- border: var(--xh-stroke-thin) solid var(--xh-number-field-trigger-border, var(--xh-_number-field-trigger-border));
310
- border-radius: var(--xh-number-field-trigger-radius, var(--xh-shape-control));
311
- background: var(--xh-number-field-trigger-bg, var(--xh-_number-field-trigger-bg));
312
- color: var(--xh-number-field-trigger-fg, var(--xh-fg-default));
313
- font-family: inherit;
314
- font-size: var(--xh-number-field-trigger-font-size, var(--xh-_number-field-trigger-font-size));
315
- line-height: var(--xh-leading-none);
316
- cursor: pointer;
317
- /* 按住不放会连发,长按期间浏览器默认会去选中按钮里的符号、
318
- 触屏上还会当成双击缩放,两条都得先掐掉 */
319
- user-select: none;
320
- touch-action: manipulation;
321
- transition: background var(--xh-motion-duration-micro) var(--xh-motion-ease-enter);
166
+ [data-scope='number-field'][data-part='control'] [data-part='increment-trigger'] {
167
+ order: 2;
322
168
  }
323
169
 
324
- /* 上面给了 display,UA 的 [hidden]{display:none} 已被盖掉,这里补回来 */
325
- [data-scope='number-field'][data-part='increment-trigger'][hidden],
326
- [data-scope='number-field'][data-part='decrement-trigger'][hidden] {
170
+ [data-scope='number-field'][data-part='control'] [data-part='increment-trigger'][hidden],
171
+ [data-scope='number-field'][data-part='control'] [data-part='decrement-trigger'][hidden] {
327
172
  display: none;
328
173
  }
329
174
 
330
- [data-scope='number-field'][data-part='increment-trigger']:hover:not(:disabled),
331
- [data-scope='number-field'][data-part='decrement-trigger']:hover:not(:disabled) {
332
- border-color: var(--xh-number-field-trigger-border-hover, var(--xh-_number-field-trigger-border-hover));
333
- background: var(--xh-number-field-trigger-bg-hover, var(--xh-_number-field-trigger-bg-hover));
334
- }
335
-
336
- /* 连发期间按钮一直是按下态::active 在指针没松开时始终成立,正好对上 */
337
- [data-scope='number-field'][data-part='increment-trigger']:active:not(:disabled),
338
- [data-scope='number-field'][data-part='decrement-trigger']:active:not(:disabled) {
339
- background: var(--xh-number-field-trigger-bg-active, var(--xh-_number-field-trigger-bg-active));
175
+ /* 右侧动作组与输入之间的细线:把「按的」与「填的」分成两块。
176
+ 线不画在钮的边框上:边框会跟着钮的圆角与悬停底走,而这道线要独立于钮的各态,长度也短于钮自己。
177
+ ::before 已被兜底字形占着,::after 在粗指针下是家族给的 44px 热区,几何只能落在
178
+ background-image 上:一条 1px × 半高的渐变贴在逻辑起始侧,底色换态时它仍叠在上层。
179
+ 线只画在动作组第一颗减钮的逻辑起始侧;background-position 是物理轴,RTL 另给一条换边。 */
180
+ [data-scope='number-field'][data-part='control']:has([data-part='input']) [data-part='decrement-trigger'] {
181
+ background-image: linear-gradient(
182
+ var(--xh-number-field-trigger-divider, var(--xh-material-soft-separator)),
183
+ var(--xh-number-field-trigger-divider, var(--xh-material-soft-separator))
184
+ );
185
+ background-repeat: no-repeat;
186
+ background-position: 0 50%;
187
+ background-size: var(--xh-stroke-thin) var(--xh-number-field-trigger-divider-h, var(--xh-_number-field-divider-h));
340
188
  }
341
189
 
342
- /* 按钮不占 Tab 位(tabindex=-1),留这条是给程序化聚焦兜底 */
343
- [data-scope='number-field'][data-part='increment-trigger']:focus-visible,
344
- [data-scope='number-field'][data-part='decrement-trigger']:focus-visible {
345
- outline: var(--xh-ring-width) solid var(--xh-_number-field-ring);
346
- outline-offset: var(--xh-ring-offset);
347
- }
348
-
349
- /* 贴到 min / max 时连接层给对应那一侧落原生 disabled:单体控件用 :disabled,
350
- 不是集合条目那套 aria-disabled */
351
- [data-scope='number-field'][data-part='increment-trigger']:disabled,
352
- [data-scope='number-field'][data-part='decrement-trigger']:disabled {
353
- border-color: var(--xh-number-field-trigger-border-disabled, var(--xh-border-subtle));
354
- background: var(--xh-number-field-trigger-bg-disabled, var(--xh-bg-muted));
355
- color: var(--xh-fg-disabled);
356
- cursor: not-allowed;
190
+ [dir='rtl'] [data-scope='number-field'][data-part='control']:has([data-part='input']) [data-part='decrement-trigger'] {
191
+ background-position: 100% 50%;
357
192
  }
358
193
 
359
194
  /* 没写内容就由皮肤画兜底字形;作者往部件里塞了自己的图形,这几条即不命中 */
360
- [data-scope='number-field'][data-part='increment-trigger']:empty::before {
195
+ [data-scope='number-field'][data-part='control'] [data-part='increment-trigger']:empty::before {
361
196
  content: '';
362
197
  display: inline-block;
363
198
  inline-size: var(--xh-icon-size, var(--xh-glyph-size-text));
@@ -368,7 +203,7 @@
368
203
  mask: var(--xh-glyph-mark-plus) center / contain no-repeat;
369
204
  }
370
205
 
371
- [data-scope='number-field'][data-part='decrement-trigger']:empty::before {
206
+ [data-scope='number-field'][data-part='control'] [data-part='decrement-trigger']:empty::before {
372
207
  content: '';
373
208
  display: inline-block;
374
209
  inline-size: var(--xh-icon-size, var(--xh-glyph-size-text));
@@ -379,6 +214,14 @@
379
214
  mask: var(--xh-glyph-mark-minus) center / contain no-repeat;
380
215
  }
381
216
 
217
+ /* 高对比档整层丢弃 background-image,分隔线改用系统色重画,并关掉这一颗钮的强制换色 */
218
+ @media (forced-colors: active) {
219
+ [data-scope='number-field'][data-part='control']:has([data-part='input']) [data-part='decrement-trigger'] {
220
+ background-image: linear-gradient(ButtonText, ButtonText);
221
+ forced-color-adjust: none;
222
+ }
223
+ }
224
+
382
225
  /* 声明过任何 display 就盖掉了 UA 的 [hidden]{display:none},收起态得自己还回去。
383
226
  写在文件末尾:兜底必须排在该部件所有 display 声明之后 */
384
227
  [data-scope='number-field'][data-part='control'][hidden] {
@@ -1,14 +1,19 @@
1
1
  /*
2
- * 浮层箭头的几何,六份浮层皮肤共用一份,按 [data-part='arrow'] 匹配。
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
+ /*
7
+ * 浮层箭头的几何,八类浮层共用一份,只匹配这些组件自身的 arrow 部件。
3
8
  *
4
9
  * 箭头是正方形转 45°,构成尖角的是哪两条物理边,所以贴边与摘边框都写物理属性。
5
10
  * 行内轴上的中心点仍写逻辑属性:定位引擎在 RTL 下已把 arrow-x 镜像成逻辑量。
6
11
  *
7
12
  * 底色与描边色留在各组件皮肤,它们同时把自己的内联落点槽接到这里的统一名字上。
8
- * 引入顺序排在六份浮层皮肤之后:摘边框那几条要压过各皮肤的 border 简写。
13
+ * 引入顺序排在消费方皮肤之后;作用域使用 :where,维持原有特异性和摘边优先级。
9
14
  */
10
15
  @layer xihan.components {
11
- [data-part='arrow'] {
16
+ :where([data-scope='context-menu'], [data-scope='hover-card'], [data-scope='menu'], [data-scope='menubar'], [data-scope='popconfirm'], [data-scope='popover'], [data-scope='tour'], [data-scope='tooltip'])[data-part='arrow'] {
12
17
  position: absolute;
13
18
  inline-size: var(--xh-_overlay-arrow-size);
14
19
  block-size: var(--xh-_overlay-arrow-size);
@@ -16,7 +21,7 @@
16
21
  }
17
22
 
18
23
  /* 浮层落在锚点下方:箭头贴 content 上缘,摘掉埋进 content 的下、右两条边 */
19
- [data-part='arrow'][data-placement^='bottom'] {
24
+ :where([data-scope='context-menu'], [data-scope='hover-card'], [data-scope='menu'], [data-scope='menubar'], [data-scope='popconfirm'], [data-scope='popover'], [data-scope='tour'], [data-scope='tooltip'])[data-part='arrow'][data-placement^='bottom'] {
20
25
  top: calc(var(--xh-_overlay-arrow-size) / -2);
21
26
  inset-inline-start: calc(var(--xh-_overlay-arrow-x) - var(--xh-_overlay-arrow-size) / 2);
22
27
  border-right: 0;
@@ -24,7 +29,7 @@
24
29
  }
25
30
 
26
31
  /* 浮层落在锚点上方:箭头贴 content 下缘,摘掉上、左两条边 */
27
- [data-part='arrow'][data-placement^='top'] {
32
+ :where([data-scope='context-menu'], [data-scope='hover-card'], [data-scope='menu'], [data-scope='menubar'], [data-scope='popconfirm'], [data-scope='popover'], [data-scope='tour'], [data-scope='tooltip'])[data-part='arrow'][data-placement^='top'] {
28
33
  bottom: calc(var(--xh-_overlay-arrow-size) / -2);
29
34
  inset-inline-start: calc(var(--xh-_overlay-arrow-x) - var(--xh-_overlay-arrow-size) / 2);
30
35
  border-top: 0;
@@ -32,7 +37,7 @@
32
37
  }
33
38
 
34
39
  /* 浮层落在锚点右侧:箭头贴 content 左缘,摘掉上、右两条边 */
35
- [data-part='arrow'][data-placement^='right'] {
40
+ :where([data-scope='context-menu'], [data-scope='hover-card'], [data-scope='menu'], [data-scope='menubar'], [data-scope='popconfirm'], [data-scope='popover'], [data-scope='tour'], [data-scope='tooltip'])[data-part='arrow'][data-placement^='right'] {
36
41
  top: calc(var(--xh-_overlay-arrow-y) - var(--xh-_overlay-arrow-size) / 2);
37
42
  /* stylelint-disable-next-line property-disallowed-list -- 旋转是物理的,贴边跟着物理走 */
38
43
  left: calc(var(--xh-_overlay-arrow-size) / -2);
@@ -41,7 +46,7 @@
41
46
  }
42
47
 
43
48
  /* 浮层落在锚点左侧:箭头贴 content 右缘,摘掉下、左两条边 */
44
- [data-part='arrow'][data-placement^='left'] {
49
+ :where([data-scope='context-menu'], [data-scope='hover-card'], [data-scope='menu'], [data-scope='menubar'], [data-scope='popconfirm'], [data-scope='popover'], [data-scope='tour'], [data-scope='tooltip'])[data-part='arrow'][data-placement^='left'] {
45
50
  top: calc(var(--xh-_overlay-arrow-y) - var(--xh-_overlay-arrow-size) / 2);
46
51
  /* stylelint-disable-next-line property-disallowed-list -- 旋转是物理的,贴边跟着物理走 */
47
52
  right: calc(var(--xh-_overlay-arrow-size) / -2);