@xihan-ui/styles 1.0.0-alpha.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 (114) hide show
  1. package/CHANGELOG.md +44 -0
  2. package/LICENSE +21 -0
  3. package/README.md +27 -0
  4. package/css/accordion.css +108 -0
  5. package/css/affix.css +27 -0
  6. package/css/alert.css +108 -0
  7. package/css/anchor.css +137 -0
  8. package/css/avatar-group.css +82 -0
  9. package/css/avatar.css +55 -0
  10. package/css/back-top.css +61 -0
  11. package/css/badge.css +50 -0
  12. package/css/breadcrumb.css +127 -0
  13. package/css/button-group.css +131 -0
  14. package/css/button.css +98 -0
  15. package/css/calendar.css +219 -0
  16. package/css/card.css +116 -0
  17. package/css/carousel.css +193 -0
  18. package/css/cascader.css +397 -0
  19. package/css/checkbox-group.css +185 -0
  20. package/css/checkbox.css +91 -0
  21. package/css/clipboard.css +133 -0
  22. package/css/code-block.css +81 -0
  23. package/css/collapsible.css +63 -0
  24. package/css/color-picker.css +424 -0
  25. package/css/combobox.css +433 -0
  26. package/css/composer.css +127 -0
  27. package/css/context-menu.css +263 -0
  28. package/css/countdown.css +21 -0
  29. package/css/date-field.css +200 -0
  30. package/css/date-picker.css +231 -0
  31. package/css/descriptions.css +200 -0
  32. package/css/dialog.css +127 -0
  33. package/css/drawer.css +372 -0
  34. package/css/dynamic-input.css +157 -0
  35. package/css/editable.css +249 -0
  36. package/css/ellipsis.css +41 -0
  37. package/css/empty-state.css +78 -0
  38. package/css/field.css +65 -0
  39. package/css/file-upload.css +298 -0
  40. package/css/flex.css +95 -0
  41. package/css/float-button.css +121 -0
  42. package/css/form.css +185 -0
  43. package/css/gradient-text.css +62 -0
  44. package/css/grid.css +428 -0
  45. package/css/highlight.css +21 -0
  46. package/css/hover-card.css +146 -0
  47. package/css/icon-wrapper.css +64 -0
  48. package/css/icon.css +54 -0
  49. package/css/image.css +45 -0
  50. package/css/infinite-scroll.css +22 -0
  51. package/css/layers.css +2 -0
  52. package/css/layout.css +169 -0
  53. package/css/list.css +117 -0
  54. package/css/listbox.css +174 -0
  55. package/css/loading-bar.css +66 -0
  56. package/css/log.css +66 -0
  57. package/css/marquee.css +182 -0
  58. package/css/mention.css +222 -0
  59. package/css/menu.css +144 -0
  60. package/css/menubar.css +271 -0
  61. package/css/motion.css +58 -0
  62. package/css/navigation-menu.css +270 -0
  63. package/css/number-animation.css +32 -0
  64. package/css/number-field.css +219 -0
  65. package/css/page-header.css +85 -0
  66. package/css/pagination.css +148 -0
  67. package/css/pin-input.css +157 -0
  68. package/css/popconfirm.css +150 -0
  69. package/css/popover.css +150 -0
  70. package/css/popselect.css +207 -0
  71. package/css/progress.css +37 -0
  72. package/css/qr-code.css +50 -0
  73. package/css/radio-group.css +101 -0
  74. package/css/rating.css +141 -0
  75. package/css/reset.css +22 -0
  76. package/css/result.css +104 -0
  77. package/css/scroll-area.css +176 -0
  78. package/css/select.css +264 -0
  79. package/css/separator.css +17 -0
  80. package/css/skeleton.css +78 -0
  81. package/css/slider.css +197 -0
  82. package/css/spinner.css +74 -0
  83. package/css/splitter.css +127 -0
  84. package/css/statistic.css +67 -0
  85. package/css/steps.css +252 -0
  86. package/css/switch.css +61 -0
  87. package/css/table.css +404 -0
  88. package/css/tabs.css +157 -0
  89. package/css/tags-input.css +360 -0
  90. package/css/text-field.css +195 -0
  91. package/css/thread.css +107 -0
  92. package/css/time-field.css +200 -0
  93. package/css/time-picker.css +347 -0
  94. package/css/time.css +20 -0
  95. package/css/timeline.css +284 -0
  96. package/css/toast.css +195 -0
  97. package/css/toaster.css +69 -0
  98. package/css/toggle-group.css +160 -0
  99. package/css/toggle.css +103 -0
  100. package/css/tone.css +85 -0
  101. package/css/toolbar.css +114 -0
  102. package/css/tooltip.css +109 -0
  103. package/css/tour.css +305 -0
  104. package/css/transfer.css +318 -0
  105. package/css/tree-select.css +441 -0
  106. package/css/tree.css +204 -0
  107. package/css/typography.css +151 -0
  108. package/css/undefined.css +38 -0
  109. package/css/virtualizer.css +104 -0
  110. package/css/visually-hidden.css +13 -0
  111. package/css/watermark.css +48 -0
  112. package/index.css +113 -0
  113. package/index.unlayered.css +16164 -0
  114. package/package.json +163 -0
