@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/separator.css CHANGED
@@ -1,12 +1,29 @@
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
+ /* 定义 separator 样式。 */
7
+
1
8
  @layer xihan.components {
2
9
  /* 皮肤在场的标记:开发模式下按 scope 探一次,取不到就说明这份皮肤没被引入。 */
3
10
  [data-scope='separator'] {
4
11
  --xh-separator-skin: 1;
5
12
  }
6
13
 
14
+ /*
15
+ * 线的颜色与线型都先收进两个私有槽,再由 root(只有它一个时)与 line(有分节文字时)
16
+ * 各自取用:换档只改槽,画在哪个节点上互不影响。
17
+ */
7
18
  [data-scope='separator'][data-part='root'] {
19
+ --xh-_separator-color: var(--xh-separator-color, var(--xh-material-frosted-separator));
20
+ --xh-_separator-dash: var(--xh-separator-dash-length, var(--xh-space-1_5));
21
+ --xh-_separator-dash-gap: var(--xh-separator-dash-gap, var(--xh-space-1_5));
22
+ --xh-_separator-paint: var(--xh-_separator-color);
23
+
8
24
  border: 0;
9
- background: var(--xh-separator-color, var(--xh-border-default));
25
+ border-radius: var(--xh-separator-radius, var(--xh-shape-pill));
26
+ background: var(--xh-_separator-paint);
10
27
  }
11
28
 
12
29
  [data-scope='separator'][data-part='root'][data-orientation='horizontal'] {
@@ -19,4 +36,87 @@
19
36
  inline-size: var(--xh-separator-thickness, var(--xh-stroke-thin));
20
37
  block-size: 100%;
21
38
  }
39
+
40
+ /* —— 形态 ——
41
+ 三档只换线的深浅,缺省档写在上面的基础规则里。使用者槽排在档值前面,
42
+ 写了 --xh-separator-color 的那一条仍然压过档值 */
43
+ [data-scope='separator'][data-part='root'][data-variant='subtle'] {
44
+ --xh-_separator-color: var(--xh-separator-color, var(--xh-material-soft-separator));
45
+ }
46
+
47
+ [data-scope='separator'][data-part='root'][data-variant='strong'] {
48
+ --xh-_separator-color: var(--xh-separator-color, var(--xh-border-strong));
49
+ }
50
+
51
+ /* —— 虚线 ——
52
+ 实线段与空白段交替铺;方向由 data-orientation 选,表达式只写这两条 */
53
+ [data-scope='separator'][data-part='root'][data-dashed][data-orientation='horizontal'] {
54
+ --xh-_separator-paint: repeating-linear-gradient(
55
+ to right,
56
+ var(--xh-_separator-color) 0 var(--xh-_separator-dash),
57
+ transparent var(--xh-_separator-dash) calc(var(--xh-_separator-dash) + var(--xh-_separator-dash-gap))
58
+ );
59
+ }
60
+
61
+ [data-scope='separator'][data-part='root'][data-dashed][data-orientation='vertical'] {
62
+ --xh-_separator-paint: repeating-linear-gradient(
63
+ to bottom,
64
+ var(--xh-_separator-color) 0 var(--xh-_separator-dash),
65
+ transparent var(--xh-_separator-dash) calc(var(--xh-_separator-dash) + var(--xh-_separator-dash-gap))
66
+ );
67
+ }
68
+
69
+ /* —— 带分节文字的三段形态 ——
70
+ 渲染了 content 之后 root 改当容器:自己不再画线,线交给两条 line。
71
+ 形态由部件在不在决定,没有开关 */
72
+ [data-scope='separator'][data-part='root']:has([data-part='content']) {
73
+ display: flex;
74
+ align-items: center;
75
+ inline-size: 100%;
76
+ block-size: auto;
77
+ gap: var(--xh-separator-gap, var(--xh-space-3));
78
+ background: none;
79
+ }
80
+
81
+ [data-scope='separator'][data-part='root'][data-orientation='vertical']:has([data-part='content']) {
82
+ flex-direction: column;
83
+ inline-size: auto;
84
+ block-size: 100%;
85
+ }
86
+
87
+ /* 两条线等分剩下的地方;粗细与颜色跟 root 单节点时同源 */
88
+ [data-scope='separator'][data-part='line'] {
89
+ flex: 1 1 0;
90
+ border-radius: var(--xh-separator-radius, var(--xh-shape-pill));
91
+ background: var(--xh-_separator-paint);
92
+ }
93
+
94
+ [data-scope='separator'][data-part='line'][data-orientation='horizontal'] {
95
+ block-size: var(--xh-separator-thickness, var(--xh-stroke-thin));
96
+ }
97
+
98
+ [data-scope='separator'][data-part='line'][data-orientation='vertical'] {
99
+ inline-size: var(--xh-separator-thickness, var(--xh-stroke-thin));
100
+ }
101
+
102
+ /* 分节文字:不参与等分,也不折行 */
103
+ [data-scope='separator'][data-part='content'] {
104
+ flex: none;
105
+ color: var(--xh-separator-content-fg, var(--xh-fg-muted));
106
+ font-size: var(--xh-separator-content-font-size, var(--xh-text-secondary-size));
107
+ line-height: var(--xh-leading-normal);
108
+ white-space: nowrap;
109
+ }
110
+
111
+ /* 文字靠边:靠哪边就把那一侧的线收成一小截,另一侧照旧等分 */
112
+ [data-scope='separator'][data-part='root'][data-align='start'] > [data-part='line']:first-child,
113
+ [data-scope='separator'][data-part='root'][data-align='end'] > [data-part='line']:last-child {
114
+ flex: 0 0 var(--xh-separator-align-length, var(--xh-space-6));
115
+ }
116
+
117
+ /* 声明过任何 display 就盖掉了 UA 的 [hidden]{display:none},收起态得自己还回去。
118
+ 写在文件末尾:兜底必须排在该部件所有 display 声明之后 */
119
+ [data-scope='separator'][data-part='root'][hidden] {
120
+ display: none;
121
+ }
22
122
  }
