@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
package/css/card.css ADDED
@@ -0,0 +1,116 @@
1
+ @layer xihan.components {
2
+ [data-scope='card'][data-part='root'] {
3
+ display: flex;
4
+ flex-direction: column;
5
+ /* 封面要被圆角裁住,所以根自己收边 */
6
+ overflow: hidden;
7
+ border: var(--xh-stroke-thin) solid transparent;
8
+ border-radius: var(--xh-card-radius, var(--xh-shape-surface));
9
+ background: var(--xh-card-bg, var(--xh-bg-surface));
10
+ color: var(--xh-card-fg, var(--xh-fg-default));
11
+ /* 各段的内边距由根上这一个槽位统一给,换档只改这里 */
12
+ --xh-_card-pad: var(--xh-space-4);
13
+ }
14
+
15
+ /* —— 形态 —— */
16
+ [data-scope='card'][data-part='root'][data-variant='outline'] {
17
+ border-color: var(--xh-card-border, var(--xh-border-default));
18
+ }
19
+
20
+ [data-scope='card'][data-part='root'][data-variant='subtle'] {
21
+ background: var(--xh-card-bg, var(--xh-bg-subtle));
22
+ }
23
+
24
+ [data-scope='card'][data-part='root'][data-variant='elevated'] {
25
+ box-shadow: var(--xh-elevation-2);
26
+ }
27
+
28
+ [data-scope='card'][data-part='root'][data-variant='ghost'] {
29
+ background: transparent;
30
+ }
31
+
32
+ /* —— 尺寸 —— */
33
+ [data-scope='card'][data-part='root'][data-size='sm'] {
34
+ --xh-_card-pad: var(--xh-space-3);
35
+ }
36
+
37
+ [data-scope='card'][data-part='root'][data-size='lg'] {
38
+ --xh-_card-pad: var(--xh-space-6);
39
+ }
40
+
41
+ /* 悬停抬起:只在能用指针的设备上生效,触摸端不留一个按不掉的悬停态 */
42
+ @media (hover: hover) {
43
+ [data-scope='card'][data-part='root'][data-hoverable]:hover {
44
+ border-color: var(--xh-card-border, var(--xh-border-strong));
45
+ box-shadow: var(--xh-elevation-2);
46
+ }
47
+ }
48
+
49
+ [data-scope='card'][data-part='root'][data-hoverable] {
50
+ transition:
51
+ box-shadow var(--xh-motion-duration-micro) var(--xh-motion-ease-enter),
52
+ border-color var(--xh-motion-duration-micro) var(--xh-motion-ease-enter);
53
+ }
54
+
55
+ /* —— 各段 —— */
56
+ /* 封面顶到根的边上,不吃内边距 */
57
+ [data-scope='card'][data-part='cover'] {
58
+ display: block;
59
+ overflow: hidden;
60
+ }
61
+
62
+ [data-scope='card'][data-part='header'] {
63
+ display: flex;
64
+ flex-direction: column;
65
+ gap: var(--xh-space-1);
66
+ padding: var(--xh-_card-pad);
67
+ /* 头下面若还有别的段,间距由那一段自己的内边距接上,这里不重复留白 */
68
+ padding-block-end: var(--xh-space-2);
69
+ }
70
+
71
+ [data-scope='card'][data-part='title'] {
72
+ font-size: var(--xh-card-title-font-size, var(--xh-font-size-md));
73
+ font-weight: var(--xh-font-weight-medium);
74
+ line-height: var(--xh-leading-tight);
75
+ }
76
+
77
+ [data-scope='card'][data-part='root'][data-size='lg'] [data-part='title'] {
78
+ font-size: var(--xh-card-title-font-size, var(--xh-font-size-lg));
79
+ }
80
+
81
+ [data-scope='card'][data-part='description'] {
82
+ color: var(--xh-fg-muted);
83
+ font-size: var(--xh-font-size-sm);
84
+ line-height: var(--xh-leading-normal);
85
+ }
86
+
87
+ [data-scope='card'][data-part='body'] {
88
+ flex: 1 1 auto;
89
+ padding: var(--xh-_card-pad);
90
+ }
91
+
92
+ /* 头与身相邻时,头已经收窄了下边距,身不必再从顶上留一份 */
93
+ [data-scope='card'][data-part='header'] + [data-part='body'] {
94
+ padding-block-start: var(--xh-space-2);
95
+ }
96
+
97
+ [data-scope='card'][data-part='footer'] {
98
+ display: flex;
99
+ align-items: center;
100
+ gap: var(--xh-space-2);
101
+ padding: var(--xh-_card-pad);
102
+ padding-block-start: var(--xh-space-2);
103
+ }
104
+
105
+ /* —— 分段 —— */
106
+ /* 分隔线画在下一段的上边,段与段之间才只有一条 */
107
+ [data-scope='card'][data-part='root'][data-segmented] [data-part='body'],
108
+ [data-scope='card'][data-part='root'][data-segmented] [data-part='footer'] {
109
+ border-block-start: var(--xh-stroke-thin) solid var(--xh-card-border, var(--xh-border-subtle));
110
+ padding-block-start: var(--xh-_card-pad);
111
+ }
112
+
113
+ [data-scope='card'][data-part='root'][data-segmented] [data-part='header'] {
114
+ padding-block-end: var(--xh-_card-pad);
115
+ }
116
+ }
@@ -0,0 +1,193 @@
1
+ @layer xihan.components {
2
+ /* 根节点是 region 地标:把上一张 / 视口 / 下一张排成一行,指示点另起一行。
3
+ 两端按钮浮在视口上还是排在两侧由作者定,这里只给最朴素的一版排布 */
4
+ [data-scope='carousel'][data-part='root'] {
5
+ display: flex;
6
+ flex-wrap: wrap;
7
+ align-items: center;
8
+ gap: var(--xh-carousel-gap, var(--xh-space-2));
9
+ }
10
+
11
+ [data-scope='carousel'][data-part='root'][hidden] {
12
+ display: none;
13
+ }
14
+
15
+ /* 纵轨时按钮在上下两端,整条竖着排 */
16
+ [data-scope='carousel'][data-part='root'][data-orientation='vertical'] {
17
+ flex-direction: column;
18
+ }
19
+
20
+ /* 视口是裁切窗口:轨道比它宽(高),露在外面的那些张全靠它切掉。
21
+ min-inline-size: 0 是关键——弹性子项的默认最小尺寸是内容尺寸,
22
+ 不压成 0 的话视口会被整条轨道撑开,什么都切不掉 */
23
+ [data-scope='carousel'][data-part='viewport'] {
24
+ flex: 1 1 auto;
25
+ min-inline-size: 0;
26
+ overflow: hidden;
27
+ border-radius: var(--xh-carousel-viewport-radius, var(--xh-shape-surface));
28
+ }
29
+
30
+ [data-scope='carousel'][data-part='viewport'][hidden] {
31
+ display: none;
32
+ }
33
+
34
+ /* 被位移的那条轨道。
35
+ transform 归连接层:整页位移与拖拽中的像素偏移都写在它的内联 style 上,
36
+ 样式层再碰这条轴就会把两个位移互相覆盖,画面当场错位。
37
+ 这里只负责排布与过渡 */
38
+ [data-scope='carousel'][data-part='item-group'] {
39
+ display: flex;
40
+ flex-direction: row;
41
+ block-size: 100%;
42
+ transition: transform var(--xh-carousel-duration, var(--xh-motion-duration-enter))
43
+ var(--xh-carousel-ease, var(--xh-motion-ease-enter));
44
+ }
45
+
46
+ [data-scope='carousel'][data-part='item-group'][hidden] {
47
+ display: none;
48
+ }
49
+
50
+ [data-scope='carousel'][data-part='item-group'][data-orientation='vertical'] {
51
+ flex-direction: column;
52
+ }
53
+
54
+ /* 拖拽期间关掉过渡:留着的话画面会拖着手指慢半拍,像在拉一根皮筋 */
55
+ [data-scope='carousel'][data-part='item-group'][data-dragging] {
56
+ transition: none;
57
+ }
58
+
59
+ /* 一张幻灯片。
60
+ 尺寸(flex-basis)与间距(padding)同样归连接层:一屏放几张只有它知道,
61
+ CSS 拿不到那个数(属性值参与不了计算)。这里只补三件配套的事:
62
+ · box-sizing —— 内联的 padding 不得把这张撑出格子(reset 层已有同款兜底);
63
+ · flex-grow/shrink 归零 —— 弹性布局默认会把不满一屏的那几张拉伸,位移就对不上了;
64
+ · min-inline-size: 0 —— 同视口,防止长内容把这张顶宽 */
65
+ [data-scope='carousel'][data-part='item'] {
66
+ box-sizing: border-box;
67
+ flex-grow: 0;
68
+ flex-shrink: 0;
69
+ min-inline-size: 0;
70
+ }
71
+
72
+ [data-scope='carousel'][data-part='item'][hidden] {
73
+ display: none;
74
+ }
75
+
76
+ /* 两端按钮:圆形、与控件同高,禁用时靠原生 :disabled 变灰 */
77
+ [data-scope='carousel'][data-part='prev-trigger'],
78
+ [data-scope='carousel'][data-part='next-trigger'] {
79
+ display: inline-flex;
80
+ flex: none;
81
+ align-items: center;
82
+ justify-content: center;
83
+ inline-size: var(--xh-carousel-trigger-size, var(--xh-control-h-md));
84
+ block-size: var(--xh-carousel-trigger-size, var(--xh-control-h-md));
85
+ border: var(--xh-stroke-thin) solid var(--xh-carousel-trigger-border, var(--xh-border-default));
86
+ border-radius: var(--xh-carousel-trigger-radius, var(--xh-shape-pill));
87
+ background: var(--xh-carousel-trigger-bg, var(--xh-bg-surface));
88
+ color: var(--xh-carousel-trigger-fg, var(--xh-fg-default));
89
+ line-height: var(--xh-leading-none);
90
+ cursor: pointer;
91
+ transition:
92
+ background var(--xh-motion-duration-micro) var(--xh-motion-ease-enter),
93
+ border-color var(--xh-motion-duration-micro) var(--xh-motion-ease-enter);
94
+ }
95
+
96
+ [data-scope='carousel'][data-part='prev-trigger'][hidden],
97
+ [data-scope='carousel'][data-part='next-trigger'][hidden] {
98
+ display: none;
99
+ }
100
+
101
+ [data-scope='carousel'][data-part='prev-trigger']:hover:not(:disabled),
102
+ [data-scope='carousel'][data-part='next-trigger']:hover:not(:disabled) {
103
+ background: var(--xh-carousel-trigger-bg-hover, var(--xh-bg-subtle-hover));
104
+ }
105
+
106
+ [data-scope='carousel'][data-part='prev-trigger']:active:not(:disabled),
107
+ [data-scope='carousel'][data-part='next-trigger']:active:not(:disabled) {
108
+ background: var(--xh-carousel-trigger-bg-active, var(--xh-bg-subtle-active));
109
+ }
110
+
111
+ [data-scope='carousel'][data-part='prev-trigger']:focus-visible,
112
+ [data-scope='carousel'][data-part='next-trigger']:focus-visible,
113
+ [data-scope='carousel'][data-part='indicator']:focus-visible {
114
+ outline: var(--xh-ring-width) solid var(--xh-ring-focus);
115
+ outline-offset: var(--xh-ring-offset);
116
+ }
117
+
118
+ /* 两端到头时按钮是原生 disabled(不可聚焦、进不了 Tab 序列),所以这里必须用 :disabled;
119
+ 连接层同时给的 data-disabled 只是留给作者的钩子 */
120
+ [data-scope='carousel'][data-part='prev-trigger']:disabled,
121
+ [data-scope='carousel'][data-part='next-trigger']:disabled {
122
+ color: var(--xh-fg-disabled);
123
+ cursor: not-allowed;
124
+ }
125
+
126
+ /* 视口与指示点都不是可聚焦节点,落焦只会是浏览器兜底行为,别画焦点环 */
127
+ [data-scope='carousel'][data-part='viewport']:focus-visible,
128
+ [data-scope='carousel'][data-part='item-group']:focus-visible,
129
+ [data-scope='carousel'][data-part='indicator-group']:focus-visible {
130
+ outline: none;
131
+ }
132
+
133
+ [data-scope='carousel'][data-part='indicator-group'] {
134
+ display: flex;
135
+ flex-wrap: wrap;
136
+ align-items: center;
137
+ justify-content: center;
138
+ gap: var(--xh-carousel-indicator-gap, var(--xh-space-1));
139
+ }
140
+
141
+ [data-scope='carousel'][data-part='indicator-group'][hidden] {
142
+ display: none;
143
+ }
144
+
145
+ [data-scope='carousel'][data-part='indicator-group'][data-orientation='vertical'] {
146
+ flex-direction: column;
147
+ }
148
+
149
+ /* 横轨时指示点另起一行占满整宽(根节点开了 flex-wrap),不跟两端按钮挤在同一行 */
150
+ [data-scope='carousel'][data-part='indicator-group'][data-orientation='horizontal'] {
151
+ flex-basis: 100%;
152
+ }
153
+
154
+ /* 指示点:一颗小圆点。点得动的东西必须够大才点得中,
155
+ 所以圆点本身小、可点区域靠内边距撑到最小触达尺寸 */
156
+ [data-scope='carousel'][data-part='indicator'] {
157
+ display: inline-flex;
158
+ flex: none;
159
+ align-items: center;
160
+ justify-content: center;
161
+ inline-size: var(--xh-carousel-indicator-size, var(--xh-space-2));
162
+ block-size: var(--xh-carousel-indicator-size, var(--xh-space-2));
163
+ /* 圆点本身没有文字,按钮里的文案(页码)交给作者,默认不显示 */
164
+ padding: 0;
165
+ border: 0;
166
+ border-radius: var(--xh-carousel-indicator-radius, var(--xh-radius-full));
167
+ background: var(--xh-carousel-indicator-bg, var(--xh-border-strong));
168
+ font-size: 0;
169
+ cursor: pointer;
170
+ transition: background var(--xh-motion-duration-micro) var(--xh-motion-ease-enter);
171
+ }
172
+
173
+ [data-scope='carousel'][data-part='indicator'][hidden] {
174
+ display: none;
175
+ }
176
+
177
+ [data-scope='carousel'][data-part='indicator']:hover:not([data-selected]) {
178
+ background: var(--xh-carousel-indicator-bg-hover, var(--xh-fg-subtle));
179
+ }
180
+
181
+ /* 当前页:data-selected 与 aria-current='true' 由连接层成对给出,
182
+ 样式挂在 data 钩子上,无障碍语义留给 aria,两边各司其职 */
183
+ [data-scope='carousel'][data-part='indicator'][data-selected] {
184
+ background: var(--xh-carousel-indicator-bg-selected, var(--xh-bg-brand));
185
+ }
186
+
187
+ /* 减少动效:位移立刻到位。翻页本身照常发生,只是不再有滑动的过程 */
188
+ @media (prefers-reduced-motion: reduce) {
189
+ [data-scope='carousel'][data-part='item-group'] {
190
+ transition: none;
191
+ }
192
+ }
193
+ }