@wtfalch/design 0.7.0 → 0.9.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.
- package/README.md +18 -0
- package/dist/components/Button.js +8 -7
- package/dist/components/Callout.js +1 -1
- package/dist/components/Card.d.ts +1 -1
- package/dist/components/Card.js +21 -4
- package/dist/components/Command.js +2 -2
- package/dist/components/Empty.js +22 -1
- package/dist/components/Field.d.ts +22 -19
- package/dist/components/Field.js +11 -9
- package/dist/components/Input.d.ts +10 -0
- package/dist/components/Input.js +26 -5
- package/dist/components/Kbd.js +11 -1
- package/dist/components/Menu.js +3 -3
- package/dist/components/Modal.js +2 -2
- package/dist/components/Pagination.js +6 -1
- package/dist/components/Progress.js +8 -1
- package/dist/components/Rows.d.ts +1 -1
- package/dist/components/Rows.js +1 -1
- package/dist/components/Select.d.ts +3 -1
- package/dist/components/Select.js +28 -6
- package/dist/components/Shell.d.ts +35 -0
- package/dist/components/Shell.js +36 -0
- package/dist/components/SizeGrid.js +14 -2
- package/dist/components/Stat.js +11 -2
- package/dist/components/Table.js +7 -1
- package/dist/components/Textarea.js +14 -4
- package/dist/components/ThemeSwitch.d.ts +19 -0
- package/dist/components/ThemeSwitch.js +65 -0
- package/dist/components/Toast.js +1 -1
- package/dist/components/Tooltip.js +16 -2
- package/dist/components/Tour.js +1 -1
- package/dist/components/fieldWiring.d.ts +44 -0
- package/dist/components/fieldWiring.js +30 -0
- package/dist/index.d.ts +10 -1
- package/dist/index.js +8 -0
- package/dist/styles/index.css +1110 -355
- package/dist/tf.css +1110 -355
- package/dist/themes/choice.d.ts +71 -0
- package/dist/themes/choice.js +81 -0
- package/dist/valet.css +1110 -355
- package/package.json +3 -1
package/dist/valet.css
CHANGED
|
@@ -282,6 +282,705 @@
|
|
|
282
282
|
*
|
|
283
283
|
* `scripts/copy-css.mjs` flattens these into one file at build time.
|
|
284
284
|
*/
|
|
285
|
+
/* ---- ./_tailwind.built.css ---- */
|
|
286
|
+
/*! tailwindcss v4.3.3 | MIT License | https://tailwindcss.com */
|
|
287
|
+
@layer properties;
|
|
288
|
+
@layer theme, base, components, utilities;
|
|
289
|
+
@layer theme {
|
|
290
|
+
:root, :host {
|
|
291
|
+
--font-sans: var(--font-sans);
|
|
292
|
+
--font-mono: var(--font-mono);
|
|
293
|
+
--text-xs: var(--text-xs);
|
|
294
|
+
--text-xs--line-height: inherit;
|
|
295
|
+
--text-sm: var(--text-sm);
|
|
296
|
+
--text-sm--line-height: inherit;
|
|
297
|
+
--text-base: var(--text-base);
|
|
298
|
+
--text-lg: var(--text-lg);
|
|
299
|
+
--text-lg--line-height: inherit;
|
|
300
|
+
--text-xl: var(--text-xl);
|
|
301
|
+
--font-weight-normal: var(--weight);
|
|
302
|
+
--tracking-normal: var(--tracking);
|
|
303
|
+
--radius-sm: var(--radius-sm);
|
|
304
|
+
--radius-md: var(--radius-md);
|
|
305
|
+
--radius-lg: var(--radius-lg);
|
|
306
|
+
--ease-out: cubic-bezier(0, 0, 0.2, 1);
|
|
307
|
+
--spacing-1: var(--space-1);
|
|
308
|
+
--spacing-2: var(--space-2);
|
|
309
|
+
--spacing-3: var(--space-3);
|
|
310
|
+
--spacing-4: var(--space-4);
|
|
311
|
+
--spacing-5: var(--space-5);
|
|
312
|
+
--spacing-6: var(--space-6);
|
|
313
|
+
--spacing-10: var(--space-10);
|
|
314
|
+
--text-2xs--line-height: inherit;
|
|
315
|
+
--text-2xs: var(--text-2xs);
|
|
316
|
+
--text-md: var(--text-md);
|
|
317
|
+
--font-weight-strong: var(--weight-strong);
|
|
318
|
+
--radius-pill: var(--radius-pill);
|
|
319
|
+
--color-text: var(--text);
|
|
320
|
+
--color-muted: var(--muted);
|
|
321
|
+
--color-accent: var(--accent);
|
|
322
|
+
--color-border: var(--border);
|
|
323
|
+
--color-border-strong: var(--border-strong);
|
|
324
|
+
}
|
|
325
|
+
}
|
|
326
|
+
@layer utilities {
|
|
327
|
+
.collapse {
|
|
328
|
+
visibility: collapse;
|
|
329
|
+
}
|
|
330
|
+
.invisible {
|
|
331
|
+
visibility: hidden;
|
|
332
|
+
}
|
|
333
|
+
.visible {
|
|
334
|
+
visibility: visible;
|
|
335
|
+
}
|
|
336
|
+
.sr-only {
|
|
337
|
+
position: absolute;
|
|
338
|
+
width: 1px;
|
|
339
|
+
height: 1px;
|
|
340
|
+
padding: 0;
|
|
341
|
+
margin: -1px;
|
|
342
|
+
overflow: hidden;
|
|
343
|
+
clip-path: inset(50%);
|
|
344
|
+
white-space: nowrap;
|
|
345
|
+
border-width: 0;
|
|
346
|
+
}
|
|
347
|
+
.absolute {
|
|
348
|
+
position: absolute;
|
|
349
|
+
}
|
|
350
|
+
.fixed {
|
|
351
|
+
position: fixed;
|
|
352
|
+
}
|
|
353
|
+
.relative {
|
|
354
|
+
position: relative;
|
|
355
|
+
}
|
|
356
|
+
.sticky {
|
|
357
|
+
position: sticky;
|
|
358
|
+
}
|
|
359
|
+
.z-\[60\] {
|
|
360
|
+
z-index: 60;
|
|
361
|
+
}
|
|
362
|
+
.container {
|
|
363
|
+
width: 100%;
|
|
364
|
+
@media (width >= 40rem) {
|
|
365
|
+
max-width: 40rem;
|
|
366
|
+
}
|
|
367
|
+
@media (width >= 48rem) {
|
|
368
|
+
max-width: 48rem;
|
|
369
|
+
}
|
|
370
|
+
@media (width >= 64rem) {
|
|
371
|
+
max-width: 64rem;
|
|
372
|
+
}
|
|
373
|
+
@media (width >= 80rem) {
|
|
374
|
+
max-width: 80rem;
|
|
375
|
+
}
|
|
376
|
+
@media (width >= 96rem) {
|
|
377
|
+
max-width: 96rem;
|
|
378
|
+
}
|
|
379
|
+
}
|
|
380
|
+
.m-0 {
|
|
381
|
+
margin: 0px;
|
|
382
|
+
}
|
|
383
|
+
.m-auto {
|
|
384
|
+
margin: auto;
|
|
385
|
+
}
|
|
386
|
+
.mx-auto {
|
|
387
|
+
margin-inline: auto;
|
|
388
|
+
}
|
|
389
|
+
.mt-1 {
|
|
390
|
+
margin-top: var(--spacing-1);
|
|
391
|
+
}
|
|
392
|
+
.mb-3 {
|
|
393
|
+
margin-bottom: var(--spacing-3);
|
|
394
|
+
}
|
|
395
|
+
.ml-2 {
|
|
396
|
+
margin-left: var(--spacing-2);
|
|
397
|
+
}
|
|
398
|
+
.block {
|
|
399
|
+
display: block;
|
|
400
|
+
}
|
|
401
|
+
.contents {
|
|
402
|
+
display: contents;
|
|
403
|
+
}
|
|
404
|
+
.flex {
|
|
405
|
+
display: flex;
|
|
406
|
+
}
|
|
407
|
+
.grid {
|
|
408
|
+
display: grid;
|
|
409
|
+
}
|
|
410
|
+
.hidden {
|
|
411
|
+
display: none;
|
|
412
|
+
}
|
|
413
|
+
.inline {
|
|
414
|
+
display: inline;
|
|
415
|
+
}
|
|
416
|
+
.inline-flex {
|
|
417
|
+
display: inline-flex;
|
|
418
|
+
}
|
|
419
|
+
.table {
|
|
420
|
+
display: table;
|
|
421
|
+
}
|
|
422
|
+
.h-\[14px\] {
|
|
423
|
+
height: 14px;
|
|
424
|
+
}
|
|
425
|
+
.h-\[18px\] {
|
|
426
|
+
height: 18px;
|
|
427
|
+
}
|
|
428
|
+
.max-h-\[24rem\] {
|
|
429
|
+
max-height: 24rem;
|
|
430
|
+
}
|
|
431
|
+
.max-h-\[280px\] {
|
|
432
|
+
max-height: 280px;
|
|
433
|
+
}
|
|
434
|
+
.min-h-0 {
|
|
435
|
+
min-height: 0px;
|
|
436
|
+
}
|
|
437
|
+
.min-h-screen {
|
|
438
|
+
min-height: 100vh;
|
|
439
|
+
}
|
|
440
|
+
.w-\[18px\] {
|
|
441
|
+
width: 18px;
|
|
442
|
+
}
|
|
443
|
+
.w-full {
|
|
444
|
+
width: 100%;
|
|
445
|
+
}
|
|
446
|
+
.max-w-\[46ch\] {
|
|
447
|
+
max-width: 46ch;
|
|
448
|
+
}
|
|
449
|
+
.max-w-\[min\(20rem\,calc\(100vw-var\(--space-6\)\)\)\] {
|
|
450
|
+
max-width: min(20rem, calc(100vw - var(--space-6)));
|
|
451
|
+
}
|
|
452
|
+
.max-w-\[var\(--shell-measure\)\] {
|
|
453
|
+
max-width: var(--shell-measure);
|
|
454
|
+
}
|
|
455
|
+
.max-w-\[var\(--shell-measure-wide\)\] {
|
|
456
|
+
max-width: var(--shell-measure-wide);
|
|
457
|
+
}
|
|
458
|
+
.min-w-0 {
|
|
459
|
+
min-width: 0px;
|
|
460
|
+
}
|
|
461
|
+
.min-w-\[12rem\] {
|
|
462
|
+
min-width: 12rem;
|
|
463
|
+
}
|
|
464
|
+
.flex-1 {
|
|
465
|
+
flex: 1;
|
|
466
|
+
}
|
|
467
|
+
.flex-none {
|
|
468
|
+
flex: none;
|
|
469
|
+
}
|
|
470
|
+
.shrink {
|
|
471
|
+
flex-shrink: 1;
|
|
472
|
+
}
|
|
473
|
+
.grow {
|
|
474
|
+
flex-grow: 1;
|
|
475
|
+
}
|
|
476
|
+
.transform {
|
|
477
|
+
transform: var(--tw-rotate-x,) var(--tw-rotate-y,) var(--tw-rotate-z,) var(--tw-skew-x,) var(--tw-skew-y,);
|
|
478
|
+
}
|
|
479
|
+
.cursor-help {
|
|
480
|
+
cursor: help;
|
|
481
|
+
}
|
|
482
|
+
.cursor-pointer {
|
|
483
|
+
cursor: pointer;
|
|
484
|
+
}
|
|
485
|
+
.resize {
|
|
486
|
+
resize: both;
|
|
487
|
+
}
|
|
488
|
+
.list-none {
|
|
489
|
+
list-style-type: none;
|
|
490
|
+
}
|
|
491
|
+
.flex-col {
|
|
492
|
+
flex-direction: column;
|
|
493
|
+
}
|
|
494
|
+
.flex-wrap {
|
|
495
|
+
flex-wrap: wrap;
|
|
496
|
+
}
|
|
497
|
+
.items-baseline {
|
|
498
|
+
align-items: baseline;
|
|
499
|
+
}
|
|
500
|
+
.items-center {
|
|
501
|
+
align-items: center;
|
|
502
|
+
}
|
|
503
|
+
.items-start {
|
|
504
|
+
align-items: flex-start;
|
|
505
|
+
}
|
|
506
|
+
.justify-between {
|
|
507
|
+
justify-content: space-between;
|
|
508
|
+
}
|
|
509
|
+
.justify-items-center {
|
|
510
|
+
justify-items: center;
|
|
511
|
+
}
|
|
512
|
+
.gap-0 {
|
|
513
|
+
gap: 0px;
|
|
514
|
+
}
|
|
515
|
+
.gap-1 {
|
|
516
|
+
gap: var(--spacing-1);
|
|
517
|
+
}
|
|
518
|
+
.gap-2 {
|
|
519
|
+
gap: var(--spacing-2);
|
|
520
|
+
}
|
|
521
|
+
.gap-3 {
|
|
522
|
+
gap: var(--spacing-3);
|
|
523
|
+
}
|
|
524
|
+
.gap-4 {
|
|
525
|
+
gap: var(--spacing-4);
|
|
526
|
+
}
|
|
527
|
+
.gap-\[var\(--border-width\)\] {
|
|
528
|
+
gap: var(--border-width);
|
|
529
|
+
}
|
|
530
|
+
.self-center {
|
|
531
|
+
align-self: center;
|
|
532
|
+
}
|
|
533
|
+
.truncate {
|
|
534
|
+
overflow: hidden;
|
|
535
|
+
text-overflow: ellipsis;
|
|
536
|
+
white-space: nowrap;
|
|
537
|
+
}
|
|
538
|
+
.overflow-auto {
|
|
539
|
+
overflow: auto;
|
|
540
|
+
}
|
|
541
|
+
.overflow-hidden {
|
|
542
|
+
overflow: hidden;
|
|
543
|
+
}
|
|
544
|
+
.overflow-x-auto {
|
|
545
|
+
overflow-x: auto;
|
|
546
|
+
}
|
|
547
|
+
.overflow-y-auto {
|
|
548
|
+
overflow-y: auto;
|
|
549
|
+
}
|
|
550
|
+
.overscroll-contain {
|
|
551
|
+
overscroll-behavior: contain;
|
|
552
|
+
}
|
|
553
|
+
.rounded {
|
|
554
|
+
border-radius: 0.25rem;
|
|
555
|
+
}
|
|
556
|
+
.rounded-full {
|
|
557
|
+
border-radius: calc(infinity * 1px);
|
|
558
|
+
}
|
|
559
|
+
.rounded-md {
|
|
560
|
+
border-radius: var(--radius-md);
|
|
561
|
+
}
|
|
562
|
+
.rounded-sm {
|
|
563
|
+
border-radius: var(--radius-sm);
|
|
564
|
+
}
|
|
565
|
+
.border {
|
|
566
|
+
border-style: var(--tw-border-style);
|
|
567
|
+
border-width: var(--border-width);
|
|
568
|
+
}
|
|
569
|
+
.border-b {
|
|
570
|
+
border-bottom-style: var(--tw-border-style);
|
|
571
|
+
border-bottom-width: var(--border-width);
|
|
572
|
+
}
|
|
573
|
+
.border-dashed {
|
|
574
|
+
--tw-border-style: dashed;
|
|
575
|
+
border-style: dashed;
|
|
576
|
+
}
|
|
577
|
+
.border-accent {
|
|
578
|
+
border-color: var(--color-accent);
|
|
579
|
+
}
|
|
580
|
+
.border-border {
|
|
581
|
+
border-color: var(--color-border);
|
|
582
|
+
}
|
|
583
|
+
.border-border-strong {
|
|
584
|
+
border-color: var(--color-border-strong);
|
|
585
|
+
}
|
|
586
|
+
.p-0 {
|
|
587
|
+
padding: 0px;
|
|
588
|
+
}
|
|
589
|
+
.p-1 {
|
|
590
|
+
padding: var(--spacing-1);
|
|
591
|
+
}
|
|
592
|
+
.p-2 {
|
|
593
|
+
padding: var(--spacing-2);
|
|
594
|
+
}
|
|
595
|
+
.p-4 {
|
|
596
|
+
padding: var(--spacing-4);
|
|
597
|
+
}
|
|
598
|
+
.px-4 {
|
|
599
|
+
padding-inline: var(--spacing-4);
|
|
600
|
+
}
|
|
601
|
+
.py-2 {
|
|
602
|
+
padding-block: var(--spacing-2);
|
|
603
|
+
}
|
|
604
|
+
.py-3 {
|
|
605
|
+
padding-block: var(--spacing-3);
|
|
606
|
+
}
|
|
607
|
+
.py-5 {
|
|
608
|
+
padding-block: var(--spacing-5);
|
|
609
|
+
}
|
|
610
|
+
.py-6 {
|
|
611
|
+
padding-block: var(--spacing-6);
|
|
612
|
+
}
|
|
613
|
+
.py-10 {
|
|
614
|
+
padding-block: var(--spacing-10);
|
|
615
|
+
}
|
|
616
|
+
.pb-2 {
|
|
617
|
+
padding-bottom: var(--spacing-2);
|
|
618
|
+
}
|
|
619
|
+
.pb-3 {
|
|
620
|
+
padding-bottom: var(--spacing-3);
|
|
621
|
+
}
|
|
622
|
+
.text-center {
|
|
623
|
+
text-align: center;
|
|
624
|
+
}
|
|
625
|
+
.font-mono {
|
|
626
|
+
font-family: var(--font-mono);
|
|
627
|
+
}
|
|
628
|
+
.text-2xs {
|
|
629
|
+
font-size: var(--text-2xs);
|
|
630
|
+
line-height: var(--tw-leading, var(--text-2xs--line-height));
|
|
631
|
+
}
|
|
632
|
+
.text-lg {
|
|
633
|
+
font-size: var(--text-lg);
|
|
634
|
+
line-height: var(--tw-leading, var(--text-lg--line-height));
|
|
635
|
+
}
|
|
636
|
+
.text-sm {
|
|
637
|
+
font-size: var(--text-sm);
|
|
638
|
+
line-height: var(--tw-leading, var(--text-sm--line-height));
|
|
639
|
+
}
|
|
640
|
+
.text-xs {
|
|
641
|
+
font-size: var(--text-xs);
|
|
642
|
+
line-height: var(--tw-leading, var(--text-xs--line-height));
|
|
643
|
+
}
|
|
644
|
+
.leading-\[0\] {
|
|
645
|
+
--tw-leading: 0;
|
|
646
|
+
line-height: 0;
|
|
647
|
+
}
|
|
648
|
+
.leading-\[1\.5\] {
|
|
649
|
+
--tw-leading: 1.5;
|
|
650
|
+
line-height: 1.5;
|
|
651
|
+
}
|
|
652
|
+
.leading-\[1\.25\] {
|
|
653
|
+
--tw-leading: 1.25;
|
|
654
|
+
line-height: 1.25;
|
|
655
|
+
}
|
|
656
|
+
.leading-\[16px\] {
|
|
657
|
+
--tw-leading: 16px;
|
|
658
|
+
line-height: 16px;
|
|
659
|
+
}
|
|
660
|
+
.font-normal {
|
|
661
|
+
--tw-font-weight: var(--font-weight-normal);
|
|
662
|
+
font-weight: var(--font-weight-normal);
|
|
663
|
+
}
|
|
664
|
+
.font-strong {
|
|
665
|
+
--tw-font-weight: var(--font-weight-strong);
|
|
666
|
+
font-weight: var(--font-weight-strong);
|
|
667
|
+
}
|
|
668
|
+
.tracking-normal {
|
|
669
|
+
--tw-tracking: var(--tracking-normal);
|
|
670
|
+
letter-spacing: var(--tracking-normal);
|
|
671
|
+
}
|
|
672
|
+
.text-ellipsis {
|
|
673
|
+
text-overflow: ellipsis;
|
|
674
|
+
}
|
|
675
|
+
.whitespace-nowrap {
|
|
676
|
+
white-space: nowrap;
|
|
677
|
+
}
|
|
678
|
+
.text-muted {
|
|
679
|
+
color: var(--color-muted);
|
|
680
|
+
}
|
|
681
|
+
.text-text {
|
|
682
|
+
color: var(--color-text);
|
|
683
|
+
}
|
|
684
|
+
.lowercase {
|
|
685
|
+
text-transform: lowercase;
|
|
686
|
+
}
|
|
687
|
+
.normal-case {
|
|
688
|
+
text-transform: none;
|
|
689
|
+
}
|
|
690
|
+
.uppercase {
|
|
691
|
+
text-transform: uppercase;
|
|
692
|
+
}
|
|
693
|
+
.tabular-nums {
|
|
694
|
+
--tw-numeric-spacing: tabular-nums;
|
|
695
|
+
font-variant-numeric: var(--tw-ordinal,) var(--tw-slashed-zero,) var(--tw-numeric-figure,) var(--tw-numeric-spacing,) var(--tw-numeric-fraction,);
|
|
696
|
+
}
|
|
697
|
+
.opacity-0 {
|
|
698
|
+
opacity: 0%;
|
|
699
|
+
}
|
|
700
|
+
.opacity-60 {
|
|
701
|
+
opacity: 60%;
|
|
702
|
+
}
|
|
703
|
+
.opacity-\[0\.55\] {
|
|
704
|
+
opacity: 0.55;
|
|
705
|
+
}
|
|
706
|
+
.shadow {
|
|
707
|
+
--tw-shadow: 0 1px 3px 0 var(--tw-shadow-color, rgb(0 0 0 / 0.1)), 0 1px 2px -1px var(--tw-shadow-color, rgb(0 0 0 / 0.1));
|
|
708
|
+
box-shadow: var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow);
|
|
709
|
+
}
|
|
710
|
+
.ring {
|
|
711
|
+
--tw-ring-shadow: var(--tw-ring-inset,) 0 0 0 calc(1px + var(--tw-ring-offset-width)) var(--tw-ring-color, currentcolor);
|
|
712
|
+
box-shadow: var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow);
|
|
713
|
+
}
|
|
714
|
+
.outline {
|
|
715
|
+
outline-style: var(--tw-outline-style);
|
|
716
|
+
outline-width: 1px;
|
|
717
|
+
}
|
|
718
|
+
.blur {
|
|
719
|
+
--tw-blur: blur(8px);
|
|
720
|
+
filter: var(--tw-blur,) var(--tw-brightness,) var(--tw-contrast,) var(--tw-grayscale,) var(--tw-hue-rotate,) var(--tw-invert,) var(--tw-saturate,) var(--tw-sepia,) var(--tw-drop-shadow,);
|
|
721
|
+
}
|
|
722
|
+
.sepia {
|
|
723
|
+
--tw-sepia: sepia(100%);
|
|
724
|
+
filter: var(--tw-blur,) var(--tw-brightness,) var(--tw-contrast,) var(--tw-grayscale,) var(--tw-hue-rotate,) var(--tw-invert,) var(--tw-saturate,) var(--tw-sepia,) var(--tw-drop-shadow,);
|
|
725
|
+
}
|
|
726
|
+
.filter {
|
|
727
|
+
filter: var(--tw-blur,) var(--tw-brightness,) var(--tw-contrast,) var(--tw-grayscale,) var(--tw-hue-rotate,) var(--tw-invert,) var(--tw-saturate,) var(--tw-sepia,) var(--tw-drop-shadow,);
|
|
728
|
+
}
|
|
729
|
+
.outline-none {
|
|
730
|
+
--tw-outline-style: none;
|
|
731
|
+
outline-style: none;
|
|
732
|
+
}
|
|
733
|
+
.\[font\:inherit\] {
|
|
734
|
+
font: inherit;
|
|
735
|
+
}
|
|
736
|
+
.surface-bg {
|
|
737
|
+
background: var(--bg);
|
|
738
|
+
}
|
|
739
|
+
.surface-panel {
|
|
740
|
+
background: var(--panel);
|
|
741
|
+
}
|
|
742
|
+
.surface-panel-2 {
|
|
743
|
+
background: var(--panel-2);
|
|
744
|
+
}
|
|
745
|
+
.disabled\:cursor-default:disabled {
|
|
746
|
+
cursor: default;
|
|
747
|
+
}
|
|
748
|
+
.disabled\:opacity-50:disabled {
|
|
749
|
+
opacity: 50%;
|
|
750
|
+
}
|
|
751
|
+
.\[\&\>p\]\:m-0 > p {
|
|
752
|
+
margin: 0px;
|
|
753
|
+
}
|
|
754
|
+
}
|
|
755
|
+
@property --tw-rotate-x {
|
|
756
|
+
syntax: "*";
|
|
757
|
+
inherits: false;
|
|
758
|
+
}
|
|
759
|
+
@property --tw-rotate-y {
|
|
760
|
+
syntax: "*";
|
|
761
|
+
inherits: false;
|
|
762
|
+
}
|
|
763
|
+
@property --tw-rotate-z {
|
|
764
|
+
syntax: "*";
|
|
765
|
+
inherits: false;
|
|
766
|
+
}
|
|
767
|
+
@property --tw-skew-x {
|
|
768
|
+
syntax: "*";
|
|
769
|
+
inherits: false;
|
|
770
|
+
}
|
|
771
|
+
@property --tw-skew-y {
|
|
772
|
+
syntax: "*";
|
|
773
|
+
inherits: false;
|
|
774
|
+
}
|
|
775
|
+
@property --tw-border-style {
|
|
776
|
+
syntax: "*";
|
|
777
|
+
inherits: false;
|
|
778
|
+
initial-value: solid;
|
|
779
|
+
}
|
|
780
|
+
@property --tw-leading {
|
|
781
|
+
syntax: "*";
|
|
782
|
+
inherits: false;
|
|
783
|
+
}
|
|
784
|
+
@property --tw-font-weight {
|
|
785
|
+
syntax: "*";
|
|
786
|
+
inherits: false;
|
|
787
|
+
}
|
|
788
|
+
@property --tw-tracking {
|
|
789
|
+
syntax: "*";
|
|
790
|
+
inherits: false;
|
|
791
|
+
}
|
|
792
|
+
@property --tw-ordinal {
|
|
793
|
+
syntax: "*";
|
|
794
|
+
inherits: false;
|
|
795
|
+
}
|
|
796
|
+
@property --tw-slashed-zero {
|
|
797
|
+
syntax: "*";
|
|
798
|
+
inherits: false;
|
|
799
|
+
}
|
|
800
|
+
@property --tw-numeric-figure {
|
|
801
|
+
syntax: "*";
|
|
802
|
+
inherits: false;
|
|
803
|
+
}
|
|
804
|
+
@property --tw-numeric-spacing {
|
|
805
|
+
syntax: "*";
|
|
806
|
+
inherits: false;
|
|
807
|
+
}
|
|
808
|
+
@property --tw-numeric-fraction {
|
|
809
|
+
syntax: "*";
|
|
810
|
+
inherits: false;
|
|
811
|
+
}
|
|
812
|
+
@property --tw-shadow {
|
|
813
|
+
syntax: "*";
|
|
814
|
+
inherits: false;
|
|
815
|
+
initial-value: 0 0 #0000;
|
|
816
|
+
}
|
|
817
|
+
@property --tw-shadow-color {
|
|
818
|
+
syntax: "*";
|
|
819
|
+
inherits: false;
|
|
820
|
+
}
|
|
821
|
+
@property --tw-shadow-alpha {
|
|
822
|
+
syntax: "<percentage>";
|
|
823
|
+
inherits: false;
|
|
824
|
+
initial-value: 100%;
|
|
825
|
+
}
|
|
826
|
+
@property --tw-inset-shadow {
|
|
827
|
+
syntax: "*";
|
|
828
|
+
inherits: false;
|
|
829
|
+
initial-value: 0 0 #0000;
|
|
830
|
+
}
|
|
831
|
+
@property --tw-inset-shadow-color {
|
|
832
|
+
syntax: "*";
|
|
833
|
+
inherits: false;
|
|
834
|
+
}
|
|
835
|
+
@property --tw-inset-shadow-alpha {
|
|
836
|
+
syntax: "<percentage>";
|
|
837
|
+
inherits: false;
|
|
838
|
+
initial-value: 100%;
|
|
839
|
+
}
|
|
840
|
+
@property --tw-ring-color {
|
|
841
|
+
syntax: "*";
|
|
842
|
+
inherits: false;
|
|
843
|
+
}
|
|
844
|
+
@property --tw-ring-shadow {
|
|
845
|
+
syntax: "*";
|
|
846
|
+
inherits: false;
|
|
847
|
+
initial-value: 0 0 #0000;
|
|
848
|
+
}
|
|
849
|
+
@property --tw-inset-ring-color {
|
|
850
|
+
syntax: "*";
|
|
851
|
+
inherits: false;
|
|
852
|
+
}
|
|
853
|
+
@property --tw-inset-ring-shadow {
|
|
854
|
+
syntax: "*";
|
|
855
|
+
inherits: false;
|
|
856
|
+
initial-value: 0 0 #0000;
|
|
857
|
+
}
|
|
858
|
+
@property --tw-ring-inset {
|
|
859
|
+
syntax: "*";
|
|
860
|
+
inherits: false;
|
|
861
|
+
}
|
|
862
|
+
@property --tw-ring-offset-width {
|
|
863
|
+
syntax: "<length>";
|
|
864
|
+
inherits: false;
|
|
865
|
+
initial-value: 0px;
|
|
866
|
+
}
|
|
867
|
+
@property --tw-ring-offset-color {
|
|
868
|
+
syntax: "*";
|
|
869
|
+
inherits: false;
|
|
870
|
+
initial-value: #fff;
|
|
871
|
+
}
|
|
872
|
+
@property --tw-ring-offset-shadow {
|
|
873
|
+
syntax: "*";
|
|
874
|
+
inherits: false;
|
|
875
|
+
initial-value: 0 0 #0000;
|
|
876
|
+
}
|
|
877
|
+
@property --tw-outline-style {
|
|
878
|
+
syntax: "*";
|
|
879
|
+
inherits: false;
|
|
880
|
+
initial-value: solid;
|
|
881
|
+
}
|
|
882
|
+
@property --tw-blur {
|
|
883
|
+
syntax: "*";
|
|
884
|
+
inherits: false;
|
|
885
|
+
}
|
|
886
|
+
@property --tw-brightness {
|
|
887
|
+
syntax: "*";
|
|
888
|
+
inherits: false;
|
|
889
|
+
}
|
|
890
|
+
@property --tw-contrast {
|
|
891
|
+
syntax: "*";
|
|
892
|
+
inherits: false;
|
|
893
|
+
}
|
|
894
|
+
@property --tw-grayscale {
|
|
895
|
+
syntax: "*";
|
|
896
|
+
inherits: false;
|
|
897
|
+
}
|
|
898
|
+
@property --tw-hue-rotate {
|
|
899
|
+
syntax: "*";
|
|
900
|
+
inherits: false;
|
|
901
|
+
}
|
|
902
|
+
@property --tw-invert {
|
|
903
|
+
syntax: "*";
|
|
904
|
+
inherits: false;
|
|
905
|
+
}
|
|
906
|
+
@property --tw-opacity {
|
|
907
|
+
syntax: "*";
|
|
908
|
+
inherits: false;
|
|
909
|
+
}
|
|
910
|
+
@property --tw-saturate {
|
|
911
|
+
syntax: "*";
|
|
912
|
+
inherits: false;
|
|
913
|
+
}
|
|
914
|
+
@property --tw-sepia {
|
|
915
|
+
syntax: "*";
|
|
916
|
+
inherits: false;
|
|
917
|
+
}
|
|
918
|
+
@property --tw-drop-shadow {
|
|
919
|
+
syntax: "*";
|
|
920
|
+
inherits: false;
|
|
921
|
+
}
|
|
922
|
+
@property --tw-drop-shadow-color {
|
|
923
|
+
syntax: "*";
|
|
924
|
+
inherits: false;
|
|
925
|
+
}
|
|
926
|
+
@property --tw-drop-shadow-alpha {
|
|
927
|
+
syntax: "<percentage>";
|
|
928
|
+
inherits: false;
|
|
929
|
+
initial-value: 100%;
|
|
930
|
+
}
|
|
931
|
+
@property --tw-drop-shadow-size {
|
|
932
|
+
syntax: "*";
|
|
933
|
+
inherits: false;
|
|
934
|
+
}
|
|
935
|
+
@layer properties {
|
|
936
|
+
@supports ((-webkit-hyphens: none) and (not (margin-trim: inline))) or ((-moz-orient: inline) and (not (color:rgb(from red r g b)))) {
|
|
937
|
+
*, ::before, ::after, ::backdrop {
|
|
938
|
+
--tw-rotate-x: initial;
|
|
939
|
+
--tw-rotate-y: initial;
|
|
940
|
+
--tw-rotate-z: initial;
|
|
941
|
+
--tw-skew-x: initial;
|
|
942
|
+
--tw-skew-y: initial;
|
|
943
|
+
--tw-border-style: solid;
|
|
944
|
+
--tw-leading: initial;
|
|
945
|
+
--tw-font-weight: initial;
|
|
946
|
+
--tw-tracking: initial;
|
|
947
|
+
--tw-ordinal: initial;
|
|
948
|
+
--tw-slashed-zero: initial;
|
|
949
|
+
--tw-numeric-figure: initial;
|
|
950
|
+
--tw-numeric-spacing: initial;
|
|
951
|
+
--tw-numeric-fraction: initial;
|
|
952
|
+
--tw-shadow: 0 0 #0000;
|
|
953
|
+
--tw-shadow-color: initial;
|
|
954
|
+
--tw-shadow-alpha: 100%;
|
|
955
|
+
--tw-inset-shadow: 0 0 #0000;
|
|
956
|
+
--tw-inset-shadow-color: initial;
|
|
957
|
+
--tw-inset-shadow-alpha: 100%;
|
|
958
|
+
--tw-ring-color: initial;
|
|
959
|
+
--tw-ring-shadow: 0 0 #0000;
|
|
960
|
+
--tw-inset-ring-color: initial;
|
|
961
|
+
--tw-inset-ring-shadow: 0 0 #0000;
|
|
962
|
+
--tw-ring-inset: initial;
|
|
963
|
+
--tw-ring-offset-width: 0px;
|
|
964
|
+
--tw-ring-offset-color: #fff;
|
|
965
|
+
--tw-ring-offset-shadow: 0 0 #0000;
|
|
966
|
+
--tw-outline-style: solid;
|
|
967
|
+
--tw-blur: initial;
|
|
968
|
+
--tw-brightness: initial;
|
|
969
|
+
--tw-contrast: initial;
|
|
970
|
+
--tw-grayscale: initial;
|
|
971
|
+
--tw-hue-rotate: initial;
|
|
972
|
+
--tw-invert: initial;
|
|
973
|
+
--tw-opacity: initial;
|
|
974
|
+
--tw-saturate: initial;
|
|
975
|
+
--tw-sepia: initial;
|
|
976
|
+
--tw-drop-shadow: initial;
|
|
977
|
+
--tw-drop-shadow-color: initial;
|
|
978
|
+
--tw-drop-shadow-alpha: 100%;
|
|
979
|
+
--tw-drop-shadow-size: initial;
|
|
980
|
+
}
|
|
981
|
+
}
|
|
982
|
+
}
|
|
983
|
+
|
|
285
984
|
/* ---- ./base.css ---- */
|
|
286
985
|
/* Light, only under the `system` theme. This used to override `:root`
|
|
287
986
|
unconditionally, so choosing a dark theme on a light-mode laptop got
|
|
@@ -375,23 +1074,31 @@ body::before {
|
|
|
375
1074
|
`[aria-disabled='true']` twin rather than a rewrite, which leaves each
|
|
376
1075
|
`button` selector at the specificity it had and every committed baseline
|
|
377
1076
|
untouched. */
|
|
378
|
-
|
|
1077
|
+
.btn {
|
|
1078
|
+
/* The three an anchor brings that a `<button>` does not. Harmless on the
|
|
1079
|
+
button form -- it has no underline and centres already -- and the reason
|
|
1080
|
+
`Button` puts one class on both elements rather than keeping a twin
|
|
1081
|
+
selector for each. */
|
|
379
1082
|
text-decoration: none;
|
|
380
1083
|
color: var(--text);
|
|
381
1084
|
text-align: center;
|
|
382
1085
|
}
|
|
383
1086
|
|
|
384
|
-
|
|
1087
|
+
.btn[aria-disabled='true'] {
|
|
385
1088
|
/* A disabled anchor still takes the pointer, so say so. The click itself is
|
|
386
1089
|
blocked in the capture phase by the component. */
|
|
387
1090
|
cursor: not-allowed;
|
|
388
1091
|
}
|
|
389
1092
|
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
input,
|
|
393
|
-
|
|
394
|
-
|
|
1093
|
+
/* `:where`, so this base carries no specificity of its own.
|
|
1094
|
+
*
|
|
1095
|
+
* It was `button, input, textarea, select` -- an element selector, which
|
|
1096
|
+
* `.size-sm` and every other class outranked without anyone thinking about
|
|
1097
|
+
* it. Moving it to `.btn` to stop a tab inheriting a control's look raised it
|
|
1098
|
+
* to a class, so it tied with `.size-sm` and won on source order: every
|
|
1099
|
+
* button came out `8px 12px` whatever size it asked for. `:where` puts it
|
|
1100
|
+
* back to zero, which is what the element selector was silently providing. */
|
|
1101
|
+
:where(.btn, input, textarea, select) {
|
|
395
1102
|
font: inherit;
|
|
396
1103
|
color: var(--text);
|
|
397
1104
|
background: var(--control);
|
|
@@ -412,8 +1119,7 @@ select {
|
|
|
412
1119
|
the icon; the button simply had no opinion about how to arrange two things.
|
|
413
1120
|
`inline-flex` and a gap gives it one, and the gap replaces the space
|
|
414
1121
|
character people were putting between an icon and its label. */
|
|
415
|
-
|
|
416
|
-
a.btn {
|
|
1122
|
+
.btn {
|
|
417
1123
|
display: inline-flex;
|
|
418
1124
|
align-items: center;
|
|
419
1125
|
justify-content: center;
|
|
@@ -429,18 +1135,41 @@ a.btn {
|
|
|
429
1135
|
|
|
430
1136
|
Several places already drew this by hand as `.chat-bar-btn.on`. This is the
|
|
431
1137
|
same look, said once, on a plain button. */
|
|
432
|
-
|
|
1138
|
+
.btn[aria-pressed='true'] {
|
|
433
1139
|
border-color: var(--accent);
|
|
434
1140
|
color: var(--accent);
|
|
435
1141
|
background: color-mix(in srgb, var(--accent) 10%, var(--panel));
|
|
436
1142
|
}
|
|
437
1143
|
|
|
438
|
-
|
|
1144
|
+
.btn[aria-pressed='true']:hover:not(:disabled) { border-color: var(--accent); }
|
|
439
1145
|
|
|
440
1146
|
/* The glyph never shrinks: in a narrow row flexbox would take it from the icon
|
|
441
1147
|
before the text, and half an icon is not a smaller icon. */
|
|
442
|
-
|
|
443
|
-
|
|
1148
|
+
.btn > svg { flex: none; }
|
|
1149
|
+
|
|
1150
|
+
/* `Select`'s control wears the control styling, and says so.
|
|
1151
|
+
*
|
|
1152
|
+
* It renders React Aria's `Button` -- a bare `<button>` -- and used to take
|
|
1153
|
+
* `font`, colour, the surface and the border from the
|
|
1154
|
+
* `button, input, textarea, select` reset without asking. When that reset
|
|
1155
|
+
* moved to `.btn`, so a tab and a row would stop inheriting a control's look
|
|
1156
|
+
* only to undo it, this lost all of it at once.
|
|
1157
|
+
*
|
|
1158
|
+
* Here rather than in `select.css`, and that placement is the rule, not
|
|
1159
|
+
* tidiness: `font` is a shorthand and it resets `font-size`, so declared
|
|
1160
|
+
* after `.size-sm` below it silently makes every small control full size.
|
|
1161
|
+
* `index.css` says the import order is behaviour; this is what that means.
|
|
1162
|
+
*
|
|
1163
|
+
* `:where` for the same reason the reset above uses it: this is a base a
|
|
1164
|
+
* `size` class has to be able to beat, and a bare class ties with one. */
|
|
1165
|
+
:where(.sel-control) {
|
|
1166
|
+
font: inherit;
|
|
1167
|
+
color: var(--text);
|
|
1168
|
+
background: var(--control);
|
|
1169
|
+
border: var(--border-width) solid var(--border-strong);
|
|
1170
|
+
border-radius: var(--radius);
|
|
1171
|
+
cursor: pointer;
|
|
1172
|
+
}
|
|
444
1173
|
|
|
445
1174
|
.size-sm { font-size: var(--text-xs); padding: var(--space-1) var(--space-2); }
|
|
446
1175
|
|
|
@@ -465,8 +1194,7 @@ input, textarea, select { width: 100%; }
|
|
|
465
1194
|
same disagreement written twice. */
|
|
466
1195
|
textarea { resize: none; }
|
|
467
1196
|
|
|
468
|
-
|
|
469
|
-
a.btn:hover:not([aria-disabled='true']),
|
|
1197
|
+
.btn:hover:not(:disabled),
|
|
470
1198
|
input:hover:not(:disabled),
|
|
471
1199
|
textarea:hover:not(:disabled),
|
|
472
1200
|
select:hover:not(:disabled) { border-color: var(--accent); }
|
|
@@ -474,8 +1202,7 @@ select:hover:not(:disabled) { border-color: var(--accent); }
|
|
|
474
1202
|
/* `:focus-visible` on the button so a click does not leave a ring behind it,
|
|
475
1203
|
`:focus` on the fields because a focused field is a place you are typing and
|
|
476
1204
|
should say so however you got there. */
|
|
477
|
-
|
|
478
|
-
a.btn:focus-visible,
|
|
1205
|
+
.btn:focus-visible,
|
|
479
1206
|
input:focus,
|
|
480
1207
|
textarea:focus,
|
|
481
1208
|
select:focus { outline: none; border-color: var(--accent); }
|
|
@@ -568,14 +1295,13 @@ input[type='radio']:focus-visible { outline: none; box-shadow: var(--focus-ring)
|
|
|
568
1295
|
input[type='checkbox']:disabled,
|
|
569
1296
|
input[type='radio']:disabled { cursor: not-allowed; background: var(--panel-2); }
|
|
570
1297
|
|
|
571
|
-
|
|
572
|
-
|
|
1298
|
+
.btn:disabled,
|
|
1299
|
+
.btn[aria-disabled='true'],
|
|
573
1300
|
input:disabled,
|
|
574
1301
|
textarea:disabled,
|
|
575
1302
|
select:disabled { opacity: 0.45; cursor: not-allowed; }
|
|
576
1303
|
|
|
577
|
-
|
|
578
|
-
a.btn.primary { background: var(--accent); border-color: var(--accent); color: var(--on-accent); }
|
|
1304
|
+
.btn.primary { background: var(--accent); border-color: var(--accent); color: var(--on-accent); }
|
|
579
1305
|
|
|
580
1306
|
/* A disabled primary is not a faded primary.
|
|
581
1307
|
`opacity: .45` was the whole of it, and a coloured fill at 45% is still a
|
|
@@ -583,8 +1309,7 @@ a.btn.primary { background: var(--accent); border-color: var(--accent); color: v
|
|
|
583
1309
|
thing on the panel. That got worse when onboarding started holding people at
|
|
584
1310
|
a disabled Next. So it gives up the fill entirely and becomes the shape of a
|
|
585
1311
|
disabled control -- the opacity then has nothing left to do. */
|
|
586
|
-
|
|
587
|
-
a.btn.primary[aria-disabled='true'] {
|
|
1312
|
+
.btn.primary:disabled {
|
|
588
1313
|
background: var(--panel-2);
|
|
589
1314
|
border-color: var(--border);
|
|
590
1315
|
color: var(--muted);
|
|
@@ -598,7 +1323,7 @@ a.btn.primary[aria-disabled='true'] {
|
|
|
598
1323
|
line under it that travels.
|
|
599
1324
|
`aria-busy` rather than a class: the attribute is what a screen reader reads,
|
|
600
1325
|
and styling the thing that carries the meaning is how they stay in step. */
|
|
601
|
-
|
|
1326
|
+
.btn[aria-busy='true'] {
|
|
602
1327
|
position: relative;
|
|
603
1328
|
overflow: hidden;
|
|
604
1329
|
cursor: progress;
|
|
@@ -611,18 +1336,18 @@ button[aria-busy='true'] {
|
|
|
611
1336
|
something that is working, that reads as a control that failed and went
|
|
612
1337
|
grey. So a busy button keeps every colour it had and takes only the loss of
|
|
613
1338
|
the cursor and the press; the travelling line is what says why. */
|
|
614
|
-
|
|
1339
|
+
.btn[aria-busy='true']:disabled {
|
|
615
1340
|
opacity: 1;
|
|
616
1341
|
cursor: progress;
|
|
617
1342
|
}
|
|
618
1343
|
|
|
619
|
-
|
|
1344
|
+
.btn.primary[aria-busy='true']:disabled {
|
|
620
1345
|
background: var(--accent);
|
|
621
1346
|
border-color: var(--accent);
|
|
622
1347
|
color: var(--on-accent);
|
|
623
1348
|
}
|
|
624
1349
|
|
|
625
|
-
|
|
1350
|
+
.btn[aria-busy='true']::after {
|
|
626
1351
|
content: '';
|
|
627
1352
|
position: absolute;
|
|
628
1353
|
left: 0;
|
|
@@ -654,15 +1379,13 @@ button[aria-busy='true']::after {
|
|
|
654
1379
|
|
|
655
1380
|
/* Quiet: no border, no fill. For the action beside the action -- Cancel next to
|
|
656
1381
|
Save -- where a bordered box competes with the thing it is next to. */
|
|
657
|
-
|
|
658
|
-
a.btn.ghost {
|
|
1382
|
+
.btn.ghost {
|
|
659
1383
|
background: transparent;
|
|
660
1384
|
border-color: transparent;
|
|
661
1385
|
color: var(--muted);
|
|
662
1386
|
}
|
|
663
1387
|
|
|
664
|
-
|
|
665
|
-
a.btn.ghost:hover:not([aria-disabled='true']) {
|
|
1388
|
+
.btn.ghost:hover:not(:disabled) {
|
|
666
1389
|
background: var(--panel-2);
|
|
667
1390
|
border-color: transparent;
|
|
668
1391
|
color: var(--text);
|
|
@@ -744,7 +1467,7 @@ a.btn.ghost:hover:not([aria-disabled='true']) {
|
|
|
744
1467
|
header.) */
|
|
745
1468
|
.row { display: flex; align-items: center; gap: var(--space-3); }
|
|
746
1469
|
|
|
747
|
-
.grow { flex: 1; min-width: 0; }
|
|
1470
|
+
.ctl-grow { flex: 1; min-width: 0; }
|
|
748
1471
|
|
|
749
1472
|
.mono { font-family: var(--font-mono); font-size: var(--text-sm); }
|
|
750
1473
|
|
|
@@ -808,10 +1531,17 @@ a.btn.ghost:hover:not([aria-disabled='true']) {
|
|
|
808
1531
|
/* A pill following a name needs the gap outside its own border. Leading
|
|
809
1532
|
whitespace inside the span puts it under the pill's background instead,
|
|
810
1533
|
which reads as the badge touching the word it qualifies. */
|
|
811
|
-
|
|
1534
|
+
/* A pill beside a name, and the one thing that keeps the pair working:
|
|
1535
|
+
`flex: none`, so the pill never shrinks and the name ellipsises instead.
|
|
1536
|
+
That was `rows.css`'s `.named > .pill`, which meant anybody laying out a
|
|
1537
|
+
name and its pills had to know a package class by name to get it. The
|
|
1538
|
+
variant already says "I am in a row"; it may as well say what that costs. */
|
|
1539
|
+
.row-pill { margin-left: var(--space-2); vertical-align: baseline; flex: none; }
|
|
812
1540
|
|
|
813
1541
|
/* The tile's only control. Dim until hovered: it is chrome on someone's app. */
|
|
814
1542
|
.icon-btn {
|
|
1543
|
+
/* Stated rather than inherited. These came from the `button, input, textarea, select` reset, which applied control styling to everything that happened to be a `<button>` -- so this rule spent its opening lines undoing it, and would break silently if that rule ever moved. It did move, to `.btn`. */
|
|
1544
|
+
font: inherit;
|
|
815
1545
|
display: inline-flex; align-items: center; padding: var(--space-1);
|
|
816
1546
|
background: none; border: 0; color: var(--muted); opacity: 0.6; cursor: pointer;
|
|
817
1547
|
}
|
|
@@ -877,19 +1607,17 @@ a.btn.ghost:hover:not([aria-disabled='true']) {
|
|
|
877
1607
|
transition: none;
|
|
878
1608
|
}
|
|
879
1609
|
|
|
880
|
-
|
|
881
|
-
a.btn.primary:active:not([aria-disabled='true']) {
|
|
1610
|
+
.btn.primary:active:not(:disabled) {
|
|
882
1611
|
background: color-mix(in srgb, var(--text) var(--press-ink), var(--accent));
|
|
883
1612
|
border-color: color-mix(in srgb, var(--text) var(--press-ink), var(--accent));
|
|
884
1613
|
}
|
|
885
1614
|
|
|
886
|
-
|
|
887
|
-
a.btn.ghost:active:not([aria-disabled='true']) {
|
|
1615
|
+
.btn.ghost:active:not(:disabled) {
|
|
888
1616
|
background: color-mix(in srgb, var(--text) var(--press-ink), var(--panel-2));
|
|
889
1617
|
border-color: transparent;
|
|
890
1618
|
}
|
|
891
1619
|
|
|
892
|
-
|
|
1620
|
+
.btn[aria-pressed='true']:active:not(:disabled) {
|
|
893
1621
|
background: color-mix(in srgb, var(--accent) 18%, var(--panel));
|
|
894
1622
|
}
|
|
895
1623
|
|
|
@@ -1060,7 +1788,7 @@ input:active, textarea:active, select:active { transform: none; }
|
|
|
1060
1788
|
|
|
1061
1789
|
/* The top bar carries the title, the views and the way into settings. Nothing
|
|
1062
1790
|
that belongs to a conversation lives here any more, so it can breathe. */
|
|
1063
|
-
.topbar .grow { flex: 1; min-width: 0; }
|
|
1791
|
+
.topbar .ctl-grow { flex: 1; min-width: 0; }
|
|
1064
1792
|
|
|
1065
1793
|
/* Back on the left, Next on the right, with the gap between them doing the
|
|
1066
1794
|
separating -- so the button that goes forward is in the same place on both
|
|
@@ -1092,6 +1820,57 @@ input:active, textarea:active, select:active { transform: none; }
|
|
|
1092
1820
|
to { opacity: 1; }
|
|
1093
1821
|
}
|
|
1094
1822
|
|
|
1823
|
+
/* The states the `button` element rule used to hand every bare `<button>` in
|
|
1824
|
+
the package, now asked for by name.
|
|
1825
|
+
*
|
|
1826
|
+
* This is the half of the decoupling that a screenshot cannot show: `:focus-visible`
|
|
1827
|
+
* is not photographed, so nine components would have lost their focus ring in
|
|
1828
|
+
* silence. `keyboard.spec.ts` is what actually holds this.
|
|
1829
|
+
*
|
|
1830
|
+
* `.btn` has its own, in the rules above. These are the ones that are a button
|
|
1831
|
+
* for their behaviour and not for their appearance -- a tab, a row, a card, a
|
|
1832
|
+
* pager step, a grid cell, a remove cross. */
|
|
1833
|
+
.tab:focus-visible,
|
|
1834
|
+
.row-hit:focus-visible,
|
|
1835
|
+
.card:focus-visible,
|
|
1836
|
+
.ident-remove:focus-visible,
|
|
1837
|
+
.size-cell:focus-visible,
|
|
1838
|
+
.pager-step:focus-visible,
|
|
1839
|
+
.pager-page:focus-visible,
|
|
1840
|
+
.sel-control:focus-visible {
|
|
1841
|
+
outline: 2px solid var(--accent);
|
|
1842
|
+
outline-offset: 2px;
|
|
1843
|
+
}
|
|
1844
|
+
|
|
1845
|
+
/* `:disabled` came from the same rule. A control that cannot be pressed has to
|
|
1846
|
+
say so whatever element it is. */
|
|
1847
|
+
.tab:disabled,
|
|
1848
|
+
.row-hit:disabled,
|
|
1849
|
+
.card:disabled,
|
|
1850
|
+
.ident-remove:disabled,
|
|
1851
|
+
.size-cell:disabled,
|
|
1852
|
+
.pager-step:disabled,
|
|
1853
|
+
.pager-page:disabled,
|
|
1854
|
+
.sel-control:disabled {
|
|
1855
|
+
opacity: 0.45;
|
|
1856
|
+
cursor: not-allowed;
|
|
1857
|
+
}
|
|
1858
|
+
|
|
1859
|
+
/* The anchor form's disabled states, alongside the button's.
|
|
1860
|
+
*
|
|
1861
|
+
* `.btn` is one class on two elements, and an `<a>` has no `:disabled` -- it
|
|
1862
|
+
* carries `aria-disabled` and a capture-phase click block instead. Every
|
|
1863
|
+
* rule above that reads `:disabled` needs the attribute twin, or a disabled
|
|
1864
|
+
* link is a link that looks pressable and refuses silently. Folding the old
|
|
1865
|
+
* `a.btn` twins into `.btn` dropped these, and the baselines showed a
|
|
1866
|
+
* disabled link at full strength. */
|
|
1867
|
+
.btn.primary[aria-disabled='true'] {
|
|
1868
|
+
background: var(--panel-2);
|
|
1869
|
+
border-color: var(--border);
|
|
1870
|
+
color: var(--muted);
|
|
1871
|
+
opacity: 1;
|
|
1872
|
+
}
|
|
1873
|
+
|
|
1095
1874
|
/* ---- ./select.css ---- */
|
|
1096
1875
|
/* How big a control is, asked for rather than inherited.
|
|
1097
1876
|
Four sizes existed and every one of them came from a descendant selector:
|
|
@@ -1107,8 +1886,7 @@ input:active, textarea:active, select:active { transform: none; }
|
|
|
1107
1886
|
/* Full width, for the one action a card or a step is about. Not a size: a
|
|
1108
1887
|
`block` button is the same height as any other, it just stops being a thing
|
|
1109
1888
|
you have to aim at. */
|
|
1110
|
-
|
|
1111
|
-
a.btn.block { display: flex; width: 100%; }
|
|
1889
|
+
.btn.ctl-block { display: flex; width: 100%; }
|
|
1112
1890
|
|
|
1113
1891
|
/* The default is `size-md`, spelled once for every control.
|
|
1114
1892
|
The paragraph above promised one scale for buttons, inputs and selects, and
|
|
@@ -1116,13 +1894,24 @@ a.btn.block { display: flex; width: 100%; }
|
|
|
1116
1894
|
input was eight pixels taller than the button beside it and no row of the two
|
|
1117
1895
|
could line up. The download modal's search box against its Search button was
|
|
1118
1896
|
the version you could see from across the room. */
|
|
1119
|
-
|
|
1120
|
-
|
|
1121
|
-
input,
|
|
1122
|
-
|
|
1123
|
-
|
|
1897
|
+
/* `:where`, so this base carries no specificity of its own.
|
|
1898
|
+
*
|
|
1899
|
+
* It was `button, input, textarea, select` -- an element selector, which
|
|
1900
|
+
* `.size-sm` and every other class outranked without anyone thinking about
|
|
1901
|
+
* it. Moving it to `.btn` to stop a tab inheriting a control's look raised it
|
|
1902
|
+
* to a class, so it tied with `.size-sm` and won on source order: every
|
|
1903
|
+
* button came out `8px 12px` whatever size it asked for. `:where` puts it
|
|
1904
|
+
* back to zero, which is what the element selector was silently providing. */
|
|
1905
|
+
:where(.btn, input, textarea, select) { padding: var(--space-2) var(--space-3); }
|
|
1906
|
+
|
|
1907
|
+
/* The select's control keeps its padding at full class weight, and after
|
|
1908
|
+
`.size-sm` in the cascade, because that is where it has always been: this
|
|
1909
|
+
file is imported after `base.css`, so a `size`d select took the size's type
|
|
1910
|
+
and this padding. Folding it into the `:where` above handed the padding
|
|
1911
|
+
back to `.size-sm` and shrank every small select by seven pixels. */
|
|
1124
1912
|
.sel-control { padding: var(--space-2) var(--space-3); }
|
|
1125
1913
|
|
|
1914
|
+
|
|
1126
1915
|
/* Centred on the whole block -- the caption and the sentence together -- rather
|
|
1127
1916
|
than aligned to either end of it. `.field-row` pins to the bottom, which is
|
|
1128
1917
|
right for a field beside a button and wrong beside two lines of prose. */
|
|
@@ -1146,16 +1935,16 @@ select,
|
|
|
1146
1935
|
.sel { position: relative; display: inline-block; }
|
|
1147
1936
|
|
|
1148
1937
|
/* The subject of its pane rather than a field in it: full width and a size up.
|
|
1149
|
-
That was `.select-field.block` on the native element, and it carried the
|
|
1938
|
+
That was `.select-field.ctl-block` on the native element, and it carried the
|
|
1150
1939
|
reason with it -- model ids are long (`qwen2.5-coder:32b-instruct-q4_K_M`) and
|
|
1151
1940
|
at the narrow size they truncated mid-name. */
|
|
1152
|
-
.sel.block { display: block; width: 100%; }
|
|
1941
|
+
.sel.ctl-block { display: block; width: 100%; }
|
|
1153
1942
|
|
|
1154
|
-
.sel.block .sel-control { padding: var(--space-2) var(--space-3); font-weight: 500; }
|
|
1943
|
+
.sel.ctl-block .sel-control { padding: var(--space-2) var(--space-3); font-weight: 500; }
|
|
1155
1944
|
|
|
1156
1945
|
/* Not full width otherwise: a select as wide as its row, holding one short
|
|
1157
1946
|
word, reads as an input somebody forgot to fill in. */
|
|
1158
|
-
.sel:not(.block) .sel-control { width: auto; max-width: 320px; }
|
|
1947
|
+
.sel:not(.ctl-block) .sel-control { width: auto; max-width: 320px; }
|
|
1159
1948
|
|
|
1160
1949
|
.sel-control {
|
|
1161
1950
|
display: flex;
|
|
@@ -1168,9 +1957,7 @@ select,
|
|
|
1168
1957
|
background: var(--control);
|
|
1169
1958
|
}
|
|
1170
1959
|
|
|
1171
|
-
.sel-
|
|
1172
|
-
|
|
1173
|
-
.sel-caret { flex: none; opacity: 0.6; transition: transform var(--dur-fast) var(--ease); }
|
|
1960
|
+
.sel-caret { transition: transform var(--dur-fast) var(--ease); }
|
|
1174
1961
|
|
|
1175
1962
|
.sel[data-open] .sel-caret { transform: rotate(180deg); }
|
|
1176
1963
|
|
|
@@ -1179,21 +1966,7 @@ select,
|
|
|
1179
1966
|
/* State is read off React Aria's attributes: `data-open` on the root,
|
|
1180
1967
|
`data-focused` / `data-selected` / `data-disabled` on an item, where
|
|
1181
1968
|
`.open`, `[data-active]`, `.on` and `.off` used to be. */
|
|
1182
|
-
.sel-list {
|
|
1183
|
-
/* `fixed`, and in `document.body`: an ancestor that scrolls or hides its
|
|
1184
|
-
overflow would otherwise clip it, which in this app means every settings
|
|
1185
|
-
pane. Position comes from the button's measured rectangle. */
|
|
1186
|
-
/* Positioned by React Aria -- inline `top`/`left` on a portalled popover
|
|
1187
|
-
that flips when the edge is near. `position: fixed` and the measured
|
|
1188
|
-
rectangle it was placed by are gone with the hand-rolled version. */
|
|
1189
|
-
z-index: 60;
|
|
1190
|
-
max-height: 280px;
|
|
1191
|
-
overflow-y: auto;
|
|
1192
|
-
margin: 0;
|
|
1193
|
-
padding: var(--space-1);
|
|
1194
|
-
/* The same room while the list is scrolled as it has at rest. Padding at
|
|
1195
|
-
the top of a scroll container scrolls away with the content, so the row
|
|
1196
|
-
`scrollIntoView({block: 'nearest'})` brings up ended flush against the
|
|
1969
|
+
.sel-list { scroll-padding-block: var(--space-1); box-shadow: var(--shadow-2); })` brings up ended flush against the
|
|
1197
1970
|
border and read as clipped rather than as one of a set -- and this list
|
|
1198
1971
|
opens scrolled to whatever is chosen, so that was the ordinary state.
|
|
1199
1972
|
`scroll-padding` insets what counts as "in view", so it stops short by
|
|
@@ -1206,18 +1979,6 @@ select,
|
|
|
1206
1979
|
box-shadow: var(--shadow-2);
|
|
1207
1980
|
}
|
|
1208
1981
|
|
|
1209
|
-
.sel-item {
|
|
1210
|
-
display: flex;
|
|
1211
|
-
align-items: center;
|
|
1212
|
-
gap: var(--space-2);
|
|
1213
|
-
padding: var(--space-2) var(--space-2);
|
|
1214
|
-
border-radius: var(--radius-sm);
|
|
1215
|
-
cursor: pointer;
|
|
1216
|
-
white-space: nowrap;
|
|
1217
|
-
}
|
|
1218
|
-
|
|
1219
|
-
.sel-item-label { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; }
|
|
1220
|
-
|
|
1221
1982
|
/* Hover and keyboard land on the same row, because they are the same idea --
|
|
1222
1983
|
two highlights for one cursor is how a list starts lying about where Enter
|
|
1223
1984
|
will go. */
|
|
@@ -1229,8 +1990,6 @@ select,
|
|
|
1229
1990
|
|
|
1230
1991
|
/* The tick marks the chosen row. Colour alone would not: a list where the only
|
|
1231
1992
|
difference is a hue is a list you cannot read past. */
|
|
1232
|
-
.sel-tick { flex: none; opacity: 0; }
|
|
1233
|
-
|
|
1234
1993
|
.sel-item[data-selected] .sel-tick { opacity: 1; }
|
|
1235
1994
|
|
|
1236
1995
|
/* The icon on a speaker's row in the open list -- `Select`'s `aside`. Last in
|
|
@@ -1268,21 +2027,18 @@ select,
|
|
|
1268
2027
|
|
|
1269
2028
|
/* ---- ./dangerzone.css ---- */
|
|
1270
2029
|
/* Destructive, and legible as such standing still. */
|
|
1271
|
-
|
|
1272
|
-
a.btn.danger {
|
|
2030
|
+
.btn.danger {
|
|
1273
2031
|
color: var(--bad);
|
|
1274
2032
|
border-color: color-mix(in srgb, var(--bad) 45%, var(--border-strong));
|
|
1275
2033
|
}
|
|
1276
2034
|
|
|
1277
|
-
|
|
1278
|
-
a.btn.danger:hover:not([aria-disabled='true']) {
|
|
2035
|
+
.btn.danger:hover:not(:disabled) {
|
|
1279
2036
|
background: color-mix(in srgb, var(--bad) 12%, var(--panel));
|
|
1280
2037
|
border-color: var(--bad);
|
|
1281
2038
|
color: var(--bad);
|
|
1282
2039
|
}
|
|
1283
2040
|
|
|
1284
|
-
|
|
1285
|
-
a.btn.danger:active:not([aria-disabled='true']) {
|
|
2041
|
+
.btn.danger:active:not(:disabled) {
|
|
1286
2042
|
background: color-mix(in srgb, var(--bad) 20%, var(--panel));
|
|
1287
2043
|
border-color: var(--bad);
|
|
1288
2044
|
}
|
|
@@ -1523,33 +2279,46 @@ a.btn.danger:active:not([aria-disabled='true']) {
|
|
|
1523
2279
|
.callout button { flex: none; }
|
|
1524
2280
|
|
|
1525
2281
|
/* ---- ./card.css ---- */
|
|
2282
|
+
/* `.card` is public API, not this component's private styling.
|
|
2283
|
+
*
|
|
2284
|
+
* Consumers apply it to their own markup -- the gallery's skeleton specimen
|
|
2285
|
+
* renders `<div className="card">` around three rows, and app-template uses
|
|
2286
|
+
* `card-pick`. Moving the box into `Card`'s own class list took that away
|
|
2287
|
+
* with no type error and no failing test in this package: it broke only
|
|
2288
|
+
* where somebody else had used the class, which is the worst way for an API
|
|
2289
|
+
* to go.
|
|
2290
|
+
*
|
|
2291
|
+
* So the rule stays and `Card` wears it. The lesson generalises to every
|
|
2292
|
+
* class in this package that a consumer can reach: a component may draw
|
|
2293
|
+
* itself with utilities only where its class is genuinely private. */
|
|
1526
2294
|
.card {
|
|
2295
|
+
display: block;
|
|
2296
|
+
width: 100%;
|
|
2297
|
+
box-sizing: border-box;
|
|
2298
|
+
font: inherit;
|
|
2299
|
+
color: var(--text);
|
|
2300
|
+
text-align: left;
|
|
1527
2301
|
background: var(--panel);
|
|
1528
2302
|
border: var(--border-width) solid var(--border);
|
|
1529
2303
|
border-radius: var(--radius-md);
|
|
1530
|
-
padding: var(--space-3)
|
|
2304
|
+
padding: var(--space-3);
|
|
1531
2305
|
margin-bottom: var(--space-3);
|
|
1532
2306
|
}
|
|
1533
2307
|
|
|
2308
|
+
/* What is left once `Card` draws its own box: the tones, the pick and
|
|
2309
|
+
selected states, and the rules that reach from the card into what it
|
|
2310
|
+
holds. `:has(.card-icon) .card-inline` is a relationship, and a tone is a
|
|
2311
|
+
`color-mix`; neither is a property on one element. */
|
|
2312
|
+
|
|
1534
2313
|
/* Header, when there is one. The title and the line under it were retyped at
|
|
1535
2314
|
every call site and no two agreed on the gap between them. */
|
|
1536
|
-
.card-head { display: flex; align-items: flex-start; gap: var(--space-3); }
|
|
1537
|
-
|
|
1538
|
-
.card-head:not(:last-child) { margin-bottom: var(--space-3); }
|
|
1539
|
-
|
|
1540
|
-
.card-headings { min-width: 0; flex: 1; }
|
|
1541
|
-
|
|
1542
2315
|
/* The card owns the space between the things it holds. Without this a callout
|
|
1543
2316
|
and the button under it sit edge to edge, and every caller has to remember a
|
|
1544
2317
|
margin on whichever child happens to be second. */
|
|
1545
|
-
.card-body { display: grid; gap: var(--space-3); }
|
|
1546
|
-
|
|
1547
2318
|
/* The card's own control, on the card's padding rather than indented into its
|
|
1548
2319
|
body. Centred against the whole heading block, not against the title -- a
|
|
1549
2320
|
switch aligned to the first line drifts upward the moment the description
|
|
1550
2321
|
runs to two. */
|
|
1551
|
-
.card-action { flex: none; align-self: center; display: flex; align-items: center; }
|
|
1552
|
-
|
|
1553
2322
|
/* A row inside a card that lines up with the header rather than indenting past
|
|
1554
2323
|
it: same left edge as the title, same right edge as the action. Its label is
|
|
1555
2324
|
a quiet caption, not a second heading -- the card already has one, and two
|
|
@@ -1596,17 +2365,6 @@ a.btn.danger:active:not([aria-disabled='true']) {
|
|
|
1596
2365
|
color: var(--muted);
|
|
1597
2366
|
}
|
|
1598
2367
|
|
|
1599
|
-
/* A card that is itself the choice. Reset first, because it is a `<button>`
|
|
1600
|
-
now and inherits a control's padding and centring. */
|
|
1601
|
-
button.card {
|
|
1602
|
-
display: block;
|
|
1603
|
-
width: 100%;
|
|
1604
|
-
text-align: left;
|
|
1605
|
-
font: inherit;
|
|
1606
|
-
color: inherit;
|
|
1607
|
-
padding: var(--space-3);
|
|
1608
|
-
}
|
|
1609
|
-
|
|
1610
2368
|
/* Variants, because a card is doing four jobs and looked like one.
|
|
1611
2369
|
A search result you can act on, a thing already installed, something that
|
|
1612
2370
|
went wrong, and a heading with rows under it are not the same object, and
|
|
@@ -1649,6 +2407,20 @@ button.card {
|
|
|
1649
2407
|
|
|
1650
2408
|
.modal-body .card { background: var(--panel-2); }
|
|
1651
2409
|
|
|
2410
|
+
/* Selected, which used to arrive from `button[aria-pressed='true']`.
|
|
2411
|
+
*
|
|
2412
|
+
* A card marks its choice with `aria-pressed`, and the tint came from the
|
|
2413
|
+
* element rule every bare `<button>` in the package was picking up. That rule
|
|
2414
|
+
* belongs to `Button` now, so the card says what being chosen looks like --
|
|
2415
|
+
* which is the right place for it anyway: a chosen card is a card's idea, not
|
|
2416
|
+
* a button's. */
|
|
2417
|
+
.card[aria-pressed='true'] {
|
|
2418
|
+
border-color: var(--accent);
|
|
2419
|
+
background: color-mix(in srgb, var(--accent) 10%, var(--panel));
|
|
2420
|
+
}
|
|
2421
|
+
|
|
2422
|
+
.card[aria-pressed='true']:hover { border-color: var(--accent); }
|
|
2423
|
+
|
|
1652
2424
|
/* ---- ./toggle.css ---- */
|
|
1653
2425
|
.card-action .switch-row { padding: 0; gap: var(--space-2); }
|
|
1654
2426
|
|
|
@@ -2199,71 +2971,21 @@ input[type='radio']:active:not(:disabled) {
|
|
|
2199
2971
|
|
|
2200
2972
|
.row-hit:focus-visible { outline: none; box-shadow: var(--focus-ring); }
|
|
2201
2973
|
|
|
2202
|
-
/* ---- ./empty.css ---- */
|
|
2203
|
-
/* `Empty`: a list with nothing in it.
|
|
2204
|
-
|
|
2205
|
-
Quieter than `.empty`, which is a whole-screen state at `--space-10`. These
|
|
2206
|
-
sit inside a card that already has a heading and a description, so the same
|
|
2207
|
-
padding would leave a card that is mostly air about nothing.
|
|
2208
|
-
|
|
2209
|
-
Dashed rather than solid: a solid border reads as a thing, and the point of
|
|
2210
|
-
this box is that there is no thing. It marks out where the list will be. */
|
|
2211
|
-
.nothing {
|
|
2212
|
-
display: grid;
|
|
2213
|
-
justify-items: center;
|
|
2214
|
-
gap: var(--space-2);
|
|
2215
|
-
padding: var(--space-5) var(--space-4);
|
|
2216
|
-
border: var(--border-width) dashed var(--border-strong);
|
|
2217
|
-
border-radius: var(--radius-md);
|
|
2218
|
-
text-align: center;
|
|
2219
|
-
}
|
|
2220
|
-
|
|
2221
|
-
.nothing-mark { color: var(--muted); line-height: 0; }
|
|
2222
|
-
|
|
2223
|
-
/* The same box with a figure in it, for a whole surface rather than a slot in
|
|
2224
|
-
a card. Two things change and both follow from the size: the dashed outline
|
|
2225
|
-
goes, because an outline marks out where a list will be and a window-sized
|
|
2226
|
-
dashed rectangle reads as a layout that failed rather than a view with
|
|
2227
|
-
nothing on it; and the box centres itself in whatever it was dropped into,
|
|
2228
|
-
which is what makes it land in the middle of an empty dashboard rather than
|
|
2229
|
-
under the header. */
|
|
2230
|
-
.nothing-surface {
|
|
2231
|
-
border: none;
|
|
2232
|
-
padding: var(--space-10) var(--space-4);
|
|
2233
|
-
gap: var(--space-3);
|
|
2234
|
-
margin: auto;
|
|
2235
|
-
}
|
|
2236
|
-
|
|
2237
|
-
/* `currentColor` reaches the figure through the two rules the illustrations
|
|
2238
|
-
ship with, so the colour is set here and the drawing follows it -- the same
|
|
2239
|
-
grey as the sentence under it, in every theme.
|
|
2240
|
-
Two classes, not one: `.illo` sets `color: inherit` further down this file,
|
|
2241
|
-
which beats a single-class rule written earlier and drew the figure in full
|
|
2242
|
-
text black beside a muted sentence. */
|
|
2243
|
-
.nothing-surface .nothing-figure { color: var(--muted); }
|
|
2244
|
-
|
|
2245
|
-
/* `--text-sm`, not the `--text-xs` these lines used to be: it is a sentence
|
|
2246
|
-
somebody is meant to read, not a caption qualifying something else. */
|
|
2247
|
-
.nothing-said { margin: 0; color: var(--muted); font-size: var(--text-sm); line-height: 1.5; max-width: 46ch; }
|
|
2248
|
-
|
|
2249
|
-
.nothing-act { margin-top: var(--space-1); }
|
|
2250
|
-
|
|
2251
2974
|
/* ---- ./progress.css ---- */
|
|
2252
2975
|
/* progress ----------------------------------------------------------- */
|
|
2253
2976
|
|
|
2254
|
-
/* The bar
|
|
2977
|
+
/* The bar itself: a track with a child it fills, an animation and a
|
|
2978
|
+
reduced-motion answer. A utility is a property on one element, so none of
|
|
2979
|
+
that is one -- `Progress` draws its own wrapper and head with utilities and
|
|
2980
|
+
this is what is left.
|
|
2981
|
+
|
|
2982
|
+
The bar sat 4px under its own label and flush against whatever was above
|
|
2255
2983
|
the whole block, so a download row read as four lines of text with a rule
|
|
2256
2984
|
drawn through the last one. The label is a caption for the bar and stays
|
|
2257
2985
|
close to it; the block as a whole is a separate statement from the row it
|
|
2258
2986
|
follows. */
|
|
2259
|
-
.progress { display: grid; gap: var(--space-1); }
|
|
2260
|
-
|
|
2261
2987
|
.card > .progress { margin-top: var(--space-3); }
|
|
2262
2988
|
|
|
2263
|
-
.progress-head { display: flex; align-items: baseline; gap: var(--space-2); font-size: var(--text-sm); }
|
|
2264
|
-
|
|
2265
|
-
.progress-detail { color: var(--muted); font-size: var(--text-xs); }
|
|
2266
|
-
|
|
2267
2989
|
.bar { height: 6px; background: var(--panel-2); border-radius: var(--radius-pill); overflow: hidden; }
|
|
2268
2990
|
|
|
2269
2991
|
.bar > i {
|
|
@@ -2297,6 +3019,14 @@ input[type='radio']:active:not(:disabled) {
|
|
|
2297
3019
|
.tabs { position: relative; display: flex; gap: var(--space-1); }
|
|
2298
3020
|
|
|
2299
3021
|
.tab {
|
|
3022
|
+
/* Layout the `button` element rule used to supply. A tab is a button for its behaviour, not its look, so it now says what it wants instead of taking a control's arrangement and undoing the rest. */
|
|
3023
|
+
display: inline-flex;
|
|
3024
|
+
align-items: center;
|
|
3025
|
+
justify-content: center;
|
|
3026
|
+
gap: var(--space-2);
|
|
3027
|
+
/* Stated rather than inherited. These came from the `button, input, textarea, select` reset, which applied control styling to everything that happened to be a `<button>` -- so this rule spent its opening lines undoing it, and would break silently if that rule ever moved. It did move, to `.btn`. */
|
|
3028
|
+
font: inherit;
|
|
3029
|
+
cursor: pointer;
|
|
2300
3030
|
position: relative;
|
|
2301
3031
|
z-index: 1;
|
|
2302
3032
|
background: transparent;
|
|
@@ -2453,6 +3183,38 @@ input[type='radio']:active:not(:disabled) {
|
|
|
2453
3183
|
.toast[data-exiting] { animation: none; }
|
|
2454
3184
|
}
|
|
2455
3185
|
|
|
3186
|
+
/* The dismiss control, in its own words.
|
|
3187
|
+
*
|
|
3188
|
+
* It was `className="ghost size-sm"` -- `Button`'s vocabulary, borrowed from
|
|
3189
|
+
* a component that does not render a `Button`. That only ever worked because
|
|
3190
|
+
* `.ghost` and `.size-sm` were element-and-class rules any `<button>` could
|
|
3191
|
+
* pick up, which is the coupling this pass is removing. Nothing photographed
|
|
3192
|
+
* it, either: the toast is transient and the close button is not in any
|
|
3193
|
+
* baseline, so this would have gone quiet. */
|
|
3194
|
+
.toast-close {
|
|
3195
|
+
display: inline-flex;
|
|
3196
|
+
align-items: center;
|
|
3197
|
+
justify-content: center;
|
|
3198
|
+
font: inherit;
|
|
3199
|
+
font-size: var(--text-xs);
|
|
3200
|
+
padding: var(--space-1) var(--space-2);
|
|
3201
|
+
background: transparent;
|
|
3202
|
+
border: var(--border-width) solid transparent;
|
|
3203
|
+
border-radius: var(--radius);
|
|
3204
|
+
color: var(--muted);
|
|
3205
|
+
cursor: pointer;
|
|
3206
|
+
}
|
|
3207
|
+
|
|
3208
|
+
.toast-close:hover:not(:disabled) {
|
|
3209
|
+
background: var(--panel-2);
|
|
3210
|
+
color: var(--text);
|
|
3211
|
+
}
|
|
3212
|
+
|
|
3213
|
+
.toast-close:focus-visible {
|
|
3214
|
+
outline: 2px solid var(--accent);
|
|
3215
|
+
outline-offset: 2px;
|
|
3216
|
+
}
|
|
3217
|
+
|
|
2456
3218
|
/* ---- ./modal.css ---- */
|
|
2457
3219
|
/* modal --------------------------------------------------------------- */
|
|
2458
3220
|
|
|
@@ -2493,13 +3255,6 @@ input[type='radio']:active:not(:disabled) {
|
|
|
2493
3255
|
Not `display: contents`, which was the first attempt. An element with no box
|
|
2494
3256
|
cannot take focus, so React Aria's initial focus fell through to the first
|
|
2495
3257
|
input and Escape -- handled on the section -- stopped closing the window. */
|
|
2496
|
-
.modal-dialog {
|
|
2497
|
-
display: flex;
|
|
2498
|
-
flex-direction: column;
|
|
2499
|
-
min-height: 0;
|
|
2500
|
-
flex: 1;
|
|
2501
|
-
}
|
|
2502
|
-
|
|
2503
3258
|
.modal {
|
|
2504
3259
|
background: var(--panel);
|
|
2505
3260
|
border: 1px solid var(--border);
|
|
@@ -2550,18 +3305,9 @@ input[type='radio']:active:not(:disabled) {
|
|
|
2550
3305
|
laid out for the bare `<strong>` it used to hold -- 86px tall with them,
|
|
2551
3306
|
41px without, on a head whose padding is 12 over 8. `font: inherit` so the
|
|
2552
3307
|
`<strong>` rule above is the one that sets the size. */
|
|
2553
|
-
.modal-title { margin: 0; font: inherit; }
|
|
2554
|
-
|
|
2555
3308
|
/* Under the title, on the header's padding rather than the body's, so it reads
|
|
2556
3309
|
as part of the heading rather than as the first line of content. */
|
|
2557
|
-
.modal-desc {
|
|
2558
|
-
margin: 0;
|
|
2559
|
-
padding: 0 var(--space-4) var(--space-3);
|
|
2560
|
-
color: var(--muted);
|
|
2561
|
-
font-size: var(--text-sm);
|
|
2562
|
-
line-height: 1.5;
|
|
2563
|
-
max-width: 62ch;
|
|
2564
|
-
}
|
|
3310
|
+
.modal-desc { line-height: 1.5; }
|
|
2565
3311
|
|
|
2566
3312
|
.modal-body { padding: var(--space-2) var(--space-4) var(--space-3); overflow-y: auto; }
|
|
2567
3313
|
|
|
@@ -2921,7 +3667,8 @@ input[type='range'].slider:disabled::-moz-range-thumb { opacity: 0; }
|
|
|
2921
3667
|
buttons only, so a button in a row stood 25px beside a 35px select and no
|
|
2922
3668
|
size class could ask for the select's height. Type from the row, box from
|
|
2923
3669
|
the scale, and the two line up; an explicit `size-*` still wins. */
|
|
2924
|
-
:where(.set-row) button,
|
|
3670
|
+
:where(.set-row) button,
|
|
3671
|
+
:where(.set-row) .slider-box { font-size: var(--text-xs); }
|
|
2925
3672
|
|
|
2926
3673
|
/* ---- ./checkbox.css ---- */
|
|
2927
3674
|
/* A row you choose. There is no checkbox in it.
|
|
@@ -3099,30 +3846,28 @@ input[type='range'].slider:disabled::-moz-range-thumb { opacity: 0; }
|
|
|
3099
3846
|
one. The cell is bold because it is a heading; what hangs under it is not,
|
|
3100
3847
|
and inherited the weight -- so a pinned version read as loud as the thing it
|
|
3101
3848
|
versions. */
|
|
3102
|
-
.table th .set-hint { font-weight: 400; }
|
|
3849
|
+
.data-table th .set-hint { font-weight: 400; }
|
|
3103
3850
|
|
|
3104
|
-
.table
|
|
3105
|
-
|
|
3106
|
-
.table {
|
|
3851
|
+
.data-table {
|
|
3107
3852
|
width: 100%;
|
|
3108
3853
|
border-collapse: collapse;
|
|
3109
3854
|
font-size: var(--text-sm);
|
|
3110
3855
|
}
|
|
3111
3856
|
|
|
3112
|
-
.table th,
|
|
3113
|
-
.table td {
|
|
3857
|
+
.data-table th,
|
|
3858
|
+
.data-table td {
|
|
3114
3859
|
text-align: left;
|
|
3115
3860
|
padding: var(--space-2) var(--space-3);
|
|
3116
3861
|
border-bottom: var(--border-width) solid var(--border);
|
|
3117
3862
|
}
|
|
3118
3863
|
|
|
3119
|
-
.table th:first-child,
|
|
3120
|
-
.table td:first-child { padding-left: 0; }
|
|
3864
|
+
.data-table th:first-child,
|
|
3865
|
+
.data-table td:first-child { padding-left: 0; }
|
|
3121
3866
|
|
|
3122
|
-
.table th:last-child,
|
|
3123
|
-
.table td:last-child { padding-right: 0; }
|
|
3867
|
+
.data-table th:last-child,
|
|
3868
|
+
.data-table td:last-child { padding-right: 0; }
|
|
3124
3869
|
|
|
3125
|
-
.table thead th {
|
|
3870
|
+
.data-table thead th {
|
|
3126
3871
|
font-size: var(--text-xs);
|
|
3127
3872
|
font-weight: var(--weight-strong);
|
|
3128
3873
|
text-transform: uppercase;
|
|
@@ -3133,40 +3878,31 @@ input[type='range'].slider:disabled::-moz-range-thumb { opacity: 0; }
|
|
|
3133
3878
|
|
|
3134
3879
|
/* The row's own name: a `<th scope="row">`, so it carries weight rather than
|
|
3135
3880
|
reading as one more cell. */
|
|
3136
|
-
.table tbody th { font-weight: var(--weight-strong); }
|
|
3881
|
+
.data-table tbody th { font-weight: var(--weight-strong); }
|
|
3137
3882
|
|
|
3138
|
-
.table tbody tr:last-child th,
|
|
3139
|
-
.table tbody tr:last-child td { border-bottom: none; }
|
|
3883
|
+
.data-table tbody tr:last-child th,
|
|
3884
|
+
.data-table tbody tr:last-child td { border-bottom: none; }
|
|
3140
3885
|
|
|
3141
3886
|
/* Numbers compare by column, so they align right and hold their tracks --
|
|
3142
3887
|
proportional digits shift the alignment by a pixel per glyph, which is
|
|
3143
3888
|
exactly the comparison the column was for. */
|
|
3144
|
-
.table .num { text-align: right; font-variant-numeric: tabular-nums; font-family: var(--font-mono); }
|
|
3889
|
+
.data-table .num { text-align: right; font-variant-numeric: tabular-nums; font-family: var(--font-mono); }
|
|
3145
3890
|
|
|
3146
|
-
.table thead th[style*='right'] { text-align: right; }
|
|
3891
|
+
.data-table thead th[style*='right'] { text-align: right; }
|
|
3147
3892
|
|
|
3148
3893
|
/* ---- ./sizegrid.css ---- */
|
|
3149
|
-
/*
|
|
3150
|
-
|
|
3151
|
-
|
|
3152
|
-
|
|
3153
|
-
|
|
3154
|
-
|
|
3155
|
-
|
|
3156
|
-
|
|
3157
|
-
|
|
3894
|
+
/* What is left of the size grid once it draws itself.
|
|
3895
|
+
*
|
|
3896
|
+
* `on` follows the pointer; `chosen` is what is actually saved, shown only
|
|
3897
|
+
* when nothing is hovered so the two can never contradict each other.
|
|
3898
|
+
* `chosen` is a border colour and says so at the call site; `on` is a fill
|
|
3899
|
+
* mixed from the accent, and `color-mix` in an arbitrary value is less
|
|
3900
|
+
* readable than the rule it replaces. */
|
|
3901
|
+
.size-cell.on {
|
|
3902
|
+
border-color: var(--accent);
|
|
3903
|
+
background: color-mix(in srgb, var(--accent) 45%, transparent);
|
|
3158
3904
|
}
|
|
3159
3905
|
|
|
3160
|
-
/* `on` follows the pointer; `chosen` is what is actually saved, shown only
|
|
3161
|
-
when nothing is hovered so the two can never contradict each other. */
|
|
3162
|
-
.size-cell.on { border-color: var(--accent); background: color-mix(in srgb, var(--accent) 45%, transparent); }
|
|
3163
|
-
|
|
3164
|
-
.size-cell.chosen { border-color: var(--accent); }
|
|
3165
|
-
|
|
3166
|
-
.size-cell:disabled { cursor: default; opacity: 0.5; }
|
|
3167
|
-
|
|
3168
|
-
.size-ceiling { opacity: 0.55; }
|
|
3169
|
-
|
|
3170
3906
|
/* ---- ./tooltip.css ---- */
|
|
3171
3907
|
/* A callout: something worth knowing, with nothing to answer. Distinct from a
|
|
3172
3908
|
`?`, which is an offer to read more, and from a banner, which is a problem.
|
|
@@ -3175,36 +3911,15 @@ input[type='range'].slider:disabled::-moz-range-thumb { opacity: 0; }
|
|
|
3175
3911
|
/* An info-toned `.callout`, spelled the old way. Identical to it now rather than
|
|
3176
3912
|
nearly identical to it, which is the whole point of the consolidation: the
|
|
3177
3913
|
|
|
3178
|
-
/*
|
|
3914
|
+
/* What is left once `Tooltip` draws its own mark: the hover and focus that
|
|
3915
|
+
reach the mark from its parent, and the tip -- whose closed and open
|
|
3916
|
+
states are three rules the cascade resolves in order, with
|
|
3917
|
+
`data-entering` and `data-exiting` around the transition. None of that is
|
|
3918
|
+
a property on one element.
|
|
3919
|
+
|
|
3920
|
+
The `?` beside a setting, and the box it shows on hover. Built like the
|
|
3179
3921
|
status dot's tooltip and for the same reasons: `title` waits a second and a
|
|
3180
3922
|
half, renders newlines however it likes, and cannot be styled. */
|
|
3181
|
-
.explain {
|
|
3182
|
-
position: relative;
|
|
3183
|
-
flex: none;
|
|
3184
|
-
display: inline-flex;
|
|
3185
|
-
align-items: center;
|
|
3186
|
-
/* The heading it follows is tracked out, which leaves the last letter's
|
|
3187
|
-
spacing sitting between them and reads as none at all. */
|
|
3188
|
-
margin-left: var(--space-2);
|
|
3189
|
-
cursor: help;
|
|
3190
|
-
/* Headings here are uppercase and tracked out, and one of these sits inside
|
|
3191
|
-
a heading. */
|
|
3192
|
-
text-transform: none;
|
|
3193
|
-
letter-spacing: normal;
|
|
3194
|
-
font-weight: 400;
|
|
3195
|
-
}
|
|
3196
|
-
|
|
3197
|
-
.explain-mark {
|
|
3198
|
-
width: 18px;
|
|
3199
|
-
height: 18px;
|
|
3200
|
-
border-radius: 50%;
|
|
3201
|
-
border: 1px solid var(--border);
|
|
3202
|
-
color: var(--muted);
|
|
3203
|
-
font-size: var(--text-xs);
|
|
3204
|
-
line-height: 16px;
|
|
3205
|
-
text-align: center;
|
|
3206
|
-
}
|
|
3207
|
-
|
|
3208
3923
|
.explain:hover .explain-mark,
|
|
3209
3924
|
.explain:focus-visible .explain-mark { color: var(--text); border-color: var(--accent); }
|
|
3210
3925
|
|
|
@@ -3305,6 +4020,18 @@ input[type='range'].slider:disabled::-moz-range-thumb { opacity: 0; }
|
|
|
3305
4020
|
a shirt that lets the arm behind it show through reads as a hole. */
|
|
3306
4021
|
.illo .paper { fill: var(--illo-paper); }
|
|
3307
4022
|
|
|
4023
|
+
/* The figure in a whole-surface `Empty`, drawn in the muted grey of the
|
|
4024
|
+
sentence under it.
|
|
4025
|
+
*
|
|
4026
|
+
* A utility cannot do this, and the reason is worth keeping: `.illo` sets
|
|
4027
|
+
* `color: inherit` and is unlayered, while every Tailwind utility lives in
|
|
4028
|
+
* `@layer utilities` -- and an unlayered declaration beats a layered one
|
|
4029
|
+
* whatever the specificity. So `text-muted` on the figure lost, silently,
|
|
4030
|
+
* and the shirt came out full text black beside a muted sentence. The
|
|
4031
|
+
* original rule already carried a note about needing two classes to beat
|
|
4032
|
+
* `.illo`; layers make that impossible rather than merely fiddly. */
|
|
4033
|
+
.nothing-figure { color: var(--muted); }
|
|
4034
|
+
|
|
3308
4035
|
/* ---- ./field.css ---- */
|
|
3309
4036
|
/* fields --------------------------------------------------------------- */
|
|
3310
4037
|
|
|
@@ -3392,6 +4119,95 @@ input[type='range'].slider:disabled::-moz-range-thumb { opacity: 0; }
|
|
|
3392
4119
|
|
|
3393
4120
|
.secret-lg > .secret-eye { padding: var(--space-2); }
|
|
3394
4121
|
|
|
4122
|
+
/* An input with something inside its edges: a glyph on the left, a hint or a
|
|
4123
|
+
clear button on the right. Same arrangement as `.secret` above, and for the
|
|
4124
|
+
same reason -- one grid cell with everything stacked in it, and the room
|
|
4125
|
+
reserved in the input's own padding, so nothing is positioned against a
|
|
4126
|
+
height that changes with `size`. */
|
|
4127
|
+
.adorned { display: grid; align-items: center; }
|
|
4128
|
+
|
|
4129
|
+
.adorned > input,
|
|
4130
|
+
.adorned > .adorned-mark,
|
|
4131
|
+
.adorned > .adorned-end { grid-area: 1 / 1; }
|
|
4132
|
+
|
|
4133
|
+
.adorned.ctl-block { width: 100%; }
|
|
4134
|
+
|
|
4135
|
+
.adorned > .adorned-mark {
|
|
4136
|
+
justify-self: start;
|
|
4137
|
+
margin-left: var(--space-2);
|
|
4138
|
+
color: var(--muted);
|
|
4139
|
+
/* The glyph is decoration over the box; clicks belong to the input under
|
|
4140
|
+
it, which is otherwise unreachable in its own left edge. */
|
|
4141
|
+
pointer-events: none;
|
|
4142
|
+
/* Over the input, not under it. Both share one grid cell, the input has an
|
|
4143
|
+
opaque `--control` background, and it comes later in the DOM -- so
|
|
4144
|
+
without this the glyph is painted and then covered, which looks exactly
|
|
4145
|
+
like an icon that failed to render. `.secret` never hit this because its
|
|
4146
|
+
button is written after the input. */
|
|
4147
|
+
z-index: 1;
|
|
4148
|
+
}
|
|
4149
|
+
|
|
4150
|
+
/* Room for the glyph, on the scale, so a density change moves the text with
|
|
4151
|
+
the mark rather than leaving one behind. `--space-8` is what `.secret`
|
|
4152
|
+
reserves on the right for the same reason; the scale has no 7, and an
|
|
4153
|
+
undefined custom property does not fall back -- the declaration computes
|
|
4154
|
+
to 0 and the text sits under the glyph. */
|
|
4155
|
+
.adorned-icon > input { padding-left: var(--space-8); }
|
|
4156
|
+
|
|
4157
|
+
/* No `--space-12` on the scale; two steps that are, added. Same arithmetic
|
|
4158
|
+
as `.secret-lg`. */
|
|
4159
|
+
.adorned-icon.adorned-lg > input { padding-left: calc(var(--space-10) + var(--space-1)); }
|
|
4160
|
+
|
|
4161
|
+
.adorned > .adorned-end {
|
|
4162
|
+
justify-self: end;
|
|
4163
|
+
display: flex;
|
|
4164
|
+
align-items: center;
|
|
4165
|
+
gap: var(--space-1);
|
|
4166
|
+
margin-right: var(--space-1);
|
|
4167
|
+
}
|
|
4168
|
+
|
|
4169
|
+
/* `:has`, not a sibling combinator: the input comes *before* the end cap in
|
|
4170
|
+
the DOM, so `~` reads the wrong way and matches nothing. */
|
|
4171
|
+
.adorned:has(> .adorned-end) > input { padding-right: var(--space-8); }
|
|
4172
|
+
.adorned-lg:has(> .adorned-end) > input {
|
|
4173
|
+
padding-right: calc(var(--space-10) + var(--space-1));
|
|
4174
|
+
}
|
|
4175
|
+
|
|
4176
|
+
/* Sized from its glyph, not `.icon-btn`'s 34px tile, which would be taller
|
|
4177
|
+
than a small input -- the note above `.secret-eye` in full. */
|
|
4178
|
+
.adorned-clear {
|
|
4179
|
+
width: auto; height: auto;
|
|
4180
|
+
padding: var(--space-1);
|
|
4181
|
+
opacity: 1;
|
|
4182
|
+
}
|
|
4183
|
+
|
|
4184
|
+
.adorned-lg .adorned-clear { padding: var(--space-2); }
|
|
4185
|
+
|
|
4186
|
+
/* The eye and the clear button stop borrowing `ghost`.
|
|
4187
|
+
*
|
|
4188
|
+
* Both were `className="icon-btn ghost …"` -- reaching into `Button`'s class
|
|
4189
|
+
* vocabulary from another component, which worked only because `.ghost` was
|
|
4190
|
+
* written as `button.ghost` and they happen to be `<button>`s. It is `.btn.ghost`
|
|
4191
|
+
* now, so the borrowing stopped matching and `.icon-btn`'s panel background
|
|
4192
|
+
* came through: the baselines showed a filled tile where there had been a bare
|
|
4193
|
+
* glyph.
|
|
4194
|
+
*
|
|
4195
|
+
* Stated here instead. What they actually wanted from `ghost` is two lines,
|
|
4196
|
+
* and saying them is cheaper than either component knowing what a button's
|
|
4197
|
+
* classes are called. */
|
|
4198
|
+
.secret-eye,
|
|
4199
|
+
.adorned-clear {
|
|
4200
|
+
background: transparent;
|
|
4201
|
+
border-color: transparent;
|
|
4202
|
+
color: var(--muted);
|
|
4203
|
+
}
|
|
4204
|
+
|
|
4205
|
+
.secret-eye:hover:not(:disabled),
|
|
4206
|
+
.adorned-clear:hover:not(:disabled) {
|
|
4207
|
+
background: var(--panel-2);
|
|
4208
|
+
color: var(--text);
|
|
4209
|
+
}
|
|
4210
|
+
|
|
3395
4211
|
/* ---- ./tour.css ---- */
|
|
3396
4212
|
/* tour ----------------------------------------------------------------- */
|
|
3397
4213
|
|
|
@@ -3459,72 +4275,46 @@ input[type='range'].slider:disabled::-moz-range-thumb { opacity: 0; }
|
|
|
3459
4275
|
anchored surfaces (`.pop`, `.menu-sheet`, `.cmd`) sit over everything and a
|
|
3460
4276
|
rule of equal specificity that came earlier would lose to whatever the
|
|
3461
4277
|
sheets they cover happen to set. */
|
|
3462
|
-
/* ---- ./kbd.css ---- */
|
|
3463
|
-
/* One rule where there were two identical ones, in `menu.css` and
|
|
3464
|
-
`command.css`. Both keep their class as well, so `Menu` and `Command` are
|
|
3465
|
-
`.kbd .menu-key` and `.kbd .cmd-key` now: the declarations are the same, so
|
|
3466
|
-
nothing moves, and the context classes stay available for a rule that ever
|
|
3467
|
-
needs to tell the two apart. */
|
|
3468
|
-
.kbd {
|
|
3469
|
-
flex: none;
|
|
3470
|
-
font-family: var(--font-mono);
|
|
3471
|
-
font-size: var(--text-2xs);
|
|
3472
|
-
color: var(--muted);
|
|
3473
|
-
letter-spacing: var(--tracking);
|
|
3474
|
-
}
|
|
3475
|
-
|
|
3476
4278
|
/* ---- ./stat.css ---- */
|
|
3477
|
-
/*
|
|
3478
|
-
|
|
3479
|
-
.
|
|
3480
|
-
display: grid;
|
|
3481
|
-
gap: var(--space-1);
|
|
3482
|
-
padding: var(--space-4);
|
|
3483
|
-
border: var(--border-width) solid var(--border);
|
|
3484
|
-
border-radius: var(--radius-md);
|
|
3485
|
-
background: var(--panel);
|
|
3486
|
-
}
|
|
3487
|
-
|
|
3488
|
-
/* Inside something already bordered. A bordered tile in a bordered row is two
|
|
3489
|
-
boxes saying one thing. */
|
|
3490
|
-
.stat-bare {
|
|
3491
|
-
padding: 0;
|
|
3492
|
-
border: 0;
|
|
3493
|
-
border-radius: 0;
|
|
3494
|
-
background: none;
|
|
3495
|
-
gap: 0;
|
|
3496
|
-
line-height: 1.25;
|
|
3497
|
-
}
|
|
3498
|
-
|
|
3499
|
-
.stat > p { margin: 0; }
|
|
4279
|
+
/* What the utilities on `Stat` cannot say: a tone on the tile colouring the
|
|
4280
|
+
figure inside it. An attribute on the parent selecting a child is a
|
|
4281
|
+
relationship; a utility is a property on one element.
|
|
3500
4282
|
|
|
3501
|
-
.
|
|
3502
|
-
|
|
3503
|
-
|
|
3504
|
-
}
|
|
4283
|
+
Only the figure takes the colour. Colouring the label too makes the tile a
|
|
4284
|
+
status box, where a tone here is a remark about the number. */
|
|
4285
|
+
.stat[data-tone='info'] .stat-value { color: var(--info); }
|
|
4286
|
+
.stat[data-tone='good'] .stat-value { color: var(--good); }
|
|
4287
|
+
.stat[data-tone='warn'] .stat-value { color: var(--warn); }
|
|
4288
|
+
.stat[data-tone='bad'] .stat-value { color: var(--bad); }
|
|
3505
4289
|
|
|
3506
|
-
/*
|
|
3507
|
-
|
|
3508
|
-
|
|
3509
|
-
|
|
3510
|
-
|
|
3511
|
-
|
|
4290
|
+
/* ---- ./shell.css ---- */
|
|
4291
|
+
/* The measure, and only the measure.
|
|
4292
|
+
*
|
|
4293
|
+
* `Shell` draws itself with utilities -- it is layout and nothing else. What
|
|
4294
|
+
* stays here is the one value the header band, the nav band and the main band
|
|
4295
|
+
* all have to agree on: a custom property, so an app changes it in one place
|
|
4296
|
+
* rather than overriding three rules and missing the fourth. That is how
|
|
4297
|
+
* manage ended up carrying `head-inner-wide` and `main-wide` as separate
|
|
4298
|
+
* classes it had to remember together. */
|
|
4299
|
+
.shell {
|
|
4300
|
+
--shell-measure: 64rem;
|
|
4301
|
+
--shell-measure-wide: 90rem;
|
|
4302
|
+
}
|
|
4303
|
+
|
|
4304
|
+
/* The label beside the theme control, when it is drawn. */
|
|
4305
|
+
.theme-switch {
|
|
4306
|
+
display: flex;
|
|
4307
|
+
align-items: center;
|
|
4308
|
+
gap: var(--space-2);
|
|
4309
|
+
min-width: 0;
|
|
3512
4310
|
}
|
|
3513
4311
|
|
|
3514
|
-
.
|
|
3515
|
-
|
|
3516
|
-
.stat-note {
|
|
4312
|
+
.theme-switch-label {
|
|
3517
4313
|
color: var(--muted);
|
|
3518
|
-
font-size: var(--text-
|
|
4314
|
+
font-size: var(--text-sm);
|
|
4315
|
+
white-space: nowrap;
|
|
3519
4316
|
}
|
|
3520
4317
|
|
|
3521
|
-
/* Only the figure takes the colour. Colouring the label too makes the tile a
|
|
3522
|
-
status box, and a tone here is a remark about the number. */
|
|
3523
|
-
.stat[data-tone='info'] .stat-value { color: var(--info); }
|
|
3524
|
-
.stat[data-tone='good'] .stat-value { color: var(--good); }
|
|
3525
|
-
.stat[data-tone='warn'] .stat-value { color: var(--warn); }
|
|
3526
|
-
.stat[data-tone='bad'] .stat-value { color: var(--bad); }
|
|
3527
|
-
|
|
3528
4318
|
/* ---- ./scrollarea.css ---- */
|
|
3529
4319
|
/* A box that scrolls, with its edges drawn.
|
|
3530
4320
|
|
|
@@ -3776,27 +4566,13 @@ body.splitting * { cursor: inherit !important; }
|
|
|
3776
4566
|
}
|
|
3777
4567
|
|
|
3778
4568
|
/* ---- ./menu.css ---- */
|
|
3779
|
-
/*
|
|
3780
|
-
|
|
3781
|
-
|
|
3782
|
-
|
|
3783
|
-
|
|
3784
|
-
box-shadow: var(--shadow-2);
|
|
3785
|
-
min-width: 12rem;
|
|
3786
|
-
max-width: min(20rem, calc(100vw - var(--space-6)));
|
|
3787
|
-
max-height: 24rem;
|
|
3788
|
-
overflow: auto;
|
|
3789
|
-
overscroll-behavior: contain;
|
|
3790
|
-
z-index: 60;
|
|
3791
|
-
}
|
|
3792
|
-
|
|
3793
|
-
.menu-list {
|
|
3794
|
-
padding: var(--space-1);
|
|
3795
|
-
outline: none;
|
|
3796
|
-
display: grid;
|
|
3797
|
-
gap: var(--border-width);
|
|
3798
|
-
}
|
|
4569
|
+
/* What is left once `Menu` draws its sheet and its list: the rows, whose
|
|
4570
|
+
`data-focused`, `data-pressed` and danger states React Aria stamps on
|
|
4571
|
+
them, and the rules that reach from a row into what it holds. The
|
|
4572
|
+
`box-shadow` stays on the sheet too -- `--shadow-2` is a token, and a
|
|
4573
|
+
utility would have to inline it. */
|
|
3799
4574
|
|
|
4575
|
+
/* A list of verbs, on the same sheet as every other anchored surface. */
|
|
3800
4576
|
.menu-item {
|
|
3801
4577
|
display: flex;
|
|
3802
4578
|
align-items: center;
|
|
@@ -3835,14 +4611,6 @@ body.splitting * { cursor: inherit !important; }
|
|
|
3835
4611
|
/* The binding, set in the mono face at the size of the small print. Right of
|
|
3836
4612
|
the row and never the reason the row is wide: `flex: none` with the label
|
|
3837
4613
|
taking the slack. */
|
|
3838
|
-
.menu-key {
|
|
3839
|
-
flex: none;
|
|
3840
|
-
font-family: var(--font-mono);
|
|
3841
|
-
font-size: var(--text-2xs);
|
|
3842
|
-
color: var(--muted);
|
|
3843
|
-
letter-spacing: var(--tracking);
|
|
3844
|
-
}
|
|
3845
|
-
|
|
3846
4614
|
.menu-more { flex: none; color: var(--muted); }
|
|
3847
4615
|
|
|
3848
4616
|
.menu-rule {
|
|
@@ -3878,6 +4646,8 @@ body.splitting * { cursor: inherit !important; }
|
|
|
3878
4646
|
.menu-sheet[data-exiting] { animation: none; }
|
|
3879
4647
|
}
|
|
3880
4648
|
|
|
4649
|
+
.menu-sheet { box-shadow: var(--shadow-2); }
|
|
4650
|
+
|
|
3881
4651
|
/* ---- ./command.css ---- */
|
|
3882
4652
|
/* The command palette: a field over the app and a list under it. */
|
|
3883
4653
|
.cmd-scrim {
|
|
@@ -3995,14 +4765,6 @@ body.splitting * { cursor: inherit !important; }
|
|
|
3995
4765
|
white-space: nowrap;
|
|
3996
4766
|
}
|
|
3997
4767
|
|
|
3998
|
-
.cmd-key {
|
|
3999
|
-
flex: none;
|
|
4000
|
-
font-family: var(--font-mono);
|
|
4001
|
-
font-size: var(--text-2xs);
|
|
4002
|
-
color: var(--muted);
|
|
4003
|
-
letter-spacing: var(--tracking);
|
|
4004
|
-
}
|
|
4005
|
-
|
|
4006
4768
|
.cmd-empty {
|
|
4007
4769
|
margin: 0;
|
|
4008
4770
|
padding: var(--space-6) var(--space-4);
|
|
@@ -4030,23 +4792,14 @@ body.splitting * { cursor: inherit !important; }
|
|
|
4030
4792
|
}
|
|
4031
4793
|
|
|
4032
4794
|
/* ---- ./pagination.css ---- */
|
|
4033
|
-
/*
|
|
4034
|
-
|
|
4035
|
-
|
|
4036
|
-
|
|
4037
|
-
justify-content: space-between;
|
|
4038
|
-
gap: var(--space-4);
|
|
4039
|
-
flex-wrap: wrap;
|
|
4040
|
-
padding: var(--space-2) 0;
|
|
4041
|
-
font-size: var(--text-xs);
|
|
4042
|
-
color: var(--muted);
|
|
4043
|
-
}
|
|
4795
|
+
/* What is left once `Pagination` draws its own frame: the step and page
|
|
4796
|
+
buttons, whose hover, focus-visible and current states are pseudo-classes
|
|
4797
|
+
on two selectors at once, and `.pager-count strong`, which reaches into
|
|
4798
|
+
text the caller passed. */
|
|
4044
4799
|
|
|
4045
|
-
|
|
4800
|
+
/* Moving through a list that does not fit, and saying how far in you are. */
|
|
4046
4801
|
.pager-count strong { color: var(--text); font-weight: var(--weight-strong); }
|
|
4047
4802
|
|
|
4048
|
-
.pager-controls { display: flex; align-items: center; gap: var(--space-1); }
|
|
4049
|
-
|
|
4050
4803
|
.pager-step,
|
|
4051
4804
|
.pager-page {
|
|
4052
4805
|
display: inline-flex;
|
|
@@ -4238,6 +4991,8 @@ body.splitting * { cursor: inherit !important; }
|
|
|
4238
4991
|
}
|
|
4239
4992
|
|
|
4240
4993
|
.ident-remove {
|
|
4994
|
+
/* Stated rather than inherited. These came from the `button, input, textarea, select` reset, which applied control styling to everything that happened to be a `<button>` -- so this rule spent its opening lines undoing it, and would break silently if that rule ever moved. It did move, to `.btn`. */
|
|
4995
|
+
font: inherit;
|
|
4241
4996
|
flex: none;
|
|
4242
4997
|
display: inline-flex;
|
|
4243
4998
|
align-items: center;
|