package/css/side-nav.css CHANGED
@@ -1,30 +1,13 @@
1
- @layer xihan.motion {
2
- /* 动画名的查找只认「文档里有没有这个名字」:引用别处文件里的名字,那份文件不一定在场,
3
- 动画会静默地整个不跑。每份皮肤都能单独引入,所以它用到的关键帧都写在自己身上。 */
4
- @keyframes xh-pop-in {
5
- from {
6
- opacity: 0;
7
- scale: var(--xh-motion-scale-enter);
8
- }
9
-
10
- to {
11
- opacity: 1;
12
- scale: 1;
13
- }
14
- }
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
+ */
15
5
 
16
- @keyframes xh-pop-out {
17
- from {
18
- opacity: 1;
19
- scale: 1;
20
- }
6
+ /* 定义 side nav 样式。 */
21
7
 
22
- to {
23
- opacity: 0;
24
- scale: var(--xh-motion-scale-enter);
25
- }
26
- }
27
- }
8
+ /* 共享关键帧由 family/motion.css 提供,行走 Collection Item 家族;本皮肤 @import 它们,单独引入仍成立。 */
9
+ @import '../family/collection-item.css';
10
+ @import '../family/motion.css';
28
11
 
29
12
  @layer xihan.components {
30
13
  /* 皮肤在场的标记:开发模式下按 scope 探一次,取不到就说明这份皮肤没被引入。 */
@@ -32,10 +15,41 @@
32
15
  --xh-side-nav-skin: 1;
33
16
  }
34
17
 
