@manohub/ui 0.10.5 → 1.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 (70) hide show
  1. package/README.md +155 -155
  2. package/dist/components/form/index.js +8 -1
  3. package/dist/styles/components/avatar.css +131 -131
  4. package/dist/styles/components/avatar.tokens.css +24 -24
  5. package/dist/styles/components/badge.css +266 -266
  6. package/dist/styles/components/badge.tokens.css +24 -24
  7. package/dist/styles/components/button.css +460 -460
  8. package/dist/styles/components/capsule.css +128 -128
  9. package/dist/styles/components/capsule.tokens.css +27 -27
  10. package/dist/styles/components/card.css +198 -198
  11. package/dist/styles/components/checkbox.css +145 -145
  12. package/dist/styles/components/checkbox.tokens.css +26 -26
  13. package/dist/styles/components/code-block.css +216 -216
  14. package/dist/styles/components/code-block.tokens.css +40 -40
  15. package/dist/styles/components/collapse.css +62 -62
  16. package/dist/styles/components/collapse.tokens.css +20 -20
  17. package/dist/styles/components/dialog.css +158 -158
  18. package/dist/styles/components/dialog.tokens.css +24 -24
  19. package/dist/styles/components/divider.css +75 -75
  20. package/dist/styles/components/divider.tokens.css +22 -22
  21. package/dist/styles/components/drawer.css +143 -143
  22. package/dist/styles/components/drawer.tokens.css +22 -22
  23. package/dist/styles/components/filter.css +29 -29
  24. package/dist/styles/components/form.css +442 -425
  25. package/dist/styles/components/form.tokens.css +15 -15
  26. package/dist/styles/components/input.css +538 -538
  27. package/dist/styles/components/input.tokens.css +43 -43
  28. package/dist/styles/components/layout.css +200 -200
  29. package/dist/styles/components/list-view.css +244 -244
  30. package/dist/styles/components/loading.css +76 -76
  31. package/dist/styles/components/loading.tokens.css +23 -23
  32. package/dist/styles/components/nav.css +48 -48
  33. package/dist/styles/components/notice.css +153 -153
  34. package/dist/styles/components/notice.tokens.css +17 -17
  35. package/dist/styles/components/notification.css +159 -159
  36. package/dist/styles/components/notification.tokens.css +37 -37
  37. package/dist/styles/components/page.css +473 -473
  38. package/dist/styles/components/pagination.css +303 -303
  39. package/dist/styles/components/pagination.tokens.css +32 -32
  40. package/dist/styles/components/panel.css +77 -77
  41. package/dist/styles/components/query-state.css +88 -88
  42. package/dist/styles/components/radio.css +271 -271
  43. package/dist/styles/components/radio.tokens.css +26 -26
  44. package/dist/styles/components/search.css +34 -34
  45. package/dist/styles/components/select.css +326 -326
  46. package/dist/styles/components/select.tokens.css +44 -44
  47. package/dist/styles/components/skeleton.css +60 -60
  48. package/dist/styles/components/skeleton.tokens.css +27 -27
  49. package/dist/styles/components/steps.css +205 -205
  50. package/dist/styles/components/steps.tokens.css +44 -44
  51. package/dist/styles/components/switch.css +165 -165
  52. package/dist/styles/components/switch.tokens.css +26 -26
  53. package/dist/styles/components/tabbar.css +235 -235
  54. package/dist/styles/components/tabbar.tokens.css +30 -30
  55. package/dist/styles/components/table.css +504 -504
  56. package/dist/styles/components/table.tokens.css +44 -44
  57. package/dist/styles/components/tag.css +127 -127
  58. package/dist/styles/components/tag.tokens.css +24 -24
  59. package/dist/styles/components/toast.css +185 -185
  60. package/dist/styles/components/toast.tokens.css +26 -26
  61. package/dist/styles/components/tooltip.css +89 -89
  62. package/dist/styles/components/tooltip.tokens.css +25 -25
  63. package/dist/styles/components/tree.css +173 -173
  64. package/dist/styles/components/upload.css +151 -151
  65. package/dist/styles/components/upload.tokens.css +27 -27
  66. package/dist/styles/index.css +153 -153
  67. package/dist/styles/operations/collapse.css +84 -84
  68. package/dist/styles/operations/popup.css +193 -193
  69. package/dist/styles/operations/tabs.css +82 -82
  70. package/package.json +62 -62
