unmagic-components 0.2.0 → 0.3.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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +43 -1
- data/README.md +81 -63
- data/app/assets/tailwind/unmagic_components/engine.css +1164 -0
- data/lib/unmagic/components/action_view_helpers.rb +17 -1
- data/lib/unmagic/components/configuration.rb +8 -1
- data/lib/unmagic/components/control.rb +62 -0
- data/lib/unmagic/components/engine.rb +4 -5
- data/lib/unmagic/components/form_builder.rb +54 -6
- data/lib/unmagic/components/version.rb +1 -1
- data/lib/unmagic/components.rb +1 -0
- metadata +6 -4
- data/app/assets/stylesheets/unmagic/components.css +0 -1309
|
@@ -1,1309 +0,0 @@
|
|
|
1
|
-
/* unmagic-components
|
|
2
|
-
*
|
|
3
|
-
* Plain CSS on purpose. Tailwind only generates classes it can see and it does
|
|
4
|
-
* not scan installed gems, so any utility written inside this gem's Ruby would
|
|
5
|
-
* silently render unstyled in a host app. Owning the CSS here also means the
|
|
6
|
-
* components work in an app that doesn't use Tailwind at all.
|
|
7
|
-
*
|
|
8
|
-
* Theming is one layer of custom properties. Every value falls back to a
|
|
9
|
-
* Tailwind palette default, so the components look right with no configuration;
|
|
10
|
-
* a host overrides by setting --unmagic-* wherever its own theme is defined:
|
|
11
|
-
*
|
|
12
|
-
* :root {
|
|
13
|
-
* --unmagic-surface: var(--surface);
|
|
14
|
-
* --unmagic-border: var(--border);
|
|
15
|
-
* }
|
|
16
|
-
*
|
|
17
|
-
* Dark mode needs nothing here. Host tokens that already flip carry these with
|
|
18
|
-
* them, which is why this file declares no dark variant of its own and makes no
|
|
19
|
-
* assumption about how the host selects a theme.
|
|
20
|
-
*/
|
|
21
|
-
|
|
22
|
-
/* ------------------------------------------------------------------ Table */
|
|
23
|
-
|
|
24
|
-
/* Content-sized by default, so a Markdown table wearing this class hugs its
|
|
25
|
-
content rather than stretching. table_tag adds the --full modifier, which is
|
|
26
|
-
what an index table wants. */
|
|
27
|
-
.UnmagicTable {
|
|
28
|
-
font-size: 0.875rem;
|
|
29
|
-
line-height: 1.25rem;
|
|
30
|
-
color: var(--unmagic-text, var(--color-neutral-900, #171717));
|
|
31
|
-
background-color: var(--unmagic-surface, var(--color-white, #fff));
|
|
32
|
-
border: 1px solid var(--unmagic-border, var(--color-neutral-200, #e5e5e5));
|
|
33
|
-
border-radius: 0.75rem;
|
|
34
|
-
border-collapse: separate;
|
|
35
|
-
border-spacing: 0;
|
|
36
|
-
overflow: hidden;
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
.UnmagicTable--full {
|
|
40
|
-
width: 100%;
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
.UnmagicTable--fixed {
|
|
44
|
-
table-layout: fixed;
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
.UnmagicTable__caption {
|
|
48
|
-
position: absolute;
|
|
49
|
-
width: 1px;
|
|
50
|
-
height: 1px;
|
|
51
|
-
padding: 0;
|
|
52
|
-
margin: -1px;
|
|
53
|
-
overflow: hidden;
|
|
54
|
-
clip-path: inset(50%);
|
|
55
|
-
white-space: nowrap;
|
|
56
|
-
border-width: 0;
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
.UnmagicTable thead th {
|
|
60
|
-
padding: 0.75rem 1rem;
|
|
61
|
-
font-size: 0.75rem;
|
|
62
|
-
line-height: 1rem;
|
|
63
|
-
font-weight: 600;
|
|
64
|
-
text-align: left;
|
|
65
|
-
white-space: nowrap;
|
|
66
|
-
color: var(--unmagic-text-2, var(--color-neutral-600, #525252));
|
|
67
|
-
background-color: var(--unmagic-surface-2, var(--color-neutral-50, #fafafa));
|
|
68
|
-
border-bottom: 1px solid var(--unmagic-border, var(--color-neutral-200, #e5e5e5));
|
|
69
|
-
}
|
|
70
|
-
|
|
71
|
-
.UnmagicTable tbody td {
|
|
72
|
-
padding: 0.75rem 1rem;
|
|
73
|
-
vertical-align: middle;
|
|
74
|
-
border-bottom: 1px solid var(--unmagic-border, var(--color-neutral-200, #e5e5e5));
|
|
75
|
-
}
|
|
76
|
-
|
|
77
|
-
/* The border rides on the cells rather than the row: with border-collapse
|
|
78
|
-
separate, a border set on a <tr> is not painted. */
|
|
79
|
-
.UnmagicTable tbody tr:last-child > td {
|
|
80
|
-
border-bottom: 0;
|
|
81
|
-
}
|
|
82
|
-
|
|
83
|
-
.UnmagicTable tbody tr:hover > td {
|
|
84
|
-
background-color: var(--unmagic-hover, var(--color-neutral-50, #fafafa));
|
|
85
|
-
}
|
|
86
|
-
|
|
87
|
-
/* A row carrying a companion details row below it drops its bottom border, so
|
|
88
|
-
the pair reads as one row. */
|
|
89
|
-
.UnmagicTable tbody tr.has-details > td {
|
|
90
|
-
border-bottom: 0;
|
|
91
|
-
}
|
|
92
|
-
|
|
93
|
-
.UnmagicTable tbody tr.UnmagicTable__details > td {
|
|
94
|
-
padding-top: 0;
|
|
95
|
-
}
|
|
96
|
-
|
|
97
|
-
.UnmagicTable .is-right {
|
|
98
|
-
text-align: right;
|
|
99
|
-
}
|
|
100
|
-
|
|
101
|
-
.UnmagicTable .is-center {
|
|
102
|
-
text-align: center;
|
|
103
|
-
}
|
|
104
|
-
|
|
105
|
-
.UnmagicTable .is-numeric {
|
|
106
|
-
font-variant-numeric: tabular-nums;
|
|
107
|
-
}
|
|
108
|
-
|
|
109
|
-
.UnmagicTable__sort {
|
|
110
|
-
display: inline-flex;
|
|
111
|
-
align-items: center;
|
|
112
|
-
gap: 0.25rem;
|
|
113
|
-
color: inherit;
|
|
114
|
-
text-decoration: none;
|
|
115
|
-
}
|
|
116
|
-
|
|
117
|
-
.UnmagicTable__sort:hover {
|
|
118
|
-
color: var(--unmagic-text, var(--color-neutral-900, #171717));
|
|
119
|
-
}
|
|
120
|
-
|
|
121
|
-
/* --------------------------------------------------------------- Skeleton */
|
|
122
|
-
|
|
123
|
-
.UnmagicSkeleton {
|
|
124
|
-
position: relative;
|
|
125
|
-
height: 1rem;
|
|
126
|
-
border-radius: 0.25rem;
|
|
127
|
-
overflow: hidden;
|
|
128
|
-
background-color: var(--unmagic-skeleton, var(--color-neutral-200, #e5e5e5));
|
|
129
|
-
}
|
|
130
|
-
|
|
131
|
-
.UnmagicSkeleton.is-right {
|
|
132
|
-
margin-left: auto;
|
|
133
|
-
}
|
|
134
|
-
|
|
135
|
-
/* The shimmer is a translated ::after so it stays on the compositor; the radius
|
|
136
|
-
and sizing stay on the element itself, which clips the band to the shape. */
|
|
137
|
-
.UnmagicSkeleton::after {
|
|
138
|
-
content: "";
|
|
139
|
-
position: absolute;
|
|
140
|
-
inset: 0;
|
|
141
|
-
background-image: linear-gradient(
|
|
142
|
-
90deg,
|
|
143
|
-
transparent,
|
|
144
|
-
var(--unmagic-skeleton-shimmer, rgb(255 255 255 / 0.7)),
|
|
145
|
-
transparent
|
|
146
|
-
);
|
|
147
|
-
transform: translateX(-100%);
|
|
148
|
-
animation: unmagic-skeleton-shimmer 1.5s ease-in-out infinite;
|
|
149
|
-
}
|
|
150
|
-
|
|
151
|
-
@keyframes unmagic-skeleton-shimmer {
|
|
152
|
-
100% {
|
|
153
|
-
transform: translateX(100%);
|
|
154
|
-
}
|
|
155
|
-
}
|
|
156
|
-
|
|
157
|
-
@media (prefers-reduced-motion: reduce) {
|
|
158
|
-
.UnmagicSkeleton::after {
|
|
159
|
-
animation: none;
|
|
160
|
-
}
|
|
161
|
-
}
|
|
162
|
-
|
|
163
|
-
/* Shapes for blocking out an interface (skeleton, skeleton_text, …). Each is sized
|
|
164
|
-
from what it stands in for, so nothing moves when the real content arrives: a
|
|
165
|
-
text line takes exactly one line box of the font around it, and a button shape
|
|
166
|
-
the height of a real .UnmagicButton. Width and height set on the element win. */
|
|
167
|
-
/* Exactly one line box tall, with the thinner bar centred inside; margins around
|
|
168
|
-
the bar would collapse through its container and lose the height. */
|
|
169
|
-
.UnmagicSkeletonLine {
|
|
170
|
-
display: flex;
|
|
171
|
-
align-items: center;
|
|
172
|
-
max-width: 100%;
|
|
173
|
-
height: 1.2em;
|
|
174
|
-
height: 1lh;
|
|
175
|
-
}
|
|
176
|
-
|
|
177
|
-
.UnmagicSkeleton--text {
|
|
178
|
-
width: 100%;
|
|
179
|
-
height: 0.7em;
|
|
180
|
-
border-radius: 0.25rem;
|
|
181
|
-
}
|
|
182
|
-
|
|
183
|
-
.UnmagicSkeletonText {
|
|
184
|
-
display: block;
|
|
185
|
-
max-width: 100%;
|
|
186
|
-
}
|
|
187
|
-
|
|
188
|
-
.UnmagicSkeleton--circle {
|
|
189
|
-
display: block;
|
|
190
|
-
flex-shrink: 0;
|
|
191
|
-
border-radius: 9999px;
|
|
192
|
-
}
|
|
193
|
-
|
|
194
|
-
.UnmagicSkeleton--block {
|
|
195
|
-
display: block;
|
|
196
|
-
width: 100%;
|
|
197
|
-
max-width: 100%;
|
|
198
|
-
border-radius: 0.5rem;
|
|
199
|
-
}
|
|
200
|
-
|
|
201
|
-
/* A button's height is its vertical padding, its line height and a 1px border
|
|
202
|
-
each side; these match .UnmagicButton at each size. */
|
|
203
|
-
.UnmagicSkeleton--button {
|
|
204
|
-
display: inline-block;
|
|
205
|
-
width: 5.5rem;
|
|
206
|
-
height: calc(2rem + 2px);
|
|
207
|
-
vertical-align: middle;
|
|
208
|
-
border-radius: 0.375rem;
|
|
209
|
-
}
|
|
210
|
-
|
|
211
|
-
.UnmagicSkeleton--button.UnmagicSkeleton--small {
|
|
212
|
-
width: 4.5rem;
|
|
213
|
-
height: calc(1.5rem + 2px);
|
|
214
|
-
}
|
|
215
|
-
|
|
216
|
-
.UnmagicSkeleton--button.UnmagicSkeleton--large {
|
|
217
|
-
width: 7rem;
|
|
218
|
-
height: calc(2.75rem + 2px);
|
|
219
|
-
border-radius: 0.5rem;
|
|
220
|
-
}
|
|
221
|
-
|
|
222
|
-
/* ------------------------------------------------------------ Empty state */
|
|
223
|
-
|
|
224
|
-
.UnmagicEmptyState {
|
|
225
|
-
padding: 2rem;
|
|
226
|
-
text-align: center;
|
|
227
|
-
font-size: 0.875rem;
|
|
228
|
-
line-height: 1.25rem;
|
|
229
|
-
color: var(--unmagic-text-3, var(--color-neutral-500, #737373));
|
|
230
|
-
border: 1px dashed var(--unmagic-border-strong, var(--color-neutral-300, #d4d4d4));
|
|
231
|
-
border-radius: 0.5rem;
|
|
232
|
-
}
|
|
233
|
-
|
|
234
|
-
/* ------------------------------------------------------------- Pagination */
|
|
235
|
-
|
|
236
|
-
.UnmagicPagination {
|
|
237
|
-
display: flex;
|
|
238
|
-
align-items: center;
|
|
239
|
-
justify-content: center;
|
|
240
|
-
gap: 1rem;
|
|
241
|
-
margin-top: 1.25rem;
|
|
242
|
-
}
|
|
243
|
-
|
|
244
|
-
.UnmagicPagination__link {
|
|
245
|
-
padding: 0.25rem 0.75rem;
|
|
246
|
-
font-size: 0.875rem;
|
|
247
|
-
line-height: 1.25rem;
|
|
248
|
-
color: var(--unmagic-text, var(--color-neutral-900, #171717));
|
|
249
|
-
text-decoration: none;
|
|
250
|
-
background-color: var(--unmagic-surface, var(--color-white, #fff));
|
|
251
|
-
border: 1px solid var(--unmagic-border-strong, var(--color-neutral-300, #d4d4d4));
|
|
252
|
-
border-radius: 0.375rem;
|
|
253
|
-
}
|
|
254
|
-
|
|
255
|
-
.UnmagicPagination__link:hover {
|
|
256
|
-
background-color: var(--unmagic-hover, var(--color-neutral-50, #fafafa));
|
|
257
|
-
}
|
|
258
|
-
|
|
259
|
-
.UnmagicPagination__link[aria-disabled="true"] {
|
|
260
|
-
opacity: 0.5;
|
|
261
|
-
pointer-events: none;
|
|
262
|
-
}
|
|
263
|
-
|
|
264
|
-
/* -------------------------------------------------------- Description list */
|
|
265
|
-
|
|
266
|
-
.UnmagicDescriptionList {
|
|
267
|
-
display: grid;
|
|
268
|
-
grid-template-columns: max-content 1fr;
|
|
269
|
-
gap: 0.5rem 1.5rem;
|
|
270
|
-
font-size: 0.875rem;
|
|
271
|
-
line-height: 1.25rem;
|
|
272
|
-
}
|
|
273
|
-
|
|
274
|
-
.UnmagicDescriptionList dt {
|
|
275
|
-
grid-column: 1;
|
|
276
|
-
color: var(--unmagic-text-2, var(--color-neutral-600, #525252));
|
|
277
|
-
}
|
|
278
|
-
|
|
279
|
-
.UnmagicDescriptionList dd {
|
|
280
|
-
grid-column: 2;
|
|
281
|
-
margin: 0;
|
|
282
|
-
color: var(--unmagic-text, var(--color-neutral-900, #171717));
|
|
283
|
-
}
|
|
284
|
-
|
|
285
|
-
/* The stacked variant is a different layout, not a restyle of the inline one:
|
|
286
|
-
small caps labels above their values, in two columns once there is room. */
|
|
287
|
-
.UnmagicDescriptionList--stacked {
|
|
288
|
-
display: grid;
|
|
289
|
-
grid-template-columns: 1fr;
|
|
290
|
-
gap: 1.25rem 2rem;
|
|
291
|
-
}
|
|
292
|
-
|
|
293
|
-
@media (min-width: 40rem) {
|
|
294
|
-
.UnmagicDescriptionList--stacked {
|
|
295
|
-
grid-template-columns: repeat(2, minmax(0, 1fr));
|
|
296
|
-
}
|
|
297
|
-
|
|
298
|
-
.UnmagicDescriptionList--stacked > .is-full {
|
|
299
|
-
grid-column: span 2 / span 2;
|
|
300
|
-
}
|
|
301
|
-
}
|
|
302
|
-
|
|
303
|
-
.UnmagicDescriptionList--stacked dt {
|
|
304
|
-
grid-column: auto;
|
|
305
|
-
font-size: 0.75rem;
|
|
306
|
-
line-height: 1rem;
|
|
307
|
-
font-weight: 500;
|
|
308
|
-
text-transform: uppercase;
|
|
309
|
-
letter-spacing: 0.025em;
|
|
310
|
-
color: var(--unmagic-text-3, var(--color-neutral-400, #a3a3a3));
|
|
311
|
-
}
|
|
312
|
-
|
|
313
|
-
.UnmagicDescriptionList--stacked dd {
|
|
314
|
-
grid-column: auto;
|
|
315
|
-
margin-top: 0.25rem;
|
|
316
|
-
color: var(--unmagic-text, var(--color-neutral-900, #171717));
|
|
317
|
-
}
|
|
318
|
-
|
|
319
|
-
/* ------------------------------------------------------------------- Forms */
|
|
320
|
-
|
|
321
|
-
/* Structure only. What a control itself looks like is left to the host: apps
|
|
322
|
-
style inputs in incompatible ways — a class on every input, or a bare-element
|
|
323
|
-
rule — and picking one here would be wrong in the other. */
|
|
324
|
-
|
|
325
|
-
.UnmagicField {
|
|
326
|
-
display: flex;
|
|
327
|
-
flex-direction: column;
|
|
328
|
-
gap: 0.375rem;
|
|
329
|
-
margin-bottom: 1rem;
|
|
330
|
-
}
|
|
331
|
-
|
|
332
|
-
.UnmagicField--in-row {
|
|
333
|
-
flex: 1 1 0%;
|
|
334
|
-
margin-bottom: 0;
|
|
335
|
-
}
|
|
336
|
-
|
|
337
|
-
.UnmagicField--inline {
|
|
338
|
-
margin-bottom: 0;
|
|
339
|
-
}
|
|
340
|
-
|
|
341
|
-
.UnmagicFieldGroup {
|
|
342
|
-
display: flex;
|
|
343
|
-
flex-direction: column;
|
|
344
|
-
gap: 1rem;
|
|
345
|
-
margin-bottom: 1rem;
|
|
346
|
-
}
|
|
347
|
-
|
|
348
|
-
@media (min-width: 40rem) {
|
|
349
|
-
.UnmagicFieldGroup {
|
|
350
|
-
flex-direction: row;
|
|
351
|
-
}
|
|
352
|
-
}
|
|
353
|
-
|
|
354
|
-
.UnmagicFieldGroup--inline {
|
|
355
|
-
display: flex;
|
|
356
|
-
flex-wrap: wrap;
|
|
357
|
-
align-items: center;
|
|
358
|
-
gap: 0.5rem;
|
|
359
|
-
}
|
|
360
|
-
|
|
361
|
-
.UnmagicLabel {
|
|
362
|
-
font-size: 0.875rem;
|
|
363
|
-
font-weight: 500;
|
|
364
|
-
color: var(--unmagic-text-2, var(--color-neutral-600, #525252));
|
|
365
|
-
}
|
|
366
|
-
|
|
367
|
-
.UnmagicLabel__required {
|
|
368
|
-
color: var(--unmagic-bad, var(--color-red-500, #ef4444));
|
|
369
|
-
}
|
|
370
|
-
|
|
371
|
-
.UnmagicHint {
|
|
372
|
-
margin: 0;
|
|
373
|
-
font-size: 0.875rem;
|
|
374
|
-
color: var(--unmagic-text-3, var(--color-neutral-500, #737373));
|
|
375
|
-
}
|
|
376
|
-
|
|
377
|
-
.UnmagicError {
|
|
378
|
-
margin: 0;
|
|
379
|
-
font-size: 0.875rem;
|
|
380
|
-
color: var(--unmagic-bad, var(--color-red-600, #dc2626));
|
|
381
|
-
}
|
|
382
|
-
|
|
383
|
-
.UnmagicFormErrors {
|
|
384
|
-
margin-bottom: 1rem;
|
|
385
|
-
padding: 0.5rem 0.75rem;
|
|
386
|
-
font-size: 0.875rem;
|
|
387
|
-
border-radius: 0.375rem;
|
|
388
|
-
color: var(--unmagic-bad, var(--color-red-700, #b91c1c));
|
|
389
|
-
border: 1px solid var(--unmagic-bad-border, var(--color-red-200, #fecaca));
|
|
390
|
-
background-color: var(--unmagic-bad-surface, var(--color-red-50, #fef2f2));
|
|
391
|
-
}
|
|
392
|
-
|
|
393
|
-
.UnmagicCheckField {
|
|
394
|
-
display: flex;
|
|
395
|
-
align-items: flex-start;
|
|
396
|
-
gap: 0.75rem;
|
|
397
|
-
cursor: pointer;
|
|
398
|
-
}
|
|
399
|
-
|
|
400
|
-
.UnmagicCheckField__text {
|
|
401
|
-
display: flex;
|
|
402
|
-
flex-direction: column;
|
|
403
|
-
gap: 0.125rem;
|
|
404
|
-
}
|
|
405
|
-
|
|
406
|
-
.UnmagicCheckField__label {
|
|
407
|
-
font-size: 0.875rem;
|
|
408
|
-
font-weight: 500;
|
|
409
|
-
color: var(--unmagic-text, var(--color-neutral-900, #171717));
|
|
410
|
-
}
|
|
411
|
-
|
|
412
|
-
.UnmagicCheckList {
|
|
413
|
-
display: flex;
|
|
414
|
-
flex-direction: column;
|
|
415
|
-
gap: 0.5rem;
|
|
416
|
-
}
|
|
417
|
-
|
|
418
|
-
.UnmagicCheckList--inline {
|
|
419
|
-
display: flex;
|
|
420
|
-
flex-wrap: wrap;
|
|
421
|
-
gap: 0.5rem 1.5rem;
|
|
422
|
-
}
|
|
423
|
-
|
|
424
|
-
/* ---------------------------------------------------------------- Buttons */
|
|
425
|
-
|
|
426
|
-
/* A plain, unobtrusive button, so an unconfigured form still has one that looks
|
|
427
|
-
deliberate. Most apps point config.submit_class at their own button helper. */
|
|
428
|
-
.UnmagicButton {
|
|
429
|
-
display: inline-flex;
|
|
430
|
-
align-items: center;
|
|
431
|
-
justify-content: center;
|
|
432
|
-
gap: 0.5rem;
|
|
433
|
-
padding: 0.375rem 0.875rem;
|
|
434
|
-
font: inherit;
|
|
435
|
-
font-size: 0.875rem;
|
|
436
|
-
line-height: 1.25rem;
|
|
437
|
-
font-weight: 500;
|
|
438
|
-
white-space: nowrap;
|
|
439
|
-
text-decoration: none;
|
|
440
|
-
border-radius: 0.375rem;
|
|
441
|
-
cursor: pointer;
|
|
442
|
-
border: 1px solid var(--unmagic-border-strong, var(--color-neutral-300, #d4d4d4));
|
|
443
|
-
background-color: var(--unmagic-surface, var(--color-white, #fff));
|
|
444
|
-
color: var(--unmagic-text, var(--color-neutral-900, #171717));
|
|
445
|
-
}
|
|
446
|
-
|
|
447
|
-
.UnmagicButton:hover {
|
|
448
|
-
background-color: var(--unmagic-hover, var(--color-neutral-50, #fafafa));
|
|
449
|
-
}
|
|
450
|
-
|
|
451
|
-
.UnmagicButton:focus-visible {
|
|
452
|
-
outline: 2px solid var(--unmagic-focus, var(--color-neutral-400, #a3a3a3));
|
|
453
|
-
outline-offset: 2px;
|
|
454
|
-
}
|
|
455
|
-
|
|
456
|
-
.UnmagicButton:disabled,
|
|
457
|
-
.UnmagicButton[aria-disabled="true"] {
|
|
458
|
-
opacity: 0.5;
|
|
459
|
-
pointer-events: none;
|
|
460
|
-
}
|
|
461
|
-
|
|
462
|
-
.UnmagicButton--primary {
|
|
463
|
-
border-color: transparent;
|
|
464
|
-
background-color: var(--unmagic-accent, var(--color-neutral-900, #171717));
|
|
465
|
-
color: var(--unmagic-on-accent, var(--color-white, #fff));
|
|
466
|
-
}
|
|
467
|
-
|
|
468
|
-
.UnmagicButton--primary:hover {
|
|
469
|
-
background-color: var(--unmagic-accent, var(--color-neutral-900, #171717));
|
|
470
|
-
opacity: 0.9;
|
|
471
|
-
}
|
|
472
|
-
|
|
473
|
-
.UnmagicButton--ghost {
|
|
474
|
-
border-color: transparent;
|
|
475
|
-
background-color: transparent;
|
|
476
|
-
}
|
|
477
|
-
|
|
478
|
-
/* Styled like the default so the two sit level in an actions row; only the label
|
|
479
|
-
and the hover carry the warning. */
|
|
480
|
-
.UnmagicButton--danger {
|
|
481
|
-
color: var(--unmagic-bad, var(--color-red-600, #dc2626));
|
|
482
|
-
}
|
|
483
|
-
|
|
484
|
-
.UnmagicButton--danger:hover {
|
|
485
|
-
background-color: var(--unmagic-bad-surface, var(--color-red-50, #fef2f2));
|
|
486
|
-
}
|
|
487
|
-
|
|
488
|
-
.UnmagicButton--icon {
|
|
489
|
-
padding: 0.375rem;
|
|
490
|
-
border-color: transparent;
|
|
491
|
-
background-color: transparent;
|
|
492
|
-
color: var(--unmagic-text-3, var(--color-neutral-500, #737373));
|
|
493
|
-
}
|
|
494
|
-
|
|
495
|
-
.UnmagicButton--icon:hover {
|
|
496
|
-
color: var(--unmagic-text, var(--color-neutral-900, #171717));
|
|
497
|
-
}
|
|
498
|
-
|
|
499
|
-
.UnmagicButton--small {
|
|
500
|
-
padding: 0.25rem 0.625rem;
|
|
501
|
-
font-size: 0.75rem;
|
|
502
|
-
line-height: 1rem;
|
|
503
|
-
}
|
|
504
|
-
|
|
505
|
-
.UnmagicButton--large {
|
|
506
|
-
padding: 0.625rem 1.25rem;
|
|
507
|
-
font-size: 1rem;
|
|
508
|
-
line-height: 1.5rem;
|
|
509
|
-
border-radius: 0.5rem;
|
|
510
|
-
}
|
|
511
|
-
|
|
512
|
-
/* ------------------------------------------------------------------ Icons */
|
|
513
|
-
|
|
514
|
-
.UnmagicIcon {
|
|
515
|
-
width: 1rem;
|
|
516
|
-
height: 1rem;
|
|
517
|
-
flex-shrink: 0;
|
|
518
|
-
}
|
|
519
|
-
|
|
520
|
-
.UnmagicVisuallyHidden {
|
|
521
|
-
position: absolute;
|
|
522
|
-
width: 1px;
|
|
523
|
-
height: 1px;
|
|
524
|
-
padding: 0;
|
|
525
|
-
margin: -1px;
|
|
526
|
-
overflow: hidden;
|
|
527
|
-
clip-path: inset(50%);
|
|
528
|
-
white-space: nowrap;
|
|
529
|
-
border-width: 0;
|
|
530
|
-
}
|
|
531
|
-
|
|
532
|
-
/* ---------------------------------------------------------------- Dialogs */
|
|
533
|
-
|
|
534
|
-
/* The <dialog> itself is only a transparent positioning box; the panel inside is
|
|
535
|
-
the visible surface. overflow stays visible so a dropdown inside a dialog form
|
|
536
|
-
isn't clipped, which means a dialog keeps its content short enough to fit. */
|
|
537
|
-
.UnmagicDialogBox {
|
|
538
|
-
margin: auto;
|
|
539
|
-
padding: 0;
|
|
540
|
-
max-width: calc(100vw - 2rem);
|
|
541
|
-
max-height: 90dvh;
|
|
542
|
-
overflow: visible;
|
|
543
|
-
color: inherit;
|
|
544
|
-
background: transparent;
|
|
545
|
-
border: 0;
|
|
546
|
-
}
|
|
547
|
-
|
|
548
|
-
.UnmagicDialogBox:focus {
|
|
549
|
-
outline: none;
|
|
550
|
-
}
|
|
551
|
-
|
|
552
|
-
.UnmagicDialogBox::backdrop {
|
|
553
|
-
background-color: var(--unmagic-backdrop, rgb(0 0 0 / 0.45));
|
|
554
|
-
backdrop-filter: blur(4px);
|
|
555
|
-
}
|
|
556
|
-
|
|
557
|
-
.UnmagicDialogBox[open] {
|
|
558
|
-
animation: unmagic-dialog-in 150ms ease-out;
|
|
559
|
-
}
|
|
560
|
-
|
|
561
|
-
@keyframes unmagic-dialog-in {
|
|
562
|
-
from {
|
|
563
|
-
opacity: 0;
|
|
564
|
-
transform: translateY(0.5rem) scale(0.98);
|
|
565
|
-
}
|
|
566
|
-
}
|
|
567
|
-
|
|
568
|
-
@media (prefers-reduced-motion: reduce) {
|
|
569
|
-
.UnmagicDialogBox[open] {
|
|
570
|
-
animation: none;
|
|
571
|
-
}
|
|
572
|
-
}
|
|
573
|
-
|
|
574
|
-
.UnmagicDialog {
|
|
575
|
-
width: min(100vw - 2rem, 32rem);
|
|
576
|
-
font-size: 0.875rem;
|
|
577
|
-
line-height: 1.5;
|
|
578
|
-
color: var(--unmagic-text, var(--color-neutral-900, #171717));
|
|
579
|
-
background-color: var(--unmagic-surface, var(--color-white, #fff));
|
|
580
|
-
border: 1px solid var(--unmagic-border, var(--color-neutral-200, #e5e5e5));
|
|
581
|
-
border-radius: 0.75rem;
|
|
582
|
-
box-shadow: 0 20px 25px -5px rgb(0 0 0 / 0.1), 0 8px 10px -6px rgb(0 0 0 / 0.1);
|
|
583
|
-
}
|
|
584
|
-
|
|
585
|
-
.UnmagicDialog--wide {
|
|
586
|
-
width: min(100vw - 2rem, 48rem);
|
|
587
|
-
}
|
|
588
|
-
|
|
589
|
-
/* margin is reset because this is a <header>, and hosts often style bare
|
|
590
|
-
header elements for their page chrome. */
|
|
591
|
-
.UnmagicDialog__header {
|
|
592
|
-
display: flex;
|
|
593
|
-
align-items: center;
|
|
594
|
-
justify-content: space-between;
|
|
595
|
-
gap: 0.75rem;
|
|
596
|
-
margin: 0;
|
|
597
|
-
padding: 1rem 1.25rem 0.5rem;
|
|
598
|
-
}
|
|
599
|
-
|
|
600
|
-
.UnmagicDialog__title {
|
|
601
|
-
margin: 0;
|
|
602
|
-
font-size: 1rem;
|
|
603
|
-
line-height: 1.5rem;
|
|
604
|
-
font-weight: 600;
|
|
605
|
-
}
|
|
606
|
-
|
|
607
|
-
/* Pushed right even when the panel has no title beside it. */
|
|
608
|
-
.UnmagicDialog__close {
|
|
609
|
-
margin-left: auto;
|
|
610
|
-
margin-right: -0.375rem;
|
|
611
|
-
}
|
|
612
|
-
|
|
613
|
-
.UnmagicDialog__body {
|
|
614
|
-
padding: 1rem 1.25rem;
|
|
615
|
-
}
|
|
616
|
-
|
|
617
|
-
.UnmagicDialog__body > :first-child {
|
|
618
|
-
margin-top: 0;
|
|
619
|
-
}
|
|
620
|
-
|
|
621
|
-
.UnmagicDialog__body > :last-child {
|
|
622
|
-
margin-bottom: 0;
|
|
623
|
-
}
|
|
624
|
-
|
|
625
|
-
.UnmagicDialog__footer {
|
|
626
|
-
display: flex;
|
|
627
|
-
align-items: center;
|
|
628
|
-
justify-content: flex-end;
|
|
629
|
-
gap: 0.75rem;
|
|
630
|
-
padding: 0.5rem 1.25rem 1rem;
|
|
631
|
-
}
|
|
632
|
-
|
|
633
|
-
.UnmagicDialog__error {
|
|
634
|
-
display: flex;
|
|
635
|
-
align-items: flex-start;
|
|
636
|
-
gap: 0.75rem;
|
|
637
|
-
color: var(--unmagic-text-2, var(--color-neutral-600, #525252));
|
|
638
|
-
}
|
|
639
|
-
|
|
640
|
-
.UnmagicDialog__error > .UnmagicIcon {
|
|
641
|
-
margin-top: 0.125rem;
|
|
642
|
-
color: var(--unmagic-bad, var(--color-red-500, #ef4444));
|
|
643
|
-
}
|
|
644
|
-
|
|
645
|
-
.UnmagicDialog__error > p {
|
|
646
|
-
margin: 0;
|
|
647
|
-
}
|
|
648
|
-
|
|
649
|
-
.UnmagicDialog__skeleton-field {
|
|
650
|
-
display: grid;
|
|
651
|
-
gap: 0.5rem;
|
|
652
|
-
margin-bottom: 1.25rem;
|
|
653
|
-
}
|
|
654
|
-
|
|
655
|
-
.UnmagicDialog__skeleton-title {
|
|
656
|
-
width: 10rem;
|
|
657
|
-
height: 1.25rem;
|
|
658
|
-
}
|
|
659
|
-
|
|
660
|
-
.UnmagicDialog__skeleton-label {
|
|
661
|
-
width: 6rem;
|
|
662
|
-
height: 0.75rem;
|
|
663
|
-
}
|
|
664
|
-
|
|
665
|
-
.UnmagicDialog__skeleton-input {
|
|
666
|
-
height: 2.25rem;
|
|
667
|
-
border-radius: 0.375rem;
|
|
668
|
-
}
|
|
669
|
-
|
|
670
|
-
.UnmagicDialog__skeleton-button {
|
|
671
|
-
width: 6rem;
|
|
672
|
-
height: 2.25rem;
|
|
673
|
-
border-radius: 0.375rem;
|
|
674
|
-
}
|
|
675
|
-
|
|
676
|
-
/* ----------------------------------------------------------------- Toasts */
|
|
677
|
-
|
|
678
|
-
/* The stack is a manual popover, so the popover defaults (centred, bordered,
|
|
679
|
-
painted) are undone here. It never takes pointer events itself; the toasts
|
|
680
|
-
inside it do. */
|
|
681
|
-
.UnmagicToasts__stack {
|
|
682
|
-
position: fixed;
|
|
683
|
-
inset: 1rem 1rem auto auto;
|
|
684
|
-
z-index: 60;
|
|
685
|
-
display: flex;
|
|
686
|
-
flex-direction: column;
|
|
687
|
-
gap: 0.5rem;
|
|
688
|
-
width: min(100vw - 2rem, 24rem);
|
|
689
|
-
margin: 0;
|
|
690
|
-
padding: 0;
|
|
691
|
-
overflow: visible;
|
|
692
|
-
color: inherit;
|
|
693
|
-
background: transparent;
|
|
694
|
-
border: 0;
|
|
695
|
-
pointer-events: none;
|
|
696
|
-
}
|
|
697
|
-
|
|
698
|
-
.UnmagicToast {
|
|
699
|
-
display: flex;
|
|
700
|
-
align-items: flex-start;
|
|
701
|
-
gap: 0.5rem;
|
|
702
|
-
padding: 0.625rem 0.75rem;
|
|
703
|
-
font-size: 0.875rem;
|
|
704
|
-
line-height: 1.25rem;
|
|
705
|
-
color: var(--unmagic-text, var(--color-neutral-900, #171717));
|
|
706
|
-
background-color: var(--unmagic-surface, var(--color-white, #fff));
|
|
707
|
-
border: 1px solid var(--unmagic-border, var(--color-neutral-200, #e5e5e5));
|
|
708
|
-
border-radius: 0.5rem;
|
|
709
|
-
box-shadow: 0 10px 15px -3px rgb(0 0 0 / 0.1), 0 4px 6px -4px rgb(0 0 0 / 0.1);
|
|
710
|
-
pointer-events: auto;
|
|
711
|
-
opacity: 0;
|
|
712
|
-
transform: translateY(-0.5rem);
|
|
713
|
-
transition: opacity 200ms ease, transform 200ms ease;
|
|
714
|
-
}
|
|
715
|
-
|
|
716
|
-
.UnmagicToast[data-open] {
|
|
717
|
-
opacity: 1;
|
|
718
|
-
transform: none;
|
|
719
|
-
}
|
|
720
|
-
|
|
721
|
-
@media (prefers-reduced-motion: reduce) {
|
|
722
|
-
.UnmagicToast {
|
|
723
|
-
transform: none;
|
|
724
|
-
transition: none;
|
|
725
|
-
}
|
|
726
|
-
}
|
|
727
|
-
|
|
728
|
-
.UnmagicToast__icon {
|
|
729
|
-
margin-top: 0.125rem;
|
|
730
|
-
}
|
|
731
|
-
|
|
732
|
-
.UnmagicToast__message {
|
|
733
|
-
flex: 1 1 auto;
|
|
734
|
-
min-width: 0;
|
|
735
|
-
overflow-wrap: anywhere;
|
|
736
|
-
}
|
|
737
|
-
|
|
738
|
-
.UnmagicToast__dismiss {
|
|
739
|
-
display: inline-flex;
|
|
740
|
-
flex-shrink: 0;
|
|
741
|
-
margin: -0.125rem -0.25rem -0.125rem 0;
|
|
742
|
-
padding: 0.25rem;
|
|
743
|
-
color: inherit;
|
|
744
|
-
background: transparent;
|
|
745
|
-
border: 0;
|
|
746
|
-
border-radius: 0.25rem;
|
|
747
|
-
opacity: 0.6;
|
|
748
|
-
cursor: pointer;
|
|
749
|
-
}
|
|
750
|
-
|
|
751
|
-
.UnmagicToast__dismiss:hover,
|
|
752
|
-
.UnmagicToast__dismiss:focus-visible {
|
|
753
|
-
opacity: 1;
|
|
754
|
-
}
|
|
755
|
-
|
|
756
|
-
.UnmagicToast__dismiss .UnmagicIcon {
|
|
757
|
-
width: 0.875rem;
|
|
758
|
-
height: 0.875rem;
|
|
759
|
-
}
|
|
760
|
-
|
|
761
|
-
.UnmagicToast--good {
|
|
762
|
-
color: var(--unmagic-good, var(--color-green-700, #15803d));
|
|
763
|
-
background-color: var(--unmagic-good-surface, var(--color-green-50, #f0fdf4));
|
|
764
|
-
border-color: var(--unmagic-good-border, var(--color-green-200, #bbf7d0));
|
|
765
|
-
}
|
|
766
|
-
|
|
767
|
-
.UnmagicToast--warn {
|
|
768
|
-
color: var(--unmagic-warn, var(--color-amber-700, #b45309));
|
|
769
|
-
background-color: var(--unmagic-warn-surface, var(--color-amber-50, #fffbeb));
|
|
770
|
-
border-color: var(--unmagic-warn-border, var(--color-amber-200, #fde68a));
|
|
771
|
-
}
|
|
772
|
-
|
|
773
|
-
.UnmagicToast--bad {
|
|
774
|
-
color: var(--unmagic-bad, var(--color-red-700, #b91c1c));
|
|
775
|
-
background-color: var(--unmagic-bad-surface, var(--color-red-50, #fef2f2));
|
|
776
|
-
border-color: var(--unmagic-bad-border, var(--color-red-200, #fecaca));
|
|
777
|
-
}
|
|
778
|
-
|
|
779
|
-
.UnmagicToast--info .UnmagicToast__icon {
|
|
780
|
-
color: var(--unmagic-text-3, var(--color-neutral-500, #737373));
|
|
781
|
-
}
|
|
782
|
-
|
|
783
|
-
/* ----------------------------------------------------------------- Badges */
|
|
784
|
-
|
|
785
|
-
.UnmagicBadge {
|
|
786
|
-
display: inline-flex;
|
|
787
|
-
align-items: center;
|
|
788
|
-
gap: 0.25rem;
|
|
789
|
-
padding: 0.125rem 0.5rem;
|
|
790
|
-
font-size: 0.75rem;
|
|
791
|
-
line-height: 1rem;
|
|
792
|
-
font-weight: 500;
|
|
793
|
-
white-space: nowrap;
|
|
794
|
-
color: var(--unmagic-text-2, var(--color-neutral-600, #525252));
|
|
795
|
-
background-color: var(--unmagic-surface-3, var(--color-neutral-100, #f5f5f5));
|
|
796
|
-
border-radius: 9999px;
|
|
797
|
-
}
|
|
798
|
-
|
|
799
|
-
.UnmagicBadge--good {
|
|
800
|
-
color: var(--unmagic-good, var(--color-green-700, #15803d));
|
|
801
|
-
background-color: var(--unmagic-good-surface, var(--color-green-50, #f0fdf4));
|
|
802
|
-
}
|
|
803
|
-
|
|
804
|
-
.UnmagicBadge--warn {
|
|
805
|
-
color: var(--unmagic-warn, var(--color-amber-700, #b45309));
|
|
806
|
-
background-color: var(--unmagic-warn-surface, var(--color-amber-50, #fffbeb));
|
|
807
|
-
}
|
|
808
|
-
|
|
809
|
-
.UnmagicBadge--bad {
|
|
810
|
-
color: var(--unmagic-bad, var(--color-red-700, #b91c1c));
|
|
811
|
-
background-color: var(--unmagic-bad-surface, var(--color-red-50, #fef2f2));
|
|
812
|
-
}
|
|
813
|
-
|
|
814
|
-
/* Neutral, but outlined, so it reads as a note rather than a state. */
|
|
815
|
-
.UnmagicBadge--info {
|
|
816
|
-
background-color: transparent;
|
|
817
|
-
box-shadow: inset 0 0 0 1px var(--unmagic-border-strong, var(--color-neutral-300, #d4d4d4));
|
|
818
|
-
}
|
|
819
|
-
|
|
820
|
-
.UnmagicBadge--accent {
|
|
821
|
-
color: var(--unmagic-on-accent, var(--color-white, #fff));
|
|
822
|
-
background-color: var(--unmagic-accent, var(--color-neutral-900, #171717));
|
|
823
|
-
}
|
|
824
|
-
|
|
825
|
-
/* ------------------------------------------------------------------ Cards */
|
|
826
|
-
|
|
827
|
-
/* No overflow: hidden, so a dropdown inside a card isn't clipped; the footer
|
|
828
|
-
rounds its own corners instead. A column whose body grows, so a card stretched
|
|
829
|
-
to its row's height in a grid keeps its footer on the bottom edge. */
|
|
830
|
-
.UnmagicCard {
|
|
831
|
-
display: flex;
|
|
832
|
-
flex-direction: column;
|
|
833
|
-
color: var(--unmagic-text, var(--color-neutral-900, #171717));
|
|
834
|
-
background-color: var(--unmagic-surface, var(--color-white, #fff));
|
|
835
|
-
border: 1px solid var(--unmagic-border, var(--color-neutral-200, #e5e5e5));
|
|
836
|
-
border-radius: 0.75rem;
|
|
837
|
-
}
|
|
838
|
-
|
|
839
|
-
.UnmagicCard--link {
|
|
840
|
-
text-decoration: none;
|
|
841
|
-
transition: border-color 150ms ease, box-shadow 150ms ease;
|
|
842
|
-
}
|
|
843
|
-
|
|
844
|
-
.UnmagicCard--link:hover {
|
|
845
|
-
border-color: var(--unmagic-border-strong, var(--color-neutral-300, #d4d4d4));
|
|
846
|
-
box-shadow: 0 1px 3px 0 rgb(0 0 0 / 0.08);
|
|
847
|
-
}
|
|
848
|
-
|
|
849
|
-
.UnmagicCard--link:focus-visible {
|
|
850
|
-
outline: 2px solid var(--unmagic-focus, var(--color-neutral-400, #a3a3a3));
|
|
851
|
-
outline-offset: 2px;
|
|
852
|
-
}
|
|
853
|
-
|
|
854
|
-
.UnmagicCard__header {
|
|
855
|
-
display: flex;
|
|
856
|
-
align-items: center;
|
|
857
|
-
justify-content: space-between;
|
|
858
|
-
gap: 0.75rem;
|
|
859
|
-
margin: 0;
|
|
860
|
-
padding: 1rem 1rem 0;
|
|
861
|
-
}
|
|
862
|
-
|
|
863
|
-
.UnmagicCard__title {
|
|
864
|
-
margin: 0;
|
|
865
|
-
font-size: 1rem;
|
|
866
|
-
line-height: 1.5rem;
|
|
867
|
-
font-weight: 600;
|
|
868
|
-
}
|
|
869
|
-
|
|
870
|
-
.UnmagicCard__actions {
|
|
871
|
-
display: flex;
|
|
872
|
-
align-items: center;
|
|
873
|
-
gap: 0.5rem;
|
|
874
|
-
margin-left: auto;
|
|
875
|
-
}
|
|
876
|
-
|
|
877
|
-
.UnmagicCard__body {
|
|
878
|
-
flex: 1 1 auto;
|
|
879
|
-
padding: 1rem;
|
|
880
|
-
font-size: 0.875rem;
|
|
881
|
-
line-height: 1.5;
|
|
882
|
-
}
|
|
883
|
-
|
|
884
|
-
.UnmagicCard__body--flush {
|
|
885
|
-
padding: 0;
|
|
886
|
-
}
|
|
887
|
-
|
|
888
|
-
.UnmagicCard__header + .UnmagicCard__body--flush {
|
|
889
|
-
margin-top: 1rem;
|
|
890
|
-
}
|
|
891
|
-
|
|
892
|
-
/* A table in a flush card borrows the card's edge rather than drawing its own. */
|
|
893
|
-
.UnmagicCard__body--flush > .UnmagicTable {
|
|
894
|
-
border: 0;
|
|
895
|
-
border-radius: 0;
|
|
896
|
-
}
|
|
897
|
-
|
|
898
|
-
.UnmagicCard__footer {
|
|
899
|
-
display: flex;
|
|
900
|
-
align-items: center;
|
|
901
|
-
justify-content: flex-end;
|
|
902
|
-
gap: 0.75rem;
|
|
903
|
-
padding: 0.75rem 1rem;
|
|
904
|
-
font-size: 0.875rem;
|
|
905
|
-
color: var(--unmagic-text-2, var(--color-neutral-600, #525252));
|
|
906
|
-
background-color: var(--unmagic-surface-2, var(--color-neutral-50, #fafafa));
|
|
907
|
-
border-top: 1px solid var(--unmagic-border, var(--color-neutral-200, #e5e5e5));
|
|
908
|
-
border-radius: 0 0 calc(0.75rem - 1px) calc(0.75rem - 1px);
|
|
909
|
-
}
|
|
910
|
-
|
|
911
|
-
/* ----------------------------------------------------------- Page headers */
|
|
912
|
-
|
|
913
|
-
.UnmagicPageHeader {
|
|
914
|
-
margin: 0 0 1.5rem;
|
|
915
|
-
padding: 0;
|
|
916
|
-
}
|
|
917
|
-
|
|
918
|
-
.UnmagicPageHeader__back {
|
|
919
|
-
display: inline-flex;
|
|
920
|
-
align-items: center;
|
|
921
|
-
gap: 0.25rem;
|
|
922
|
-
margin-bottom: 0.5rem;
|
|
923
|
-
font-size: 0.875rem;
|
|
924
|
-
color: var(--unmagic-text-3, var(--color-neutral-500, #737373));
|
|
925
|
-
text-decoration: none;
|
|
926
|
-
}
|
|
927
|
-
|
|
928
|
-
.UnmagicPageHeader__back:hover {
|
|
929
|
-
color: var(--unmagic-text, var(--color-neutral-900, #171717));
|
|
930
|
-
}
|
|
931
|
-
|
|
932
|
-
/* The title column shrinks and wraps, so a long description sits beside the
|
|
933
|
-
actions rather than pushing them onto a row of their own — until there's no
|
|
934
|
-
room, when the actions drop below. */
|
|
935
|
-
.UnmagicPageHeader__row {
|
|
936
|
-
display: flex;
|
|
937
|
-
flex-wrap: wrap;
|
|
938
|
-
align-items: flex-start;
|
|
939
|
-
justify-content: space-between;
|
|
940
|
-
gap: 1rem;
|
|
941
|
-
}
|
|
942
|
-
|
|
943
|
-
.UnmagicPageHeader__main {
|
|
944
|
-
flex: 1 1 20rem;
|
|
945
|
-
min-width: 0;
|
|
946
|
-
}
|
|
947
|
-
|
|
948
|
-
.UnmagicPageHeader__heading {
|
|
949
|
-
display: flex;
|
|
950
|
-
flex-wrap: wrap;
|
|
951
|
-
align-items: center;
|
|
952
|
-
gap: 0.75rem;
|
|
953
|
-
}
|
|
954
|
-
|
|
955
|
-
.UnmagicPageHeader__title {
|
|
956
|
-
margin: 0;
|
|
957
|
-
font-size: 1.5rem;
|
|
958
|
-
line-height: 2rem;
|
|
959
|
-
font-weight: 600;
|
|
960
|
-
letter-spacing: -0.01em;
|
|
961
|
-
color: var(--unmagic-text, var(--color-neutral-900, #171717));
|
|
962
|
-
}
|
|
963
|
-
|
|
964
|
-
.UnmagicPageHeader__description {
|
|
965
|
-
max-width: 42rem;
|
|
966
|
-
margin-top: 0.25rem;
|
|
967
|
-
font-size: 0.875rem;
|
|
968
|
-
line-height: 1.5;
|
|
969
|
-
color: var(--unmagic-text-3, var(--color-neutral-500, #737373));
|
|
970
|
-
}
|
|
971
|
-
|
|
972
|
-
.UnmagicPageHeader__actions {
|
|
973
|
-
display: flex;
|
|
974
|
-
flex-shrink: 0;
|
|
975
|
-
align-items: center;
|
|
976
|
-
gap: 0.75rem;
|
|
977
|
-
}
|
|
978
|
-
|
|
979
|
-
/* --------------------------------------------------------------- Callouts */
|
|
980
|
-
|
|
981
|
-
.UnmagicCallout {
|
|
982
|
-
display: flex;
|
|
983
|
-
align-items: flex-start;
|
|
984
|
-
gap: 0.75rem;
|
|
985
|
-
padding: 1rem;
|
|
986
|
-
font-size: 0.875rem;
|
|
987
|
-
line-height: 1.5;
|
|
988
|
-
color: var(--unmagic-text-2, var(--color-neutral-600, #525252));
|
|
989
|
-
border: 1px solid var(--unmagic-border, var(--color-neutral-200, #e5e5e5));
|
|
990
|
-
border-radius: 0.5rem;
|
|
991
|
-
}
|
|
992
|
-
|
|
993
|
-
.UnmagicCallout__icon {
|
|
994
|
-
margin-top: 0.125rem;
|
|
995
|
-
}
|
|
996
|
-
|
|
997
|
-
.UnmagicCallout__content {
|
|
998
|
-
flex: 1 1 auto;
|
|
999
|
-
min-width: 0;
|
|
1000
|
-
}
|
|
1001
|
-
|
|
1002
|
-
.UnmagicCallout__heading {
|
|
1003
|
-
display: flex;
|
|
1004
|
-
flex-wrap: wrap;
|
|
1005
|
-
align-items: center;
|
|
1006
|
-
gap: 0.5rem;
|
|
1007
|
-
margin-bottom: 0.25rem;
|
|
1008
|
-
}
|
|
1009
|
-
|
|
1010
|
-
.UnmagicCallout__title {
|
|
1011
|
-
margin: 0;
|
|
1012
|
-
font-weight: 600;
|
|
1013
|
-
color: var(--unmagic-text, var(--color-neutral-900, #171717));
|
|
1014
|
-
}
|
|
1015
|
-
|
|
1016
|
-
.UnmagicCallout__body > :first-child {
|
|
1017
|
-
margin-top: 0;
|
|
1018
|
-
}
|
|
1019
|
-
|
|
1020
|
-
.UnmagicCallout__body > :last-child {
|
|
1021
|
-
margin-bottom: 0;
|
|
1022
|
-
}
|
|
1023
|
-
|
|
1024
|
-
.UnmagicCallout--good {
|
|
1025
|
-
background-color: var(--unmagic-good-surface, var(--color-green-50, #f0fdf4));
|
|
1026
|
-
border-color: var(--unmagic-good-border, var(--color-green-200, #bbf7d0));
|
|
1027
|
-
}
|
|
1028
|
-
|
|
1029
|
-
.UnmagicCallout--good .UnmagicCallout__icon {
|
|
1030
|
-
color: var(--unmagic-good, var(--color-green-700, #15803d));
|
|
1031
|
-
}
|
|
1032
|
-
|
|
1033
|
-
.UnmagicCallout--warn {
|
|
1034
|
-
background-color: var(--unmagic-warn-surface, var(--color-amber-50, #fffbeb));
|
|
1035
|
-
border-color: var(--unmagic-warn-border, var(--color-amber-200, #fde68a));
|
|
1036
|
-
}
|
|
1037
|
-
|
|
1038
|
-
.UnmagicCallout--warn .UnmagicCallout__icon {
|
|
1039
|
-
color: var(--unmagic-warn, var(--color-amber-700, #b45309));
|
|
1040
|
-
}
|
|
1041
|
-
|
|
1042
|
-
.UnmagicCallout--bad {
|
|
1043
|
-
background-color: var(--unmagic-bad-surface, var(--color-red-50, #fef2f2));
|
|
1044
|
-
border-color: var(--unmagic-bad-border, var(--color-red-200, #fecaca));
|
|
1045
|
-
}
|
|
1046
|
-
|
|
1047
|
-
.UnmagicCallout--bad .UnmagicCallout__icon {
|
|
1048
|
-
color: var(--unmagic-bad, var(--color-red-700, #b91c1c));
|
|
1049
|
-
}
|
|
1050
|
-
|
|
1051
|
-
.UnmagicCallout--info {
|
|
1052
|
-
background-color: var(--unmagic-surface-2, var(--color-neutral-50, #fafafa));
|
|
1053
|
-
}
|
|
1054
|
-
|
|
1055
|
-
.UnmagicCallout--info .UnmagicCallout__icon {
|
|
1056
|
-
color: var(--unmagic-text-3, var(--color-neutral-500, #737373));
|
|
1057
|
-
}
|
|
1058
|
-
|
|
1059
|
-
/* --------------------------------------------------------------- Tooltips */
|
|
1060
|
-
|
|
1061
|
-
/* A term explains itself, so it looks like one before the script upgrades it. */
|
|
1062
|
-
.UnmagicTooltip--term {
|
|
1063
|
-
text-decoration: underline dashed;
|
|
1064
|
-
text-decoration-color: var(--unmagic-text-3, var(--color-neutral-500, #737373));
|
|
1065
|
-
text-underline-offset: 0.2em;
|
|
1066
|
-
cursor: help;
|
|
1067
|
-
}
|
|
1068
|
-
|
|
1069
|
-
.UnmagicTooltip--term:focus-visible {
|
|
1070
|
-
outline: 2px solid var(--unmagic-focus, var(--color-neutral-400, #a3a3a3));
|
|
1071
|
-
outline-offset: 2px;
|
|
1072
|
-
border-radius: 2px;
|
|
1073
|
-
}
|
|
1074
|
-
|
|
1075
|
-
/* A manual popover, placed by the element; the popover defaults are undone and
|
|
1076
|
-
the host's type styles reset, since the hint inherits from wherever it sits. */
|
|
1077
|
-
.UnmagicTooltip__popup {
|
|
1078
|
-
position: fixed;
|
|
1079
|
-
inset: auto;
|
|
1080
|
-
width: max-content;
|
|
1081
|
-
max-width: min(20rem, calc(100vw - 1rem));
|
|
1082
|
-
margin: 0;
|
|
1083
|
-
padding: 0.375rem 0.625rem;
|
|
1084
|
-
font-size: 0.75rem;
|
|
1085
|
-
line-height: 1.4;
|
|
1086
|
-
font-weight: 400;
|
|
1087
|
-
font-style: normal;
|
|
1088
|
-
letter-spacing: normal;
|
|
1089
|
-
text-align: left;
|
|
1090
|
-
text-transform: none;
|
|
1091
|
-
white-space: normal;
|
|
1092
|
-
color: var(--unmagic-on-tooltip, var(--color-white, #fff));
|
|
1093
|
-
background-color: var(--unmagic-tooltip, var(--color-neutral-900, #171717));
|
|
1094
|
-
border: 0;
|
|
1095
|
-
border-radius: 0.375rem;
|
|
1096
|
-
box-shadow: 0 4px 6px -1px rgb(0 0 0 / 0.1), 0 2px 4px -2px rgb(0 0 0 / 0.1);
|
|
1097
|
-
opacity: 0;
|
|
1098
|
-
pointer-events: none;
|
|
1099
|
-
transition: opacity 100ms ease;
|
|
1100
|
-
}
|
|
1101
|
-
|
|
1102
|
-
.UnmagicTooltip__popup[data-open] {
|
|
1103
|
-
opacity: 1;
|
|
1104
|
-
}
|
|
1105
|
-
|
|
1106
|
-
@media (prefers-reduced-motion: reduce) {
|
|
1107
|
-
.UnmagicTooltip__popup {
|
|
1108
|
-
transition: none;
|
|
1109
|
-
}
|
|
1110
|
-
}
|
|
1111
|
-
|
|
1112
|
-
/* ------------------------------------------------------------------ Menus */
|
|
1113
|
-
|
|
1114
|
-
.UnmagicMenu {
|
|
1115
|
-
position: relative;
|
|
1116
|
-
display: inline-block;
|
|
1117
|
-
}
|
|
1118
|
-
|
|
1119
|
-
.UnmagicMenu__trigger {
|
|
1120
|
-
list-style: none;
|
|
1121
|
-
}
|
|
1122
|
-
|
|
1123
|
-
.UnmagicMenu__trigger::-webkit-details-marker {
|
|
1124
|
-
display: none;
|
|
1125
|
-
}
|
|
1126
|
-
|
|
1127
|
-
.UnmagicMenu__panel {
|
|
1128
|
-
position: absolute;
|
|
1129
|
-
top: calc(100% + 0.25rem);
|
|
1130
|
-
z-index: 50;
|
|
1131
|
-
display: flex;
|
|
1132
|
-
flex-direction: column;
|
|
1133
|
-
min-width: 11rem;
|
|
1134
|
-
padding: 0.25rem;
|
|
1135
|
-
background-color: var(--unmagic-surface, var(--color-white, #fff));
|
|
1136
|
-
border: 1px solid var(--unmagic-border, var(--color-neutral-200, #e5e5e5));
|
|
1137
|
-
border-radius: 0.5rem;
|
|
1138
|
-
box-shadow: 0 10px 15px -3px rgb(0 0 0 / 0.1), 0 4px 6px -4px rgb(0 0 0 / 0.1);
|
|
1139
|
-
}
|
|
1140
|
-
|
|
1141
|
-
.UnmagicMenu__panel--end {
|
|
1142
|
-
right: 0;
|
|
1143
|
-
}
|
|
1144
|
-
|
|
1145
|
-
.UnmagicMenu__panel--start {
|
|
1146
|
-
left: 0;
|
|
1147
|
-
}
|
|
1148
|
-
|
|
1149
|
-
/* button_to wraps each button in a form; this keeps it out of the column's way. */
|
|
1150
|
-
.UnmagicMenu__form {
|
|
1151
|
-
display: contents;
|
|
1152
|
-
}
|
|
1153
|
-
|
|
1154
|
-
.UnmagicMenu__item {
|
|
1155
|
-
display: flex;
|
|
1156
|
-
align-items: center;
|
|
1157
|
-
gap: 0.5rem;
|
|
1158
|
-
width: 100%;
|
|
1159
|
-
padding: 0.375rem 0.625rem;
|
|
1160
|
-
font: inherit;
|
|
1161
|
-
font-size: 0.875rem;
|
|
1162
|
-
line-height: 1.25rem;
|
|
1163
|
-
text-align: left;
|
|
1164
|
-
text-decoration: none;
|
|
1165
|
-
white-space: nowrap;
|
|
1166
|
-
color: var(--unmagic-text, var(--color-neutral-900, #171717));
|
|
1167
|
-
background: transparent;
|
|
1168
|
-
border: 0;
|
|
1169
|
-
border-radius: 0.375rem;
|
|
1170
|
-
cursor: pointer;
|
|
1171
|
-
}
|
|
1172
|
-
|
|
1173
|
-
.UnmagicMenu__item:hover,
|
|
1174
|
-
.UnmagicMenu__item:focus-visible {
|
|
1175
|
-
background-color: var(--unmagic-surface-3, var(--color-neutral-100, #f5f5f5));
|
|
1176
|
-
outline: none;
|
|
1177
|
-
}
|
|
1178
|
-
|
|
1179
|
-
.UnmagicMenu__item .UnmagicIcon {
|
|
1180
|
-
color: var(--unmagic-text-3, var(--color-neutral-500, #737373));
|
|
1181
|
-
}
|
|
1182
|
-
|
|
1183
|
-
.UnmagicMenu__item--danger,
|
|
1184
|
-
.UnmagicMenu__item--danger .UnmagicIcon {
|
|
1185
|
-
color: var(--unmagic-bad, var(--color-red-600, #dc2626));
|
|
1186
|
-
}
|
|
1187
|
-
|
|
1188
|
-
.UnmagicMenu__item--danger:hover,
|
|
1189
|
-
.UnmagicMenu__item--danger:focus-visible {
|
|
1190
|
-
background-color: var(--unmagic-bad-surface, var(--color-red-50, #fef2f2));
|
|
1191
|
-
}
|
|
1192
|
-
|
|
1193
|
-
.UnmagicMenu__divider {
|
|
1194
|
-
margin: 0.25rem -0.25rem;
|
|
1195
|
-
border: 0;
|
|
1196
|
-
border-top: 1px solid var(--unmagic-border, var(--color-neutral-200, #e5e5e5));
|
|
1197
|
-
}
|
|
1198
|
-
|
|
1199
|
-
/* ------------------------------------------------------------------- Tabs */
|
|
1200
|
-
|
|
1201
|
-
/* A segmented control: an inset track with the selected tab raised out of it.
|
|
1202
|
-
--unmagic-raised is that tab's surface, separate from --unmagic-surface because
|
|
1203
|
-
a dark theme raises by lightening rather than by staying the page colour. */
|
|
1204
|
-
.UnmagicTabs {
|
|
1205
|
-
display: block;
|
|
1206
|
-
}
|
|
1207
|
-
|
|
1208
|
-
.UnmagicTabs__list {
|
|
1209
|
-
display: inline-flex;
|
|
1210
|
-
flex-wrap: wrap;
|
|
1211
|
-
gap: 0.25rem;
|
|
1212
|
-
padding: 0.25rem;
|
|
1213
|
-
background-color: var(--unmagic-surface-3, var(--color-neutral-100, #f5f5f5));
|
|
1214
|
-
border-radius: 0.5rem;
|
|
1215
|
-
}
|
|
1216
|
-
|
|
1217
|
-
/* margin is reset because link tabs sit in a <nav>, and hosts often style bare
|
|
1218
|
-
nav links for their page chrome. */
|
|
1219
|
-
.UnmagicTabs__tab {
|
|
1220
|
-
display: inline-flex;
|
|
1221
|
-
align-items: center;
|
|
1222
|
-
gap: 0.375rem;
|
|
1223
|
-
margin: 0;
|
|
1224
|
-
padding: 0.375rem 0.75rem;
|
|
1225
|
-
font: inherit;
|
|
1226
|
-
font-size: 0.875rem;
|
|
1227
|
-
line-height: 1.25rem;
|
|
1228
|
-
font-weight: 500;
|
|
1229
|
-
white-space: nowrap;
|
|
1230
|
-
text-decoration: none;
|
|
1231
|
-
color: var(--unmagic-text-3, var(--color-neutral-500, #737373));
|
|
1232
|
-
background: transparent;
|
|
1233
|
-
border: 0;
|
|
1234
|
-
border-radius: 0.375rem;
|
|
1235
|
-
cursor: pointer;
|
|
1236
|
-
}
|
|
1237
|
-
|
|
1238
|
-
.UnmagicTabs__tab:hover {
|
|
1239
|
-
color: var(--unmagic-text, var(--color-neutral-900, #171717));
|
|
1240
|
-
}
|
|
1241
|
-
|
|
1242
|
-
.UnmagicTabs__tab[aria-selected="true"],
|
|
1243
|
-
.UnmagicTabs__tab[aria-current="page"] {
|
|
1244
|
-
color: var(--unmagic-text, var(--color-neutral-900, #171717));
|
|
1245
|
-
background-color: var(--unmagic-raised, var(--unmagic-surface, var(--color-white, #fff)));
|
|
1246
|
-
box-shadow: 0 1px 2px 0 rgb(0 0 0 / 0.08);
|
|
1247
|
-
}
|
|
1248
|
-
|
|
1249
|
-
.UnmagicTabs__tab:focus-visible,
|
|
1250
|
-
.UnmagicTabs__panel:focus-visible {
|
|
1251
|
-
outline: 2px solid var(--unmagic-focus, var(--color-neutral-400, #a3a3a3));
|
|
1252
|
-
outline-offset: 2px;
|
|
1253
|
-
}
|
|
1254
|
-
|
|
1255
|
-
.UnmagicTabs__tab[aria-disabled="true"] {
|
|
1256
|
-
cursor: not-allowed;
|
|
1257
|
-
opacity: 0.55;
|
|
1258
|
-
}
|
|
1259
|
-
|
|
1260
|
-
.UnmagicTabs__tab[aria-disabled="true"]:hover {
|
|
1261
|
-
color: var(--unmagic-text-3, var(--color-neutral-500, #737373));
|
|
1262
|
-
}
|
|
1263
|
-
|
|
1264
|
-
.UnmagicTabs__reason {
|
|
1265
|
-
font-weight: 400;
|
|
1266
|
-
}
|
|
1267
|
-
|
|
1268
|
-
.UnmagicTabs__panel {
|
|
1269
|
-
padding-top: 1rem;
|
|
1270
|
-
border-radius: 0.25rem;
|
|
1271
|
-
}
|
|
1272
|
-
|
|
1273
|
-
/* -------------------------------------------------------------- Clipboard */
|
|
1274
|
-
|
|
1275
|
-
.UnmagicClipboard {
|
|
1276
|
-
display: inline-flex;
|
|
1277
|
-
vertical-align: middle;
|
|
1278
|
-
}
|
|
1279
|
-
|
|
1280
|
-
.UnmagicClipboard__done {
|
|
1281
|
-
display: none;
|
|
1282
|
-
}
|
|
1283
|
-
|
|
1284
|
-
.UnmagicClipboard[data-copied] .UnmagicClipboard__idle {
|
|
1285
|
-
display: none;
|
|
1286
|
-
}
|
|
1287
|
-
|
|
1288
|
-
.UnmagicClipboard[data-copied] .UnmagicClipboard__done {
|
|
1289
|
-
display: block;
|
|
1290
|
-
}
|
|
1291
|
-
|
|
1292
|
-
.UnmagicClipboard[data-copied] .UnmagicClipboard__button {
|
|
1293
|
-
color: var(--unmagic-good, var(--color-green-700, #15803d));
|
|
1294
|
-
}
|
|
1295
|
-
|
|
1296
|
-
/* ------------------------------------------------------- Autogrow textarea */
|
|
1297
|
-
|
|
1298
|
-
/* The element sets the height, so a manual resize handle would only fight it. Give
|
|
1299
|
-
the textarea a max-height to cap the growth. A descendant rather than a child
|
|
1300
|
-
selector: Rails wraps an invalid control in a field_with_errors div, inside the
|
|
1301
|
-
element. */
|
|
1302
|
-
.UnmagicAutogrow {
|
|
1303
|
-
display: block;
|
|
1304
|
-
}
|
|
1305
|
-
|
|
1306
|
-
.UnmagicAutogrow textarea {
|
|
1307
|
-
resize: none;
|
|
1308
|
-
overflow-y: hidden;
|
|
1309
|
-
}
|