35
- [data-scope='side-nav'][data-part='root'] {
36
- /* 作者塞进指示符槽的图标跟着字号走,与皮肤画的兜底字形同一把尺 */
37
- --xh-icon-size: var(--xh-side-nav-icon-size, var(--xh-glyph-size-text));
18
+ /* 私有槽同时声明在根与定位层上:折叠态的弹出面板被搬到 portal 落点,
19
+ 不是根的后代,继承不过去。面板里的行与栏内那些消费的是同一批槽 */
20
+ [data-scope='side-nav']:is([data-part='root'], [data-part='positioner']) {
21
+ /* 行外的字形按档取尺,缺省 md,随 data-size 换档并同样声明在定位层上(弹出面板里的行也拿得到);
22
+ 行内的由家族随 data-xh-collection-size 下发(§6.5)。这支只管作者放进行里的图标:
23
+ 侧栏自绘的状态字形(分支行尾的展开方向 chevron)是指示符,branch-indicator 在自己身上
24
+ 把 --xh-icon-size 改接到 --xh-control-indicator-* 一族的盒尺 */
25
+ --xh-icon-size: var(--xh-side-nav-icon-size, var(--xh-glyph-size-md));
26
+
27
+ /* 尺寸档只换这三个私有槽,行从这两处继承它们,换档不必给每个部件各写一条选择器 */
28
+ --xh-_side-nav-row-h: var(--xh-control-h-md);
29
+ --xh-_side-nav-row-px: var(--xh-control-px-md);
30
+ --xh-_side-nav-row-gap: var(--xh-control-gap-md);
31
+ --xh-_side-nav-row-font-size: var(--xh-control-font-md);
32
+ }
33
+
34
+ /* —— 尺寸 —— */
35
+ /* 缺省档写在上面那条里 */
36
+ [data-scope='side-nav']:is([data-part='root'], [data-part='positioner'])[data-size='sm'] {
37
+ --xh-icon-size: var(--xh-side-nav-icon-size, var(--xh-glyph-size-sm));
38
+ --xh-_side-nav-row-h: var(--xh-control-h-sm);
39
+ --xh-_side-nav-row-px: var(--xh-control-px-sm);
40
+ --xh-_side-nav-row-gap: var(--xh-control-gap-sm);
41
+ --xh-_side-nav-row-font-size: var(--xh-control-font-sm);
42
+ }
43
+
44
+ [data-scope='side-nav']:is([data-part='root'], [data-part='positioner'])[data-size='lg'] {
45
+ --xh-icon-size: var(--xh-side-nav-icon-size, var(--xh-glyph-size-lg));
46
+ --xh-_side-nav-row-h: var(--xh-control-h-lg);
47
+ --xh-_side-nav-row-px: var(--xh-control-px-lg);
48
+ --xh-_side-nav-row-gap: var(--xh-control-gap-lg);
49
+ --xh-_side-nav-row-font-size: var(--xh-control-font-lg);
50
+ }
38
51
 
52
+ [data-scope='side-nav'][data-part='root'] {
39
53
  inline-size: var(--xh-side-nav-w, 240px);
40
54
  display: flex;
41
55
  flex-direction: column;
@@ -77,8 +91,9 @@
77
91
 
78
92
  [data-scope='side-nav'][data-part='group-label'] {
79
93
  padding-block: var(--xh-side-nav-group-label-py, var(--xh-space-1));
80
- padding-inline: var(--xh-side-nav-group-label-px, var(--xh-control-px-md));
94
+ padding-inline: var(--xh-side-nav-group-label-px, var(--xh-_side-nav-row-px));
81
95
  font-size: var(--xh-text-caption-size);
96
+ font-weight: var(--xh-text-label-weight);
82
97
  color: var(--xh-fg-subtle);
83
98
  user-select: none;
84
99
  }
@@ -102,55 +117,67 @@
102
117
  list-style: none;
103
118
  }
104
119
 
105
- /* —— 行:分支按钮与链接同一副长相 —— */
120
+ /* —— 行:分支按钮与链接同一副长相 ——
121
+ 两种行都走 Collection Item 的 page 语境(页内持久集合,§7.3):悬停 / 高亮 / 按下面(白底承载 hover 100 →
122
+ pressed 200,只换面不缩放)、当前页(品牌淡底 + 淡底前景 + 起始侧 2px 指示条,current+hover 20% /
123
+ +pressed 28%)、展开路径(与 hover 同档的中性面,不用品牌色、不加粗)与禁用面都由家族按 data-current /
124
+ data-in-path / aria-disabled 给出。这里只把公开槽映射到桥接槽。
125
+ 布局保持 flex 而不用家族网格:一行里可以并排作者自己的图标与徽标,间距统一由行的 gap 给,
126
+ 家族按槽下发的外边距(--xh-collection-gap)归零;行高由 min-block-size 撑起,家族的块向内衬归零 */
106
127
  [data-scope='side-nav'][data-part='branch-trigger'],
107
128
  [data-scope='side-nav'][data-part='link'] {
129
+ --xh-collection-block-padding: 0;
130
+ --xh-collection-inline-padding: var(--xh-side-nav-link-px, var(--xh-_side-nav-row-px));
131
+ --xh-collection-gap: 0;
132
+ --xh-collection-font-size: var(--xh-side-nav-link-font-size, var(--xh-_side-nav-row-font-size));
133
+ --xh-collection-radius: var(--xh-side-nav-link-radius, var(--xh-shape-control));
134
+ /* 作者的图标尺槽经桥接槽下发到行,家族缺省按 data-xh-collection-size 取档 */
135
+ --xh-collection-glyph-size: var(--xh-side-nav-icon-size, var(--xh-_collection-glyph-size));
136
+ --xh-collection-fg-rest: var(--xh-side-nav-row-fg, currentColor);
137
+ --xh-collection-fg-hover: var(--xh-side-nav-row-fg, currentColor);
138
+ --xh-collection-fg-keyboard-highlight: var(--xh-side-nav-row-fg, currentColor);
139
+ --xh-collection-fg-pressed: var(--xh-side-nav-row-fg, currentColor);
140
+ --xh-collection-bg-hover: var(--xh-side-nav-row-bg-hover, var(--xh-bg-subtle));
141
+ --xh-collection-bg-keyboard-highlight: var(--xh-side-nav-row-bg-hover, var(--xh-bg-subtle));
142
+ --xh-collection-bg-pressed: var(--xh-side-nav-row-bg-pressed, var(--xh-bg-subtle-hover));
143
+ /* 当前页:公开槽名不变,缺省前景由品牌深字改为淡底前景,字重保持 medium;2px 指示条取品牌色 */
144
+ --xh-collection-bg-current: var(--xh-side-nav-row-bg-active, var(--xh-bg-brand-subtle));
145
+ --xh-collection-fg-current: var(--xh-side-nav-row-fg-active, var(--xh-fg-on-brand-subtle));
146
+ --xh-collection-fg-current-hover: var(--xh-side-nav-row-fg-active, var(--xh-fg-on-brand-subtle));
147
+ --xh-collection-fg-current-highlight: var(--xh-side-nav-row-fg-active, var(--xh-fg-on-brand-subtle));
148
+ --xh-collection-fg-current-pressed: var(--xh-side-nav-row-fg-active, var(--xh-fg-on-brand-subtle));
149
+ --xh-collection-font-weight-current: var(--xh-side-nav-row-font-weight-active, var(--xh-font-weight-medium));
150
+ --xh-collection-font-weight-current-hover: var(--xh-side-nav-row-font-weight-active, var(--xh-font-weight-medium));
151
+ --xh-collection-font-weight-current-highlight: var(--xh-side-nav-row-font-weight-active, var(--xh-font-weight-medium));
152
+ --xh-collection-font-weight-current-pressed: var(--xh-side-nav-row-font-weight-active, var(--xh-font-weight-medium));
153
+ --xh-collection-indicator-fg-current: var(--xh-side-nav-indicator-color, var(--xh-fg-brand));
154
+ --xh-collection-indicator-fg-current-hover: var(--xh-side-nav-indicator-color, var(--xh-fg-brand));
155
+ --xh-collection-indicator-fg-current-highlight: var(--xh-side-nav-indicator-color, var(--xh-fg-brand));
156
+ --xh-collection-indicator-fg-current-pressed: var(--xh-side-nav-indicator-color, var(--xh-fg-brand));
157
+ /* 展开路径:中性面,字色缺省由品牌色改回行的常态色 */
158
+ --xh-collection-bg-open-path: var(--xh-side-nav-row-bg-in-path, var(--xh-bg-subtle));
159
+ --xh-collection-fg-open-path: var(--xh-side-nav-row-fg-in-path, var(--xh-side-nav-row-fg, currentColor));
160
+ /* data-highlighted 跟的是连接层记的焦点行(指针点选也会落焦):只换面,焦点环在 :focus-visible 下再接回 */
161
+ --xh-collection-outline-keyboard-highlight: transparent;
162
+ --xh-collection-outline-current-highlight: transparent;
163
+
108
164
  display: flex;
109
165
  align-items: center;
110
- gap: var(--xh-side-nav-link-gap, var(--xh-control-gap-md));
166
+ gap: var(--xh-side-nav-link-gap, var(--xh-_side-nav-row-gap));
111
167
  inline-size: 100%;
112
- min-block-size: var(--xh-control-h-md);
113
- padding-inline: var(--xh-side-nav-link-px, var(--xh-control-px-md));
168
+ min-block-size: var(--xh-side-nav-link-h, var(--xh-_side-nav-row-h));
114
169
  border: none;
115
- border-radius: var(--xh-side-nav-link-radius, var(--xh-shape-control));
116
- background: none;
117
- color: inherit;
118
- font-size: var(--xh-text-body-size);
119
170
  text-align: start;
120
171
  text-decoration: none;
121
- cursor: pointer;
122
- }
123
-
124
- /* 悬停与键盘锚点共用中性灰轻档:锚点只认连接层打的 data-highlighted,不读 :focus */
125
- [data-scope='side-nav'][data-part='branch-trigger']:not([data-disabled]):is(:hover, [data-highlighted]),
126
- [data-scope='side-nav'][data-part='link']:not([data-disabled]):is(:hover, [data-highlighted]) {
127
- background: var(--xh-side-nav-row-bg-hover, var(--xh-bg-subtle));
128
- }
129
-
130
- [data-scope='side-nav'][data-part='branch-trigger']:focus-visible,
131
- [data-scope='side-nav'][data-part='link']:focus-visible {
132
- outline: var(--xh-ring-width) solid var(--xh-ring-focus);
133
- outline-offset: var(--xh-ring-offset);
134
- }
135
-
136
- /* 选中的那条:品牌淡底 + 强调字。
137
- 守卫与轻档那条同特指度,写在其后才压得住——键盘走到当前页那一行时底色仍是品牌淡底 */
138
- [data-scope='side-nav'][data-part='link']:not([data-disabled])[data-current] {
139
- background: var(--xh-bg-brand-subtle);
140
- /* 淡底上的字走 strong 档:fg-brand(600)压在 brand-subtle(100)上只有 4.21 */
141
- color: var(--xh-fg-brand-strong);
142
- font-weight: var(--xh-font-weight-medium);
143
172
  }
144
173
 
145
- /* 选中项的祖先枝:只染字色,一路指到当前页 */
146
- [data-scope='side-nav'][data-part='branch-trigger'][data-in-path] {
147
- color: var(--xh-fg-brand);
148
- }
174
+ /* 键盘焦点出现时环才接回并立即到位,不压在背景过渡的中间帧上 */
175
+ [data-scope='side-nav'][data-part='branch-trigger']:focus-visible:not(:hover),
176
+ [data-scope='side-nav'][data-part='link']:focus-visible:not(:hover) {
177
+ --xh-collection-outline-keyboard-highlight: var(--xh-ring-focus);
178
+ --xh-collection-outline-current-highlight: var(--xh-ring-focus);
149
179
 
150
- [data-scope='side-nav'][data-part='branch-trigger'][data-disabled],
151
- [data-scope='side-nav'][data-part='link'][data-disabled] {
152
- color: var(--xh-fg-disabled);
153
- cursor: not-allowed;
180
+ transition: none;
154
181
  }
155
182
 
156
183
  [data-scope='side-nav'][data-part='branch-text'],
@@ -187,8 +214,9 @@
187
214
 
188
215
  [data-scope='side-nav'][data-part='root'][data-collapsed] [data-part='branch-trigger']:not([data-popout] *),
189
216
  [data-scope='side-nav'][data-part='root'][data-collapsed] [data-part='link']:not([data-popout] *) {
217
+ --xh-collection-inline-padding: 0;
218
+
190
219
  justify-content: center;
191
- padding-inline: 0;
192
220
  }
193
221
 
194
222
  /* 弹出面板的定位层:坐标由连接层写在行内样式上,这里只管层号与命中区。
@@ -198,9 +226,12 @@
198
226
  /* 落定那一侧的可用高度,由定位引擎经内联自定义属性写进来,面板继承它限高;
199
227
  引擎没算(尚未落位 / 无引擎 / 贴边归零)时不额外限高 */
200
228
  --xh-_side-nav-available-h: 100vh;
229
+ /* 落定那一侧的可用宽度,同样由定位引擎经内联自定义属性写进来,行内轴据此夹取;
230
+ 引擎没算(尚未落位 / 无引擎 / 贴边归零)时退到视口宽 */
231
+ --xh-_side-nav-available-w: 100vw;
201
232
 
202
233
  position: fixed;
203
- z-index: var(--xh-side-nav-popout-layer, var(--xh-layer-popover));
234
+ z-index: var(--xh-side-nav-popout-layer, var(--xh-_layer, var(--xh-layer-popover)));
204
235
  pointer-events: auto;
205
236
  }
206
237
 
@@ -213,20 +244,25 @@
213
244
  面板自己不吃子层缩进(padding 整圈盖掉),面板内的嵌套子层照常缩进 */
214
245
  [data-scope='side-nav'][data-part='branch-content'][data-popout] {
215
246
  min-inline-size: var(--xh-side-nav-popout-min-w, var(--xh-overlay-menu-min-w));
216
- max-inline-size: var(--xh-side-nav-popout-max-w, var(--xh-overlay-max-w));
247
+ /* 静态档与落位后的可用宽度取小:窄视口下面板伸出去,最右侧的内容就点不到了 */
248
+ max-inline-size: min(var(--xh-side-nav-popout-max-w, var(--xh-overlay-max-w)), var(--xh-_side-nav-available-w));
217
249
  padding: var(--xh-side-nav-popout-p, var(--xh-space-1));
218
250
  border: var(--xh-stroke-thin) solid var(--xh-side-nav-popout-border, var(--xh-border-default));
219
- border-radius: var(--xh-side-nav-popout-radius, var(--xh-shape-surface));
251
+ border-radius: var(--xh-side-nav-popout-radius, var(--xh-shape-overlay));
220
252
  background: var(--xh-side-nav-popout-bg, var(--xh-bg-surface));
221
253
  box-shadow: var(--xh-side-nav-popout-shadow, var(--xh-elevation-floating));
222
254
 
223
- /* 子导航条目数没有上限,矮视口下不限高就整块伸出视口且滚不到 */
255
+ /* 子导航条目数没有上限,矮视口下不限高就整块伸出视口且滚不到。
256
+ 浮层滚动面:到底后不把滚动链穿透给页面(§6.6);细条由 reset 层给 */
224
257
  max-block-size: min(var(--xh-side-nav-popout-max-h, var(--xh-overlay-menu-max-h)), var(--xh-_side-nav-available-h));
225
258
  overflow-y: auto;
259
+ overscroll-behavior: contain;
226
260
  }
227
261
 
262
+ /* 在场那一档才提前备好合成层:属性随 data-state 一起消失,收起后不长期占着 */
228
263
  [data-scope='side-nav'][data-part='branch-content'][data-popout][data-state='open'] {
229
- animation: xh-pop-in var(--xh-motion-duration-enter) var(--xh-motion-ease-enter);
264
+ will-change: opacity, scale;
265
+ animation: xh-pop-in var(--xh-motion-duration-enter) var(--xh-motion-ease-enter-strong);
230
266
  }
231
267
 
232
268
  /* 退场:收起那一帧 hidden 由退场闸门押后,这里才播得出来。forwards 把末态钉住,
@@ -235,18 +271,30 @@
235
271
  animation: xh-pop-out var(--xh-motion-duration-exit) var(--xh-motion-ease-exit) forwards;
236
272
  }
237
273
 
274
+ /* 箭头是行尾的后缀:auto 外边距把它顶到行尾,家族按 suffix 槽下发的外边距已在行上归零。
275
+ 盒里的 chevron 是指示符(§6.5):盒按指示符档定尺(comfortable 16 / compact 14,与 Tree / TreeSelect
276
+ 的 branch-indicator 同款定尺盒),--xh-icon-size 在自己身上改接到盒的尺,兜底字形与作者塞进盒里的
277
+ XhIcon 读同一把尺、与盒同边长;不读家族按档下发到行的 --xh-icon-size——那支只管作者放进行里的
278
+ 图标,按图标档取的 20px 比指示符档大一圈。盒自己定尺而不随字形撑开:转 90° 时才不抖 */
238
279
  [data-scope='side-nav'][data-part='branch-indicator'] {
280
+ --xh-icon-size: var(--xh-side-nav-branch-indicator-size, var(--xh-control-indicator-size));
281
+
239
282
  margin-inline-start: auto;
240
283
  display: inline-flex;
241
284
  flex: none;
242
- transition: rotate var(--xh-motion-duration-micro) var(--xh-motion-ease-enter);
285
+ align-items: center;
286
+ justify-content: center;
287
+ inline-size: var(--xh-side-nav-branch-indicator-size, var(--xh-control-indicator-size));
288
+ block-size: var(--xh-side-nav-branch-indicator-size, var(--xh-control-indicator-size));
289
+ transition: rotate var(--xh-motion-duration-micro) var(--xh-motion-ease-enter-strong);
243
290
  }
244
291
 
245
292
  [data-scope='side-nav'][data-part='branch-indicator'][data-state='open'] {
246
293
  rotate: 90deg;
247
294
  }
248
295
 
249
- /* 没写内容就由皮肤画兜底字形;作者往部件里塞了自己的图形,这几条即不命中 */
296
+ /* 没写内容就由皮肤画兜底字形;作者往部件里塞了自己的图形,这几条即不命中。
297
+ 尺寸读部件自己改接过的 --xh-icon-size:chevron 与盒同边长(见上面那块) */
250
298
  [data-scope='side-nav'][data-part='branch-indicator']:empty::before {
251
299
  content: '';
252
300
  display: inline-block;
@@ -261,11 +309,21 @@
261
309
  /* 声明过任何 display 就盖掉了 UA 的 [hidden]{display:none},收起态得自己还回去。
262
310
  写在文件末尾:兜底必须排在该部件所有 display 声明之后 */
263
311
  [data-scope='side-nav'][data-part='root'][hidden],
312
+ [data-scope='side-nav'][data-part='list'][hidden],
264
313
  [data-scope='side-nav'][data-part='group'][hidden],
265
314
  [data-scope='side-nav'][data-part='branch'][hidden],
315
+ [data-scope='side-nav'][data-part='branch-trigger'][hidden],
266
316
  [data-scope='side-nav'][data-part='item'][hidden],
267
317
  [data-scope='side-nav'][data-part='link'][hidden],
268
318
  [data-scope='side-nav'][data-part='branch-indicator'][hidden] {
269
319
  display: none;
270
320
  }
321
+
322
+ @media print {
323
+ /* 打印:定位层与遮罩是交互期才存在的东西,落到纸上只会盖住底下的正文。
324
+ 收起写在这份皮肤里而不是 reset:reset 层排在组件层之前,组件层里任何一条 display 都压得住它。 */
325
+ [data-scope='side-nav'][data-part='positioner'] {
326
+ display: none;
327
+ }
328
+ }
271
329
  }
@@ -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
+ /* 定义 signature pad 样式。 */
7
+
8
+ @import '../family/action-control.css';
9
+
1
10
  @layer xihan.components {
2
11
  /* 皮肤在场的标记:开发模式下按 scope 探一次,取不到就说明这份皮肤没被引入。 */
3
12
  [data-scope='signature-pad'] {
@@ -10,37 +19,49 @@
10
19
  position: relative;
11
20
  display: flex;
12
21
  flex-direction: column;
13
- gap: var(--xh-signature-pad-gap, var(--xh-stack-gap-md));
22
+ /* 画布到清空按钮与状态句的距离;标签到画布另有一档,见 label */
23
+ gap: var(--xh-signature-pad-gap, var(--xh-space-2));
14
24
  }
15
25
 
26
+ /* 复合单字段的标签(§6.4):14 / 500 / fg-default,不随档;贴画布 space-1——
27
+ 容器的 gap 归画布之后的部件,标签在它之上补一段差值把距离收成目标值 */
16
28
  [data-scope='signature-pad'][data-part='label'] {
17
- color: var(--xh-signature-pad-label-fg, var(--xh-fg-muted));
29
+ margin-block-end: calc(
30
+ var(--xh-signature-pad-label-gap, var(--xh-space-1))
31
+ - var(--xh-signature-pad-gap, var(--xh-space-2))
32
+ );
33
+ color: var(--xh-signature-pad-label-fg, var(--xh-fg-default));
18
34
  font-size: var(--xh-signature-pad-label-font-size, var(--xh-text-label-size));
19
35
  font-weight: var(--xh-signature-pad-label-font-weight, var(--xh-text-label-weight));
20
- line-height: var(--xh-leading-none);
21
36
  }
22
37
 
23
38
  [data-scope='signature-pad'][data-part='label'][data-disabled] {
24
- color: var(--xh-fg-subtle);
39
+ color: var(--xh-signature-pad-label-fg-disabled, var(--xh-fg-subtle));
25
40
  }
26
41
 
27
42
  /* 画布是块状的写字区:宽度铺满外层,高度由宽高比决定。
28
43
  控件行高那把尺量的是一行控件,一块要写字的面积用不上它。
29
- touch-action 由连接层内联写死,触摸落笔才不会被页面滚动抢走。 */
44
+ touch-action 由连接层内联写死,触摸落笔才不会被页面滚动抢走。
45
+ 外壳按字段规则自绘(§8.3 登记的画布型字段例外:字段家族配方钉死控件行高,画布按宽高比撑高吃不下它):
46
+ 静息透明底 + border-control 描边 + control 圆角 + 无影 */
30
47
  [data-scope='signature-pad'][data-part='control'] {
31
48
  display: block;
32
49
  inline-size: 100%;
33
50
  aspect-ratio: var(--xh-signature-pad-aspect-ratio, 5 / 2);
34
51
  border: var(--xh-stroke-thin) solid var(--xh-signature-pad-border, var(--xh-border-control));
35
- border-radius: var(--xh-signature-pad-radius, var(--xh-shape-surface));
36
- background: var(--xh-signature-pad-bg, var(--xh-bg-surface));
52
+ border-radius: var(--xh-signature-pad-radius, var(--xh-shape-control));
53
+ background: var(--xh-signature-pad-bg, transparent);
37
54
  cursor: crosshair;
38
55
  /* 一划就会把画布连同旁边的文字一起刷成选中态 */
39
56
  user-select: none;
57
+ /* 落笔、校验不过与禁用三档各换一次描边或底色,换的过程要看得出来 */
58
+ transition:
59
+ border-color var(--xh-motion-duration-micro) var(--xh-motion-ease-enter),
60
+ background var(--xh-motion-duration-micro) var(--xh-motion-ease-enter);
40
61
  }
41
62
 
42
63
  [data-scope='signature-pad'][data-part='control'][data-invalid] {
43
- border-color: var(--xh-border-invalid);
64
+ border-color: var(--xh-signature-pad-control-border-invalid, var(--xh-border-invalid));
44
65
  }
45
66
 
46
67
  /* 落笔期间把描边压深一档。border-strong 是装饰梯度里的一档,比 border-control 更淡,
@@ -49,13 +70,17 @@
49
70
  border-color: var(--xh-signature-pad-border-drawing, var(--xh-border-control-hover));
50
71
  }
51
72
 
52
- /* 只读仍看得见签名,只是改不动:收掉手型,别暗示"在这儿能写" */
53
- [data-scope='signature-pad'][data-part='control'][data-readonly] {
73
+ /* 只读仍看得见签名,只是改不动:收掉手型,别暗示"在这儿能写"
74
+ 面按字段只读规则只换到淡底,描边不动(§7.2 第 9 条) */
75
+ [data-scope='signature-pad'][data-part='control'][data-readonly]:not([data-disabled]) {
76
+ background: var(--xh-signature-pad-bg-readonly, var(--xh-bg-subtle));
54
77
  cursor: default;
55
78
  }
56
79
 
80
+ /* 字段禁用面(§7.2 第 9 条):描边退到 border-default、底换淡底 */
57
81
  [data-scope='signature-pad'][data-part='control'][data-disabled] {
58
- background: var(--xh-signature-pad-bg-disabled, var(--xh-bg-muted));
82
+ border-color: var(--xh-signature-pad-border-disabled, var(--xh-border-default));
83
+ background: var(--xh-signature-pad-bg-disabled, var(--xh-bg-subtle));
59
84
  cursor: not-allowed;
60
85
  }
61
86
 
@@ -69,64 +94,59 @@
69
94
 
70
95
  /* 笔迹是一条填充路径(每一笔是它的一条子路径),不是描边:
71
96
  粗细要随压感变,而 stroke-width 全线只有一个值 */
72
- [data-scope='signature-pad'][data-part='segment'] {
97
+ [data-scope='signature-pad'][data-part='path'] {
73
98
  fill: var(--xh-signature-pad-ink, var(--xh-fg-default));
74
99
  stroke: none;
75
100
  }
76
101
 
102
+ /*
103
+ * 清空按钮是画布旁的独立文字按钮(§9.1):盒型、sm 档几何、outline 四态面、0.97 按压与粗指针命中区由家族配方
104
+ * 按连接层投影的 data-xh-action-variant / -size 给出(缺省 outline,白底承载阶梯 100 → 200)。这里只把公开槽
105
+ * 桥接到矩阵之前(使用者槽 → 形态矩阵 → 家族缺省)与几何槽映射,矩阵各态无影(§8.3 淡底与阴影互斥)。
106
+ */
77
107
  [data-scope='signature-pad'][data-part='clear-trigger'] {
78
- display: inline-flex;
108
+ --xh-action-bg-rest: var(--xh-signature-pad-clear-bg, var(--xh-_action-variant-bg-rest));
109
+ --xh-action-bg-hover: var(--xh-signature-pad-clear-bg-hover, var(--xh-_action-variant-bg-hover));
110
+ --xh-action-bg-pressed: var(--xh-signature-pad-clear-bg-active, var(--xh-_action-variant-bg-pressed));
111
+ --xh-action-bg-focus-visible: var(--xh-signature-pad-clear-bg, var(--xh-_action-variant-bg-focus-visible));
112
+ --xh-action-bg-disabled: var(--xh-signature-pad-clear-bg-disabled, var(--xh-_action-variant-bg-disabled));
113
+ --xh-action-fg-rest: var(--xh-signature-pad-clear-fg, var(--xh-_action-variant-fg-rest));
114
+ --xh-action-fg-hover: var(--xh-signature-pad-clear-fg, var(--xh-_action-variant-fg-hover));
115
+ --xh-action-fg-pressed: var(--xh-signature-pad-clear-fg, var(--xh-_action-variant-fg-pressed));
116
+ --xh-action-fg-focus-visible: var(--xh-signature-pad-clear-fg, var(--xh-_action-variant-fg-focus-visible));
117
+ --xh-action-border-rest: var(--xh-signature-pad-clear-border, var(--xh-_action-variant-border-rest));
118
+ --xh-action-border-hover: var(--xh-signature-pad-clear-border-hover, var(--xh-_action-variant-border-hover));
119
+ --xh-action-border-pressed: var(--xh-signature-pad-clear-border-hover, var(--xh-_action-variant-border-pressed));
120
+ --xh-action-border-focus-visible: var(--xh-signature-pad-clear-border, var(--xh-_action-variant-border-focus-visible));
121
+ /* 矩阵各态无影:悬停不再抬影(raised 只给 Button),使用者槽仍可自行加 */
122
+ --xh-action-shadow-hover: var(--xh-signature-pad-clear-shadow-hover, none);
123
+ --xh-action-radius: var(--xh-signature-pad-clear-radius, var(--xh-shape-control));
124
+ --xh-action-visual-size: var(--xh-signature-pad-clear-h, var(--xh-_action-profile-visual-size));
125
+ --xh-action-padding-inline: var(--xh-signature-pad-clear-px, var(--xh-_action-profile-padding-inline));
126
+ --xh-action-gap: var(--xh-signature-pad-clear-gap, var(--xh-_action-profile-gap));
127
+ --xh-action-font-size: var(--xh-signature-pad-clear-font-size, var(--xh-_action-profile-font-size));
128
+ /* 作者塞进来的图标随档取字形尺(sm = 16px) */
129
+ --xh-icon-size: var(--xh-signature-pad-clear-icon-size, var(--xh-_action-profile-glyph-size));
130
+
131
+ /* 竖排容器里不铺满一行:按钮只占自己的宽 */
79
132
  align-self: flex-start;
80
- align-items: center;
81
- justify-content: center;
82
- gap: var(--xh-signature-pad-clear-gap, var(--xh-control-gap-sm));
83
- block-size: var(--xh-signature-pad-clear-h, var(--xh-control-h-sm));
84
- padding-inline: var(--xh-signature-pad-clear-px, var(--xh-control-px-sm));
85
- border: var(--xh-stroke-thin) solid var(--xh-signature-pad-clear-border, var(--xh-border-control));
86
- border-radius: var(--xh-signature-pad-clear-radius, var(--xh-shape-control));
87
- background: var(--xh-signature-pad-clear-bg, var(--xh-bg-surface));
88
- color: var(--xh-signature-pad-clear-fg, var(--xh-fg-default));
89
- font-size: var(--xh-text-label-size);
90
- line-height: var(--xh-leading-none);
91
- cursor: pointer;
92
- transition:
93
- background var(--xh-motion-duration-micro) var(--xh-motion-ease-enter),
94
- scale var(--xh-motion-duration-micro) var(--xh-motion-ease-enter);
95
- }
96
-
97
- [data-scope='signature-pad'][data-part='clear-trigger']:hover {
98
- background: var(--xh-signature-pad-clear-bg-hover, var(--xh-bg-subtle-hover));
99
- }
100
-
101
- /* 按下:换到按压档底色并轻微下压,松手弹回;禁用钮不压 */
102
- [data-scope='signature-pad'][data-part='clear-trigger']:not(:disabled):active {
103
- background: var(--xh-signature-pad-clear-bg-active, var(--xh-bg-subtle-active));
104
- scale: var(--xh-motion-scale-press);
105
133
  }
106
134
 
107
- [data-scope='signature-pad'][data-part='clear-trigger']:focus-visible {
108
- outline: var(--xh-ring-width) solid var(--xh-ring-focus);
109
- outline-offset: var(--xh-ring-offset);
110
- }
111
-
112
- /* 空画布时按钮照常可按(收起它会让焦点掉回 body),只把它压淡一档 */
135
+ /* 空画布时按钮照常可按(收起它会让焦点掉回 body),只把静息前景压淡一档;悬停与按下仍回到默认前景 */
113
136
  [data-scope='signature-pad'][data-part='clear-trigger'][data-empty] {
114
- color: var(--xh-fg-muted);
137
+ --xh-action-fg-rest: var(--xh-signature-pad-clear-fg-empty, var(--xh-fg-muted));
115
138
  }
116
139
 
117
- /* 单体原生控件走 :disabled;集合条目那套 [data-disabled] 在这里命不中。
118
- 禁用只换前景色,不再叠 opacity——两样一起上会把文字压到看不见 */
119
- [data-scope='signature-pad'][data-part='clear-trigger']:disabled {
120
- background: var(--xh-signature-pad-clear-bg-disabled, var(--xh-bg-muted));
121
- color: var(--xh-fg-disabled);
122
- cursor: not-allowed;
140
+ /* 面是实心的,环色与面同族,画在面里就看不出来;环改取面自己的前景色 */
141
+ [data-scope='signature-pad'][data-part='clear-trigger'][data-xh-action-variant='solid']:focus-visible {
142
+ --xh-action-ring-color-focus-visible: currentColor;
123
143
  }
124
144
 
125
- /* 签没签的那句话。读屏靠它播报,看得见的人也用得上,因此不做视觉隐藏 */
145
+ /* 签没签的那句话是说明角色(§6.4):13 / fg-muted / leading-normal。读屏靠它播报,看得见的人也用得上,因此不做视觉隐藏 */
126
146
  [data-scope='signature-pad'][data-part='status'] {
127
147
  color: var(--xh-signature-pad-status-fg, var(--xh-fg-muted));
128
- font-size: var(--xh-signature-pad-status-font-size, var(--xh-text-label-size));
129
- line-height: var(--xh-leading-none);
148
+ font-size: var(--xh-signature-pad-status-font-size, var(--xh-text-secondary-size));
149
+ line-height: var(--xh-leading-normal);
130
150
  }
131
151
 
132
152
  /* 表单影子的视觉隐藏(绝对定位 + 1px + clip-path)连接层内联给全了,这里不重复也不覆盖,