@@ -1,244 +1,244 @@
1
- /**
2
- * ListView(卡片网格列表:容器自适应列数 + 骨架卡 + 三态)。
3
- *
4
- * 依据:卡片本体沿用 card.css(Card);本文件只管网格容器、骨架卡与卡片项几何。
5
- */
6
-
7
- /* ===== ListView(卡片网格列表:容器自适应列数 + 骨架卡 + 三态)=====
8
- 列数由**容器宽度**决定(auto-fill),不跟视口断点:窄栏自动减列。
9
- `min(var(--mh-list-view-min), 100%)` 是必需的一层保护 —— 只写固定下限时,
10
- 容器比下限还窄会溢出(列宽不会缩到容器以内)。 */
11
-
12
- .mh-list-view {
13
- --mh-list-view-min: var(--ui-grid-column-min);
14
- --mh-list-view-gap: var(--ui-space-5);
15
- --mh-list-view-card-min-height: 144px;
16
- display: grid;
17
- grid-template-columns: repeat(auto-fill, minmax(min(var(--mh-list-view-min), 100%), 1fr));
18
- gap: var(--mh-list-view-gap);
19
- align-items: stretch;
20
- }
21
-
22
- /* 骨架卡:与卡片同尺寸(最小高 + 圆角),避免加载完成时高度跳动 */
23
-
24
- .mh-list-view__skeleton {
25
- min-height: var(--mh-list-view-card-min-height);
26
- border-radius: var(--ui-radius-md);
27
- background: var(--ui-base-200);
28
- animation: mh-list-view-pulse 1.4s ease-in-out infinite;
29
- }
30
-
31
- @keyframes mh-list-view-pulse {
32
- 0%,
33
- 100% {
34
- opacity: 1;
35
- }
36
- 50% {
37
- opacity: 0.55;
38
- }
39
- }
40
-
41
- /* 列表卡片项:最小高对齐(原型 min-h-36),同排卡片等高、尾部一行对齐 */
42
-
43
- .mh-list-view__card {
44
- min-height: var(--mh-list-view-card-min-height);
45
- }
46
-
47
- /* 头部:图标 + 标题块 + 状态胶囊(原型 flex items-start) */
48
-
49
- .mh-list-view__card-head {
50
- display: flex;
51
- align-items: flex-start;
52
- gap: var(--ui-space-3);
53
- }
54
-
55
- /* 图标容器 36×36(原型 h-9 w-9),圆角取控件档 6(原型 rounded-md) */
56
-
57
- .mh-list-view__card-icon {
58
- flex: none;
59
- width: 36px;
60
- height: 36px;
61
- overflow: hidden;
62
- border-radius: var(--ui-radius-control);
63
- }
64
-
65
- .mh-list-view__card-icon-img {
66
- display: block;
67
- width: 100%;
68
- height: 100%;
69
- object-fit: cover;
70
- }
71
-
72
- .mh-list-view__card-title-block {
73
- display: flex;
74
- flex: 1;
75
- flex-direction: column;
76
- min-width: 0;
77
- }
78
-
79
- /* 标题 16/600(原型 text-base font-semibold leading-6,与令牌档一致) */
80
-
81
- .mh-list-view__card-title {
82
- overflow: hidden;
83
- font-size: var(--ui-font-heading);
84
- font-weight: var(--ui-weight-semibold);
85
- line-height: var(--ui-line-heading);
86
- color: var(--ui-base-content);
87
- text-overflow: ellipsis;
88
- white-space: nowrap;
89
- }
90
-
91
- .mh-list-view__card-subtitle {
92
- font-size: var(--ui-font-caption);
93
- line-height: var(--ui-line-caption);
94
- color: var(--ui-base-content-muted);
95
- }
96
-
97
- /* 状态胶囊:全圆角 + 弱底同色字(原型 rounded-full px-2.5 text-xs leading-5) */
98
-
99
- .mh-list-view__card-status {
100
- --mh-status-fg: var(--ui-primary);
101
- --mh-status-bg: var(--ui-primary-weak);
102
- display: inline-flex;
103
- flex: none;
104
- align-items: center;
105
- gap: var(--ui-space-1);
106
- margin-left: auto;
107
- padding: 0 10px;
108
- border-radius: var(--ui-radius-full);
109
- font-size: var(--ui-font-caption);
110
- line-height: var(--ui-line-caption);
111
- white-space: nowrap;
112
- color: var(--mh-status-fg);
113
- background: var(--mh-status-bg);
114
- }
115
-
116
- .mh-list-view__card-status--primary {
117
- --mh-status-fg: var(--ui-primary);
118
- --mh-status-bg: var(--ui-primary-weak);
119
- }
120
-
121
- .mh-list-view__card-status--success {
122
- --mh-status-fg: var(--ui-success-strong);
123
- --mh-status-bg: var(--ui-success-weak);
124
- }
125
-
126
- .mh-list-view__card-status--warning {
127
- --mh-status-fg: var(--ui-warning-strong);
128
- --mh-status-bg: var(--ui-warning-weak);
129
- }
130
-
131
- .mh-list-view__card-status--error {
132
- --mh-status-fg: var(--ui-error);
133
- --mh-status-bg: var(--ui-error-weak);
134
- }
135
-
136
- .mh-list-view__card-status--neutral {
137
- --mh-status-fg: var(--ui-base-content-muted);
138
- --mh-status-bg: var(--ui-base-200);
139
- }
140
-
141
- .mh-list-view__card-status-dot {
142
- width: 6px;
143
- height: 6px;
144
- flex: none;
145
- border-radius: var(--ui-radius-full);
146
- background: var(--mh-status-fg);
147
- }
148
-
149
- /* 描述:两行截断(原型 line-clamp-2 text-xs text-muted-foreground) */
150
-
151
- .mh-list-view__card-desc {
152
- display: -webkit-box;
153
- margin: 0;
154
- overflow: hidden;
155
- -webkit-box-orient: vertical;
156
- -webkit-line-clamp: 2;
157
- line-clamp: 2;
158
- font-size: var(--ui-font-caption);
159
- line-height: var(--ui-line-caption);
160
- color: var(--ui-base-content-muted);
161
- }
162
-
163
- /* 尾部:左「自定义内容 + 标签组」、右「统计 + 操作位」;贴卡片底部(原型 mt-auto) */
164
-
165
- .mh-list-view__card-foot {
166
- display: flex;
167
- align-items: center;
168
- gap: var(--ui-space-2);
169
- margin-top: auto;
170
- }
171
-
172
- .mh-list-view__card-foot-main {
173
- display: flex;
174
- align-items: center;
175
- gap: var(--ui-space-2);
176
- min-width: 0;
177
- }
178
-
179
- .mh-list-view__card-foot-side {
180
- display: flex;
181
- flex: none;
182
- align-items: center;
183
- gap: var(--ui-space-1);
184
- margin-left: auto;
185
- }
186
-
187
- .mh-list-view__card-tags {
188
- display: flex;
189
- align-items: center;
190
- gap: var(--ui-space-2);
191
- min-width: 0;
192
- }
193
-
194
- /* 标签片:主色弱底 + 主色字 + 小圆角(原型 rounded bg-primary/10 px-2 leading-5 font-medium) */
195
-
196
- .mh-list-view__card-tag {
197
- flex: none;
198
- padding: 0 var(--ui-space-2);
199
- border-radius: var(--ui-radius-sm);
200
- font-size: var(--ui-font-caption);
201
- font-weight: var(--ui-weight-medium);
202
- line-height: var(--ui-line-caption);
203
- color: var(--ui-primary);
204
- background: var(--ui-primary-weak);
205
- }
206
-
207
- .mh-list-view__card-extra {
208
- display: inline-flex;
209
- align-items: center;
210
- gap: var(--ui-space-1);
211
- font-size: var(--ui-font-caption);
212
- line-height: var(--ui-line-caption);
213
- color: var(--ui-base-content-muted);
214
- }
215
-
216
- /* 操作位:默认隐藏,卡片悬浮(或卡内获得焦点)时显形 —— 键盘 Tab 进来同样可见。
217
- 触屏没有 hover 能力,故 hover 缺失时恒显形,避免操作不可达。 */
218
-
219
- .mh-list-view__card-actions {
220
- display: inline-flex;
221
- align-items: center;
222
- gap: var(--ui-space-1);
223
- opacity: 0;
224
- transition: opacity 0.15s ease;
225
- }
226
-
227
- .mh-list-view__card:hover .mh-list-view__card-actions {
228
- opacity: 1;
229
- }
230
-
231
- .mh-list-view__card:focus-within .mh-list-view__card-actions {
232
- opacity: 1;
233
- }
234
-
235
- @media (hover: none) {
236
- .mh-list-view__card-actions {
237
- opacity: 1;
238
- }
239
- }
240
-
241
- /* ===== 固定列数档(`columns > 0`):不再按容器宽度自适应 ===== */
242
- .mh-list-view--fixed {
243
- grid-template-columns: repeat(var(--mh-list-view-columns, 1), minmax(0, 1fr));
244
- }
1
+ /**
2
+ * ListView(卡片网格列表:容器自适应列数 + 骨架卡 + 三态)。
3
+ *
4
+ * 依据:卡片本体沿用 card.css(Card);本文件只管网格容器、骨架卡与卡片项几何。
5
+ */
6
+
7
+ /* ===== ListView(卡片网格列表:容器自适应列数 + 骨架卡 + 三态)=====
8
+ 列数由**容器宽度**决定(auto-fill),不跟视口断点:窄栏自动减列。
9
+ `min(var(--mh-list-view-min), 100%)` 是必需的一层保护 —— 只写固定下限时,
10
+ 容器比下限还窄会溢出(列宽不会缩到容器以内)。 */
11
+
12
+ .mh-list-view {
13
+ --mh-list-view-min: var(--ui-grid-column-min);
14
+ --mh-list-view-gap: var(--ui-space-5);
15
+ --mh-list-view-card-min-height: 144px;
16
+ display: grid;
17
+ grid-template-columns: repeat(auto-fill, minmax(min(var(--mh-list-view-min), 100%), 1fr));
18
+ gap: var(--mh-list-view-gap);
19
+ align-items: stretch;
20
+ }
21
+
22
+ /* 骨架卡:与卡片同尺寸(最小高 + 圆角),避免加载完成时高度跳动 */
23
+
24
+ .mh-list-view__skeleton {
25
+ min-height: var(--mh-list-view-card-min-height);
26
+ border-radius: var(--ui-radius-md);
27
+ background: var(--ui-base-200);
28
+ animation: mh-list-view-pulse 1.4s ease-in-out infinite;
29
+ }
30
+
31
+ @keyframes mh-list-view-pulse {
32
+ 0%,
33
+ 100% {
34
+ opacity: 1;
35
+ }
36
+ 50% {
37
+ opacity: 0.55;
38
+ }
39
+ }
40
+
41
+ /* 列表卡片项:最小高对齐(原型 min-h-36),同排卡片等高、尾部一行对齐 */
42
+
43
+ .mh-list-view__card {
44
+ min-height: var(--mh-list-view-card-min-height);
45
+ }
46
+
47
+ /* 头部:图标 + 标题块 + 状态胶囊(原型 flex items-start) */
48
+
49
+ .mh-list-view__card-head {
50
+ display: flex;
51
+ align-items: flex-start;
52
+ gap: var(--ui-space-3);
53
+ }
54
+
55
+ /* 图标容器 36×36(原型 h-9 w-9),圆角取控件档 6(原型 rounded-md) */
56
+
57
+ .mh-list-view__card-icon {
58
+ flex: none;
59
+ width: 36px;
60
+ height: 36px;
61
+ overflow: hidden;
62
+ border-radius: var(--ui-radius-control);
63
+ }
64
+
65
+ .mh-list-view__card-icon-img {
66
+ display: block;
67
+ width: 100%;
68
+ height: 100%;
69
+ object-fit: cover;
70
+ }
71
+
72
+ .mh-list-view__card-title-block {
73
+ display: flex;
74
+ flex: 1;
75
+ flex-direction: column;
76
+ min-width: 0;
77
+ }
78
+
79
+ /* 标题 16/600(原型 text-base font-semibold leading-6,与令牌档一致) */
80
+
81
+ .mh-list-view__card-title {
82
+ overflow: hidden;
83
+ font-size: var(--ui-font-heading);
84
+ font-weight: var(--ui-weight-semibold);
85
+ line-height: var(--ui-line-heading);
86
+ color: var(--ui-base-content);
87
+ text-overflow: ellipsis;
88
+ white-space: nowrap;
89
+ }
90
+
91
+ .mh-list-view__card-subtitle {
92
+ font-size: var(--ui-font-caption);
93
+ line-height: var(--ui-line-caption);
94
+ color: var(--ui-base-content-muted);
95
+ }
96
+
97
+ /* 状态胶囊:全圆角 + 弱底同色字(原型 rounded-full px-2.5 text-xs leading-5) */
98
+
99
+ .mh-list-view__card-status {
100
+ --mh-status-fg: var(--ui-primary);
101
+ --mh-status-bg: var(--ui-primary-weak);
102
+ display: inline-flex;
103
+ flex: none;
104
+ align-items: center;
105
+ gap: var(--ui-space-1);
106
+ margin-left: auto;
107
+ padding: 0 10px;
108
+ border-radius: var(--ui-radius-full);
109
+ font-size: var(--ui-font-caption);
110
+ line-height: var(--ui-line-caption);
111
+ white-space: nowrap;
112
+ color: var(--mh-status-fg);
113
+ background: var(--mh-status-bg);
114
+ }
115
+
116
+ .mh-list-view__card-status--primary {
117
+ --mh-status-fg: var(--ui-primary);
118
+ --mh-status-bg: var(--ui-primary-weak);
119
+ }
120
+
121
+ .mh-list-view__card-status--success {
122
+ --mh-status-fg: var(--ui-success-strong);
123
+ --mh-status-bg: var(--ui-success-weak);
124
+ }
125
+
126
+ .mh-list-view__card-status--warning {
127
+ --mh-status-fg: var(--ui-warning-strong);
128
+ --mh-status-bg: var(--ui-warning-weak);
129
+ }
130
+
131
+ .mh-list-view__card-status--error {
132
+ --mh-status-fg: var(--ui-error);
133
+ --mh-status-bg: var(--ui-error-weak);
134
+ }
135
+
136
+ .mh-list-view__card-status--neutral {
137
+ --mh-status-fg: var(--ui-base-content-muted);
138
+ --mh-status-bg: var(--ui-base-200);
139
+ }
140
+
141
+ .mh-list-view__card-status-dot {
142
+ width: 6px;
143
+ height: 6px;
144
+ flex: none;
145
+ border-radius: var(--ui-radius-full);
146
+ background: var(--mh-status-fg);
147
+ }
148
+
149
+ /* 描述:两行截断(原型 line-clamp-2 text-xs text-muted-foreground) */
150
+
151
+ .mh-list-view__card-desc {
152
+ display: -webkit-box;
153
+ margin: 0;
154
+ overflow: hidden;
155
+ -webkit-box-orient: vertical;
156
+ -webkit-line-clamp: 2;
157
+ line-clamp: 2;
158
+ font-size: var(--ui-font-caption);
159
+ line-height: var(--ui-line-caption);
160
+ color: var(--ui-base-content-muted);
161
+ }
162
+
163
+ /* 尾部:左「自定义内容 + 标签组」、右「统计 + 操作位」;贴卡片底部(原型 mt-auto) */
164
+
165
+ .mh-list-view__card-foot {
166
+ display: flex;
167
+ align-items: center;
168
+ gap: var(--ui-space-2);
169
+ margin-top: auto;
170
+ }
171
+
172
+ .mh-list-view__card-foot-main {
173
+ display: flex;
174
+ align-items: center;
175
+ gap: var(--ui-space-2);
176
+ min-width: 0;
177
+ }
178
+
179
+ .mh-list-view__card-foot-side {
180
+ display: flex;
181
+ flex: none;
182
+ align-items: center;
183
+ gap: var(--ui-space-1);
184
+ margin-left: auto;
185
+ }
186
+
187
+ .mh-list-view__card-tags {
188
+ display: flex;
189
+ align-items: center;
190
+ gap: var(--ui-space-2);
191
+ min-width: 0;
192
+ }
193
+
194
+ /* 标签片:主色弱底 + 主色字 + 小圆角(原型 rounded bg-primary/10 px-2 leading-5 font-medium) */
195
+
196
+ .mh-list-view__card-tag {
197
+ flex: none;
198
+ padding: 0 var(--ui-space-2);
199
+ border-radius: var(--ui-radius-sm);
200
+ font-size: var(--ui-font-caption);
201
+ font-weight: var(--ui-weight-medium);
202
+ line-height: var(--ui-line-caption);
203
+ color: var(--ui-primary);
204
+ background: var(--ui-primary-weak);
205
+ }
206
+
207
+ .mh-list-view__card-extra {
208
+ display: inline-flex;
209
+ align-items: center;
210
+ gap: var(--ui-space-1);
211
+ font-size: var(--ui-font-caption);
212
+ line-height: var(--ui-line-caption);
213
+ color: var(--ui-base-content-muted);
214
+ }
215
+
216
+ /* 操作位:默认隐藏,卡片悬浮(或卡内获得焦点)时显形 —— 键盘 Tab 进来同样可见。
217
+ 触屏没有 hover 能力,故 hover 缺失时恒显形,避免操作不可达。 */
218
+
219
+ .mh-list-view__card-actions {
220
+ display: inline-flex;
221
+ align-items: center;
222
+ gap: var(--ui-space-1);
223
+ opacity: 0;
224
+ transition: opacity 0.15s ease;
225
+ }
226
+
227
+ .mh-list-view__card:hover .mh-list-view__card-actions {
228
+ opacity: 1;
229
+ }
230
+
231
+ .mh-list-view__card:focus-within .mh-list-view__card-actions {
232
+ opacity: 1;
233
+ }
234
+
235
+ @media (hover: none) {
236
+ .mh-list-view__card-actions {
237
+ opacity: 1;
238
+ }
239
+ }
240
+
241
+ /* ===== 固定列数档(`columns > 0`):不再按容器宽度自适应 ===== */
242
+ .mh-list-view--fixed {
243
+ grid-template-columns: repeat(var(--mh-list-view-columns, 1), minmax(0, 1fr));
244
+ }
@@ -1,76 +1,76 @@
1
- /**
2
- * Loading —— 加载态面(转圈 + 可选文案;行内 / 区域遮罩 / 全屏遮罩三形态)。
3
- *
4
- * 出处:设计稿的「正在忙」态没有独立组件,各页自绘了五花八门的遮罩与转圈
5
- * (`::after` 画环、文字符号 `...`、gif 图各有)。本件收的是**三件事**:
6
- * 转圈字形、遮罩底色、覆盖范围 —— 三者都是「改一处要全会跟着变」的口径。
7
- *
8
- * 字形归 `@manohub/icon`(`loading`),本面只负责**转**与**在哪转**:
9
- * 动画名加 `mh-` 前缀(与 toast 的 `mh-toast-spin` 同理:动画名是全局标识,防撞名)。
10
- *
11
- * 尺寸按**全局图标档**派生(`calc()` 加减,与 button.css 同款):
12
- * 改全局图标档时三档一起缩放,不会出现「转圈比旁边图标大一圈」。
13
- *
14
- * 遮罩底色由主题底色派生(`color-mix`,**不新造色值**):换主题跟着变。
15
- */
16
- .mh-loading {
17
- display: inline-flex;
18
- align-items: center;
19
- justify-content: center;
20
- gap: var(--ui-loading-gap);
21
- color: var(--ui-loading-text-color);
22
- font-size: var(--ui-font-body);
23
- line-height: var(--ui-line-body);
24
- }
25
-
26
- /* 尺寸档(按全局图标档派生,档距用 calc 表达) */
27
- .mh-loading--sm {
28
- --ui-loading-spinner-size: calc(var(--ui-font-icon) - 4px);
29
- }
30
- .mh-loading--lg {
31
- --ui-loading-spinner-size: calc(var(--ui-font-icon) + 8px);
32
- }
33
-
34
- .mh-loading__spinner {
35
- flex: none;
36
- width: var(--ui-loading-spinner-size);
37
- height: var(--ui-loading-spinner-size);
38
- /* 转圈是**提示进行中**,取主色:与语义四色(成功/警告/错误)不混 |
39
- 独立 `rotate` 属性(不碰 transform):与全库动画令牌同款约束 */
40
- color: var(--ui-primary);
41
- animation: mh-loading-spin 0.8s linear infinite;
42
- }
43
- @keyframes mh-loading-spin {
44
- to {
45
- rotate: 360deg;
46
- }
47
- }
48
- /* 降级:减弱动效时放慢而不是全停 —— 完全静止的转圈会被读成「卡住了」 */
49
- @media (prefers-reduced-motion: reduce) {
50
- .mh-loading__spinner {
51
- animation-duration: 2.4s;
52
- }
53
- }
54
-
55
- .mh-loading__text {
56
- min-width: 0;
57
- }
58
-
59
- /* ===== 区域遮罩:铺满**最近的定位祖先**(宿主需自带 position: relative)===== */
60
- .mh-loading--area {
61
- position: absolute;
62
- inset: 0;
63
- z-index: 10;
64
- background: var(--ui-loading-mask);
65
- /* 遮罩要拦住交互:光标与吞点击都是「正在忙」的表达 */
66
- cursor: wait;
67
- }
68
-
69
- /* ===== 全屏遮罩:铺满视口(层级夹在 toast 堆叠 1080 与模态 top layer 之间)===== */
70
- .mh-loading--screen {
71
- position: fixed;
72
- inset: 0;
73
- z-index: 1090;
74
- background: var(--ui-loading-mask);
75
- cursor: wait;
76
- }
1
+ /**
2
+ * Loading —— 加载态面(转圈 + 可选文案;行内 / 区域遮罩 / 全屏遮罩三形态)。
3
+ *
4
+ * 出处:设计稿的「正在忙」态没有独立组件,各页自绘了五花八门的遮罩与转圈
5
+ * (`::after` 画环、文字符号 `...`、gif 图各有)。本件收的是**三件事**:
6
+ * 转圈字形、遮罩底色、覆盖范围 —— 三者都是「改一处要全会跟着变」的口径。
7
+ *
8
+ * 字形归 `@manohub/icon`(`loading`),本面只负责**转**与**在哪转**:
9
+ * 动画名加 `mh-` 前缀(与 toast 的 `mh-toast-spin` 同理:动画名是全局标识,防撞名)。
10
+ *
11
+ * 尺寸按**全局图标档**派生(`calc()` 加减,与 button.css 同款):
12
+ * 改全局图标档时三档一起缩放,不会出现「转圈比旁边图标大一圈」。
13
+ *
14
+ * 遮罩底色由主题底色派生(`color-mix`,**不新造色值**):换主题跟着变。
15
+ */
16
+ .mh-loading {
17
+ display: inline-flex;
18
+ align-items: center;
19
+ justify-content: center;
20
+ gap: var(--ui-loading-gap);
21
+ color: var(--ui-loading-text-color);
22
+ font-size: var(--ui-font-body);
23
+ line-height: var(--ui-line-body);
24
+ }
25
+
26
+ /* 尺寸档(按全局图标档派生,档距用 calc 表达) */
27
+ .mh-loading--sm {
28
+ --ui-loading-spinner-size: calc(var(--ui-font-icon) - 4px);
29
+ }
30
+ .mh-loading--lg {
31
+ --ui-loading-spinner-size: calc(var(--ui-font-icon) + 8px);
32
+ }
33
+
34
+ .mh-loading__spinner {
35
+ flex: none;
36
+ width: var(--ui-loading-spinner-size);
37
+ height: var(--ui-loading-spinner-size);
38
+ /* 转圈是**提示进行中**,取主色:与语义四色(成功/警告/错误)不混 |
39
+ 独立 `rotate` 属性(不碰 transform):与全库动画令牌同款约束 */
40
+ color: var(--ui-primary);
41
+ animation: mh-loading-spin 0.8s linear infinite;
42
+ }
43
+ @keyframes mh-loading-spin {
44
+ to {
45
+ rotate: 360deg;
46
+ }
47
+ }
48
+ /* 降级:减弱动效时放慢而不是全停 —— 完全静止的转圈会被读成「卡住了」 */
49
+ @media (prefers-reduced-motion: reduce) {
50
+ .mh-loading__spinner {
51
+ animation-duration: 2.4s;
52
+ }
53
+ }
54
+
55
+ .mh-loading__text {
56
+ min-width: 0;
57
+ }
58
+
59
+ /* ===== 区域遮罩:铺满**最近的定位祖先**(宿主需自带 position: relative)===== */
60
+ .mh-loading--area {
61
+ position: absolute;
62
+ inset: 0;
63
+ z-index: 10;
64
+ background: var(--ui-loading-mask);
65
+ /* 遮罩要拦住交互:光标与吞点击都是「正在忙」的表达 */
66
+ cursor: wait;
67
+ }
68
+
69
+ /* ===== 全屏遮罩:铺满视口(层级夹在 toast 堆叠 1080 与模态 top layer 之间)===== */
70
+ .mh-loading--screen {
71
+ position: fixed;
72
+ inset: 0;
73
+ z-index: 1090;
74
+ background: var(--ui-loading-mask);
75
+ cursor: wait;
76
+ }