@@ -0,0 +1,231 @@
1
+ @layer xihan.components {
2
+ /* 与文本框、分段日期同一套堆叠:标签一行、输入行一行 */
3
+ [data-scope='date-picker'][data-part='root'] {
4
+ display: inline-flex;
5
+ flex-direction: column;
6
+ gap: var(--xh-date-picker-gap, var(--xh-space-1));
7
+ }
8
+
9
+ /* 只要声明了 display 就盖掉了 UA 的 [hidden]{display:none},收起态得自己还回去 */
10
+ [data-scope='date-picker'][data-part='root'][hidden] {
11
+ display: none;
12
+ }
13
+
14
+ [data-scope='date-picker'][data-part='label'] {
15
+ color: var(--xh-date-picker-label-fg, var(--xh-fg-default));
16
+ font-size: var(--xh-date-picker-label-font-size, var(--xh-text-label-size));
17
+ font-weight: var(--xh-date-picker-label-font-weight, var(--xh-text-label-weight));
18
+ line-height: var(--xh-leading-none);
19
+ /* 点标题会把焦点送进首段,指针得说明这件事 */
20
+ cursor: default;
21
+ }
22
+
23
+ [data-scope='date-picker'][data-part='label'][hidden] {
24
+ display: none;
25
+ }
26
+
27
+ [data-scope='date-picker'][data-part='label'][data-disabled] {
28
+ color: var(--xh-date-picker-label-fg-disabled, var(--xh-fg-subtle));
29
+ cursor: not-allowed;
30
+ }
31
+
32
+ /* 画成一个框的是 control 而不是 input:段位、清空按钮、日历按钮三者要看起来是一体的,
33
+ 边框长在里面任何一个身上都会把另外两个割在框外 */
34
+ [data-scope='date-picker'][data-part='control'] {
35
+ display: inline-flex;
36
+ align-items: center;
37
+ gap: var(--xh-date-picker-control-gap, var(--xh-control-gap-md));
38
+ min-inline-size: var(--xh-date-picker-control-min-w, var(--xh-overlay-min-w));
39
+ block-size: var(--xh-date-picker-control-h, var(--xh-control-h-md));
40
+ padding-inline: var(--xh-date-picker-control-px, var(--xh-control-px-md));
41
+ padding-block: 0;
42
+ border: var(--xh-stroke-thin) solid var(--xh-date-picker-control-border, var(--xh-border-default));
43
+ border-radius: var(--xh-date-picker-control-radius, var(--xh-shape-control));
44
+ background: var(--xh-date-picker-control-bg, var(--xh-bg-canvas));
45
+ color: var(--xh-date-picker-control-fg, var(--xh-fg-default));
46
+ transition: border-color var(--xh-motion-duration-micro) var(--xh-motion-ease-enter);
47
+ }
48
+
49
+ [data-scope='date-picker'][data-part='control'][hidden] {
50
+ display: none;
51
+ }
52
+
53
+ /* hover 只在中性态换描边:invalid 正拿边框颜色说事,被 hover 盖掉那条信息就没了 */
54
+ [data-scope='date-picker'][data-part='control']:hover:not([data-disabled], [data-invalid]) {
55
+ border-color: var(--xh-date-picker-control-border-hover, var(--xh-border-strong));
56
+ }
57
+
58
+ /* 焦点落在某一段或某个按钮上,而边框长在 control 上:焦点环得由内向外借一层。
59
+ control 自己不占 Tab 位,:focus-within 是它唯一能感知组内焦点的方式 */
60
+ [data-scope='date-picker'][data-part='control']:focus-within {
61
+ border-color: var(--xh-date-picker-control-border-focus, var(--xh-ring-focus));
62
+ outline: var(--xh-ring-width) solid var(--xh-ring-focus);
63
+ outline-offset: var(--xh-ring-offset);
64
+ }
65
+
66
+ [data-scope='date-picker'][data-part='control'][data-invalid] {
67
+ border-color: var(--xh-date-picker-control-border-invalid, var(--xh-color-danger-500));
68
+ }
69
+
70
+ /* 只读仍可聚焦、日历仍能展开来看,不置灰,只把底色压下去表示"改不动" */
71
+ [data-scope='date-picker'][data-part='control'][data-readonly] {
72
+ background: var(--xh-date-picker-control-bg-readonly, var(--xh-bg-subtle));
73
+ }
74
+
75
+ [data-scope='date-picker'][data-part='control'][data-disabled] {
76
+ background: var(--xh-date-picker-control-bg-disabled, var(--xh-bg-subtle));
77
+ color: var(--xh-fg-disabled);
78
+ cursor: not-allowed;
79
+ }
80
+
81
+ /* 分段容器:段位自己那身皮由 date-field 那份样式负责(它们戴的是那一份解剖的标记),
82
+ 这里只管把一排段位横过来、占满输入行剩下的宽度 */
83
+ [data-scope='date-picker'][data-part='input'] {
84
+ display: inline-flex;
85
+ flex: 1;
86
+ align-items: center;
87
+ min-inline-size: 0;
88
+ block-size: 100%;
89
+ color: inherit;
90
+ /* 表单控件不继承页面字体,只给字号会让段位用 UA 默认字族,与周围文本对不上 */
91
+ font-family: inherit;
92
+ font-size: var(--xh-date-picker-font-size, var(--xh-text-body-size));
93
+ line-height: var(--xh-leading-none);
94
+ }
95
+
96
+ [data-scope='date-picker'][data-part='input'][hidden] {
97
+ display: none;
98
+ }
99
+
100
+ /* 容器自己不占 Tab 位、也不承载焦点,环由 control 画,这里不再套一圈 */
101
+ [data-scope='date-picker'][data-part='input']:focus-visible {
102
+ outline: none;
103
+ }
104
+
105
+ /* 两个按钮同一副长相:贴在框内末端的小方钮,不占宽度也不撑高 control */
106
+ [data-scope='date-picker'][data-part='trigger'],
107
+ [data-scope='date-picker'][data-part='clear-trigger'] {
108
+ display: inline-flex;
109
+ flex: none;
110
+ align-items: center;
111
+ justify-content: center;
112
+ inline-size: var(--xh-date-picker-action-size, var(--xh-control-action-size));
113
+ block-size: var(--xh-date-picker-action-size, var(--xh-control-action-size));
114
+ padding: 0;
115
+ border: 0;
116
+ border-radius: var(--xh-date-picker-action-radius, var(--xh-shape-control));
117
+ background: var(--xh-date-picker-action-bg, transparent);
118
+ color: var(--xh-date-picker-action-fg, var(--xh-fg-muted));
119
+ font-family: inherit;
120
+ font-size: var(--xh-date-picker-action-font-size, var(--xh-font-size-sm));
121
+ line-height: var(--xh-leading-none);
122
+ cursor: pointer;
123
+ user-select: none;
124
+ transition: background var(--xh-motion-duration-micro) var(--xh-motion-ease-enter);
125
+ }
126
+
127
+ [data-scope='date-picker'][data-part='trigger'][hidden],
128
+ [data-scope='date-picker'][data-part='clear-trigger'][hidden] {
129
+ display: none;
130
+ }
131
+
132
+ [data-scope='date-picker'][data-part='trigger']:hover:not(:disabled),
133
+ [data-scope='date-picker'][data-part='clear-trigger']:hover:not(:disabled) {
134
+ background: var(--xh-date-picker-action-bg-hover, var(--xh-bg-subtle-hover));
135
+ color: var(--xh-date-picker-action-fg-hover, var(--xh-fg-default));
136
+ }
137
+
138
+ [data-scope='date-picker'][data-part='trigger']:active:not(:disabled),
139
+ [data-scope='date-picker'][data-part='clear-trigger']:active:not(:disabled) {
140
+ background: var(--xh-date-picker-action-bg-active, var(--xh-bg-subtle-active));
141
+ }
142
+
143
+ /* 展开时按钮压一层底色,与浮层的存在互相印证 */
144
+ [data-scope='date-picker'][data-part='trigger'][data-state='open'] {
145
+ background: var(--xh-date-picker-action-bg-active, var(--xh-bg-subtle-active));
146
+ color: var(--xh-date-picker-action-fg-hover, var(--xh-fg-default));
147
+ }
148
+
149
+ /* trigger 在 Tab 序列里(清空按钮不在,它是 tabindex=-1 的兜底),落焦时必须看得见 */
150
+ [data-scope='date-picker'][data-part='trigger']:focus-visible,
151
+ [data-scope='date-picker'][data-part='clear-trigger']:focus-visible {
152
+ outline: var(--xh-ring-width) solid var(--xh-ring-focus);
153
+ outline-offset: var(--xh-ring-offset);
154
+ }
155
+
156
+ [data-scope='date-picker'][data-part='trigger']:disabled,
157
+ [data-scope='date-picker'][data-part='clear-trigger']:disabled {
158
+ background: var(--xh-date-picker-action-bg, transparent);
159
+ color: var(--xh-fg-disabled);
160
+ cursor: not-allowed;
161
+ }
162
+
163
+ /* 坐标由定位引擎写进 style(inset-inline-start / inset-block-start),这里只定位模式与层级 */
164
+ [data-scope='date-picker'][data-part='positioner'] {
165
+ position: fixed;
166
+ z-index: var(--xh-layer-popover);
167
+ /* 空壳不吃指针,交互只发生在 content 里 */
168
+ pointer-events: none;
169
+ }
170
+
171
+ /* 锚点被滚出可视区:整个浮层随之收起 */
172
+ [data-scope='date-picker'][data-part='positioner'][data-hidden] {
173
+ visibility: hidden;
174
+ }
175
+
176
+ [data-scope='date-picker'][data-part='content'] {
177
+ display: block;
178
+ padding: var(--xh-date-picker-content-p, var(--xh-space-3));
179
+ border: var(--xh-stroke-thin) solid var(--xh-date-picker-content-border, var(--xh-border-default));
180
+ border-radius: var(--xh-date-picker-content-radius, var(--xh-shape-surface));
181
+ background: var(--xh-date-picker-content-bg, var(--xh-bg-surface));
182
+ color: var(--xh-date-picker-content-fg, var(--xh-fg-default));
183
+ box-shadow: var(--xh-date-picker-content-shadow, var(--xh-elevation-2));
184
+ pointer-events: auto;
185
+ }
186
+
187
+ /* display 会盖掉 hidden 属性的 UA 规则,收起态显式让位 */
188
+ [data-scope='date-picker'][data-part='content'][hidden] {
189
+ display: none;
190
+ }
191
+
192
+ /* 浮层壳不承载焦点(焦点直接落到聚焦日那一格),但它写着 tabindex=-1,
193
+ 程序化落焦时不该再画一圈环 */
194
+ [data-scope='date-picker'][data-part='content']:focus-visible {
195
+ outline: none;
196
+ }
197
+
198
+ [data-scope='date-picker'][data-part='content'][data-state='open'] {
199
+ animation: xh-date-picker-in var(--xh-motion-duration-enter) var(--xh-motion-ease-enter);
200
+ }
201
+
202
+ /* 内嵌日历的挂载点同时充当日历的根节点:日历那份样式的 root 规则落在
203
+ [data-scope='calendar'][data-part='root'] 上,而这里没有那个节点,
204
+ 所以网格外层该有的排布得在这儿补齐(网格内部的皮仍归 calendar 那一份) */
205
+ [data-scope='date-picker'][data-part='calendar'] {
206
+ display: flex;
207
+ flex-direction: column;
208
+ gap: var(--xh-date-picker-calendar-gap, var(--xh-space-3));
209
+ /* 数字等宽:1 与 7 的字形宽度在比例字体里并不相同,不定住会让整张网格随月份抖动 */
210
+ font-variant-numeric: tabular-nums;
211
+ }
212
+
213
+ [data-scope='date-picker'][data-part='calendar'][hidden] {
214
+ display: none;
215
+ }
216
+ }
217
+
218
+ @layer xihan.motion {
219
+ /* 浮层进场:淡入 + 轻微上浮。名字带组件前缀,不与公共关键帧抢名 */
220
+ @keyframes xh-date-picker-in {
221
+ from {
222
+ opacity: 0;
223
+ translate: 0 -4px;
224
+ }
225
+
226
+ to {
227
+ opacity: 1;
228
+ translate: 0 0;
229
+ }
230
+ }
231
+ }
@@ -0,0 +1,200 @@
1
+ @layer xihan.components {
2
+ [data-scope='descriptions'][data-part='root'] {
3
+ /* 一个尺寸档只换这几个私有槽,每一格与格内两段都从根上继承它们,
4
+ 换档不必给每个部件各写一条选择器 */
5
+ --xh-_descriptions-gap: var(--xh-space-3);
6
+ --xh-_descriptions-pair-gap: var(--xh-space-1);
7
+ --xh-_descriptions-label-gap: var(--xh-space-2);
8
+ --xh-_descriptions-py: var(--xh-space-2);
9
+ --xh-_descriptions-px: var(--xh-space-3);
10
+ --xh-_descriptions-font-size: var(--xh-text-body-size);
11
+ /* 标签在左时那一列的宽度:收到最长的那个标签 */
12
+ --xh-_descriptions-label-w: max-content;
13
+
14
+ display: grid;
15
+ /* 不写 columns 即每行一组;二到六列各有一条规则 */
16
+ grid-template-columns: minmax(0, 1fr);
17
+ gap: var(--xh-descriptions-gap, var(--xh-_descriptions-gap));
18
+ /* 根可能写成 dl,UA 的上下外边距在这里清掉 */
19
+ margin: 0;
20
+ color: var(--xh-descriptions-fg, var(--xh-fg-default));
21
+ font-size: var(--xh-descriptions-font-size, var(--xh-_descriptions-font-size));
22
+ line-height: var(--xh-text-body-leading);
23
+ }
24
+
25
+ /* 上面声明了 display,会盖掉 UA 的 [hidden] 规则,收起态要在这里接回来 */
26
+ [data-scope='descriptions'][data-part='root'][hidden] {
27
+ display: none;
28
+ }
29
+
30
+ /* —— 列数 —— */
31
+ [data-scope='descriptions'][data-part='root'][data-columns='2'] {
32
+ grid-template-columns: repeat(2, minmax(0, 1fr));
33
+ }
34
+
35
+ [data-scope='descriptions'][data-part='root'][data-columns='3'] {
36
+ grid-template-columns: repeat(3, minmax(0, 1fr));
37
+ }
38
+
39
+ [data-scope='descriptions'][data-part='root'][data-columns='4'] {
40
+ grid-template-columns: repeat(4, minmax(0, 1fr));
41
+ }
42
+
43
+ [data-scope='descriptions'][data-part='root'][data-columns='5'] {
44
+ grid-template-columns: repeat(5, minmax(0, 1fr));
45
+ }
46
+
47
+ [data-scope='descriptions'][data-part='root'][data-columns='6'] {
48
+ grid-template-columns: repeat(6, minmax(0, 1fr));
49
+ }
50
+
51
+ /* —— 尺寸 —— */
52
+ [data-scope='descriptions'][data-part='root'][data-size='sm'] {
53
+ --xh-_descriptions-gap: var(--xh-space-2);
54
+ --xh-_descriptions-py: var(--xh-space-1);
55
+ --xh-_descriptions-px: var(--xh-space-2);
56
+ --xh-_descriptions-font-size: var(--xh-font-size-sm);
57
+ }
58
+
59
+ [data-scope='descriptions'][data-part='root'][data-size='lg'] {
60
+ --xh-_descriptions-gap: var(--xh-space-4);
61
+ --xh-_descriptions-pair-gap: var(--xh-space-2);
62
+ --xh-_descriptions-label-gap: var(--xh-space-3);
63
+ --xh-_descriptions-py: var(--xh-space-3);
64
+ --xh-_descriptions-px: var(--xh-space-4);
65
+ --xh-_descriptions-font-size: var(--xh-font-size-lg);
66
+ }
67
+
68
+ /* —— 每一格 —— */
69
+ /* 一格自己也是网格:不写 placement 即标签一行、取值一行叠着排 */
70
+ [data-scope='descriptions'][data-part='item'] {
71
+ display: grid;
72
+ grid-template-columns: minmax(0, 1fr);
73
+ align-content: start;
74
+ gap: var(--xh-descriptions-pair-gap, var(--xh-_descriptions-pair-gap));
75
+ }
76
+
77
+ /* 标签在左:一格分成「标签列 + 取值列」,两段的首行文字对齐同一条基线。
78
+ 只认自己的直接子格,套在取值里的另一份描述由它自己的根管 */
79
+ [data-scope='descriptions'][data-part='root'][data-placement='left']
80
+ > [data-scope='descriptions'][data-part='item'] {
81
+ grid-template-columns: var(--xh-descriptions-label-w, var(--xh-_descriptions-label-w)) minmax(0, 1fr);
82
+ align-items: baseline;
83
+ column-gap: var(--xh-descriptions-label-gap, var(--xh-_descriptions-label-gap));
84
+ }
85
+
86
+ [data-scope='descriptions'][data-part='label'] {
87
+ color: var(--xh-descriptions-label-fg, var(--xh-fg-muted));
88
+ font-weight: var(--xh-descriptions-label-font-weight, var(--xh-text-label-weight));
89
+ }
90
+
91
+ [data-scope='descriptions'][data-part='value'] {
92
+ /* 取值可能写成 dd,UA 的左缩进在这里清掉 */
93
+ margin: 0;
94
+ /* 网格项默认不肯收到内容以下,这行让长文本能被压窄 */
95
+ min-inline-size: 0;
96
+ color: var(--xh-descriptions-value-fg, var(--xh-fg-default));
97
+ }
98
+
99
+ /* —— 外框与网格线 —— */
100
+ [data-scope='descriptions'][data-part='root'][data-bordered] {
101
+ /* 网格线由每格自己的边线拼出来,格与格之间不能再留缝 */
102
+ gap: 0;
103
+ border: var(--xh-stroke-thin) solid var(--xh-descriptions-border, var(--xh-border-default));
104
+ border-radius: var(--xh-descriptions-radius, var(--xh-shape-surface));
105
+ background: var(--xh-descriptions-bg, var(--xh-bg-surface));
106
+ /* 四角的格子要被圆角裁住 */
107
+ overflow: hidden;
108
+ }
109
+
110
+ /* 每格自带上边线与左边线,行首与首行那几格再各自抹掉,相邻两格之间就只剩一条 */
111
+ [data-scope='descriptions'][data-part='root'][data-bordered]
112
+ > [data-scope='descriptions'][data-part='item'] {
113
+ padding-block: var(--xh-descriptions-item-py, var(--xh-_descriptions-py));
114
+ padding-inline: var(--xh-descriptions-item-px, var(--xh-_descriptions-px));
115
+ border-block-start: var(--xh-stroke-thin) solid var(--xh-descriptions-border, var(--xh-border-subtle));
116
+ /* 每行一组时左边没有邻居,宽度按列数补回来 */
117
+ border-inline-start: 0 solid var(--xh-descriptions-border, var(--xh-border-subtle));
118
+ }
119
+
120
+ [data-scope='descriptions'][data-part='root'][data-bordered]
121
+ > [data-scope='descriptions'][data-part='item']:first-child {
122
+ border-block-start-width: 0;
123
+ }
124
+
125
+ /* 二到六列:左边线一律补上,再抹掉每行第一格的左边线与首行那几格的上边线 */
126
+ [data-scope='descriptions'][data-part='root'][data-bordered][data-columns='2']
127
+ > [data-scope='descriptions'][data-part='item'] {
128
+ border-inline-start-width: var(--xh-stroke-thin);
129
+ }
130
+
131
+ [data-scope='descriptions'][data-part='root'][data-bordered][data-columns='2']
132
+ > [data-scope='descriptions'][data-part='item']:nth-child(2n + 1) {
133
+ border-inline-start-width: 0;
134
+ }
135
+
136
+ [data-scope='descriptions'][data-part='root'][data-bordered][data-columns='2']
137
+ > [data-scope='descriptions'][data-part='item']:nth-child(-n + 2) {
138
+ border-block-start-width: 0;
139
+ }
140
+
141
+ [data-scope='descriptions'][data-part='root'][data-bordered][data-columns='3']
142
+ > [data-scope='descriptions'][data-part='item'] {
143
+ border-inline-start-width: var(--xh-stroke-thin);
144
+ }
145
+
146
+ [data-scope='descriptions'][data-part='root'][data-bordered][data-columns='3']
147
+ > [data-scope='descriptions'][data-part='item']:nth-child(3n + 1) {
148
+ border-inline-start-width: 0;
149
+ }
150
+
151
+ [data-scope='descriptions'][data-part='root'][data-bordered][data-columns='3']
152
+ > [data-scope='descriptions'][data-part='item']:nth-child(-n + 3) {
153
+ border-block-start-width: 0;
154
+ }
155
+
156
+ [data-scope='descriptions'][data-part='root'][data-bordered][data-columns='4']
157
+ > [data-scope='descriptions'][data-part='item'] {
158
+ border-inline-start-width: var(--xh-stroke-thin);
159
+ }
160
+
161
+ [data-scope='descriptions'][data-part='root'][data-bordered][data-columns='4']
162
+ > [data-scope='descriptions'][data-part='item']:nth-child(4n + 1) {
163
+ border-inline-start-width: 0;
164
+ }
165
+
166
+ [data-scope='descriptions'][data-part='root'][data-bordered][data-columns='4']
167
+ > [data-scope='descriptions'][data-part='item']:nth-child(-n + 4) {
168
+ border-block-start-width: 0;
169
+ }
170
+
171
+ [data-scope='descriptions'][data-part='root'][data-bordered][data-columns='5']
172
+ > [data-scope='descriptions'][data-part='item'] {
173
+ border-inline-start-width: var(--xh-stroke-thin);
174
+ }
175
+
176
+ [data-scope='descriptions'][data-part='root'][data-bordered][data-columns='5']
177
+ > [data-scope='descriptions'][data-part='item']:nth-child(5n + 1) {
178
+ border-inline-start-width: 0;
179
+ }
180
+
181
+ [data-scope='descriptions'][data-part='root'][data-bordered][data-columns='5']
182
+ > [data-scope='descriptions'][data-part='item']:nth-child(-n + 5) {
183
+ border-block-start-width: 0;
184
+ }
185
+
186
+ [data-scope='descriptions'][data-part='root'][data-bordered][data-columns='6']
187
+ > [data-scope='descriptions'][data-part='item'] {
188
+ border-inline-start-width: var(--xh-stroke-thin);
189
+ }
190
+
191
+ [data-scope='descriptions'][data-part='root'][data-bordered][data-columns='6']
192
+ > [data-scope='descriptions'][data-part='item']:nth-child(6n + 1) {
193
+ border-inline-start-width: 0;
194
+ }
195
+
196
+ [data-scope='descriptions'][data-part='root'][data-bordered][data-columns='6']
197
+ > [data-scope='descriptions'][data-part='item']:nth-child(-n + 6) {
198
+ border-block-start-width: 0;
199
+ }
200
+ }
package/css/dialog.css ADDED
@@ -0,0 +1,127 @@
1
+ @layer xihan.components {
2
+ [data-scope='dialog'][data-part='backdrop'] {
3
+ position: fixed;
4
+ inset: 0;
5
+ z-index: var(--xh-layer-modal);
6
+ background: var(--xh-dialog-backdrop-bg, var(--xh-bg-overlay));
7
+ }
8
+
9
+ [data-scope='dialog'][data-part='backdrop'][data-state='open'] {
10
+ animation: xh-fade-in var(--xh-motion-duration-enter) var(--xh-motion-ease-enter);
11
+ }
12
+
13
+ [data-scope='dialog'][data-part='backdrop'][data-state='closed'] {
14
+ animation: xh-fade-out var(--xh-motion-duration-exit) var(--xh-motion-ease-exit);
15
+ }
16
+
17
+ [data-scope='dialog'][data-part='positioner'] {
18
+ position: fixed;
19
+ inset: 0;
20
+ z-index: var(--xh-layer-modal);
21
+ display: flex;
22
+ align-items: center;
23
+ justify-content: center;
24
+ padding: var(--xh-space-4);
25
+ }
26
+
27
+ [data-scope='dialog'][data-part='positioner'][data-position='top'] {
28
+ align-items: flex-start;
29
+ }
30
+
31
+ [data-scope='dialog'][data-part='content'] {
32
+ /* 尺寸档只换这一个私有槽。它声明在 content 而不是别处:dialog 的解剖里没有 root,
33
+ positioner 又不是必需部件,content 才是这层浮层恒在的最外层,且它会被 portal 到 body,
34
+ 选择器只认得它自己身上那一份 data-size。 */
35
+ --xh-_dialog-max-w: 32rem;
36
+
37
+ position: relative;
38
+ inline-size: 100%;
39
+ max-inline-size: var(--xh-dialog-max-w, var(--xh-_dialog-max-w));
40
+ display: flex;
41
+ flex-direction: column;
42
+ gap: var(--xh-dialog-gap, var(--xh-stack-gap-md));
43
+ padding-block: var(--xh-dialog-py, var(--xh-section-py));
44
+ padding-inline: var(--xh-dialog-px, var(--xh-control-px-lg));
45
+ border-radius: var(--xh-dialog-radius, var(--xh-shape-surface));
46
+ background: var(--xh-dialog-bg, var(--xh-bg-surface));
47
+ color: var(--xh-dialog-fg, var(--xh-fg-default));
48
+ box-shadow: var(--xh-dialog-shadow, var(--xh-elevation-3));
49
+ }
50
+
51
+ /* 收起态:connect 会给 content 打 hidden,但上面那条 display 会盖掉 UA 的
52
+ [hidden]{display:none}。meta 里 positioner 并非必需部件,按最小合规结构
53
+ (只有 trigger + content)写时,没有这一条收起的对话框就一直摊在页面上。 */
54
+ [data-scope='dialog'][data-part='content'][hidden] {
55
+ display: none;
56
+ }
57
+
58
+ /* —— 尺寸 —— */
59
+ /* 只有最大宽度分档;中间档不写规则,缺省即中档。
60
+ 宽度上限之外的一切(内边距、字号、圆角)都不随档位动:弹层的语气归里面的内容表达。 */
61
+ [data-scope='dialog'][data-part='content'][data-size='sm'] {
62
+ --xh-_dialog-max-w: 24rem;
63
+ }
64
+
65
+ [data-scope='dialog'][data-part='content'][data-size='lg'] {
66
+ --xh-_dialog-max-w: 48rem;
67
+ }
68
+
69
+ [data-scope='dialog'][data-part='content']:focus-visible {
70
+ outline: none;
71
+ }
72
+
73
+ /* 入场用 @starting-style 只驱动动画名切换;退场由 presence 保留 DOM 后播放 */
74
+ [data-scope='dialog'][data-part='content'][data-state='open'] {
75
+ animation: xh-dialog-in var(--xh-motion-duration-enter) var(--xh-motion-ease-enter);
76
+ }
77
+
78
+ [data-scope='dialog'][data-part='content'][data-state='closed'] {
79
+ animation: xh-dialog-out var(--xh-motion-duration-exit) var(--xh-motion-ease-exit);
80
+ }
81
+
82
+ [data-scope='dialog'][data-part='title'] {
83
+ margin: 0;
84
+ font-size: var(--xh-dialog-title-font-size, var(--xh-text-heading-3-size));
85
+ font-weight: var(--xh-dialog-title-font-weight, var(--xh-text-heading-3-weight));
86
+ color: var(--xh-dialog-title-fg, var(--xh-fg-default));
87
+ }
88
+
89
+ [data-scope='dialog'][data-part='description'] {
90
+ margin: 0;
91
+ font-size: var(--xh-text-body-size);
92
+ color: var(--xh-dialog-description-fg, var(--xh-fg-muted));
93
+ }
94
+
95
+ /* 关闭按钮是绝对定位的,不占流内宽度:标题得自己让出右上角那块,
96
+ 否则长标题会直接钻到按钮底下。只在真有关闭按钮时让位。 */
97
+ [data-scope='dialog'][data-part='content']:has([data-scope='dialog'][data-part='close-trigger'])
98
+ [data-scope='dialog'][data-part='title'] {
99
+ padding-inline-end: calc(var(--xh-control-h-sm) + var(--xh-space-3));
100
+ }
101
+
102
+ [data-scope='dialog'][data-part='close-trigger'] {
103
+ position: absolute;
104
+ inset-block-start: var(--xh-space-3);
105
+ inset-inline-end: var(--xh-space-3);
106
+ display: inline-flex;
107
+ align-items: center;
108
+ justify-content: center;
109
+ block-size: var(--xh-control-h-sm);
110
+ inline-size: var(--xh-control-h-sm);
111
+ border: 0;
112
+ border-radius: var(--xh-shape-control);
113
+ background: transparent;
114
+ color: var(--xh-fg-muted);
115
+ cursor: pointer;
116
+ }
117
+
118
+ [data-scope='dialog'][data-part='close-trigger']:hover {
119
+ background: var(--xh-bg-subtle);
120
+ color: var(--xh-fg-default);
121
+ }
122
+
123
+ [data-scope='dialog'][data-part='close-trigger']:focus-visible {
124
+ outline: var(--xh-ring-width) solid var(--xh-ring-focus);
125
+ outline-offset: var(--xh-ring-offset);
126
+ }
127
+ }