@juxtui/ui 0.1.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.
Files changed (58) hide show
  1. package/README.md +1 -1
  2. package/dist/components/accordion/JAccordion.vue.d.ts +34 -0
  3. package/dist/components/accordion/JAccordionItem.vue.d.ts +19 -0
  4. package/dist/components/accordion/context.d.ts +7 -0
  5. package/dist/components/alert/JAlert.vue.d.ts +30 -0
  6. package/dist/components/aspect-ratio/JAspectRatio.vue.d.ts +18 -0
  7. package/dist/components/avatar/JAvatar.vue.d.ts +1 -1
  8. package/dist/components/avatar-group/JAvatarGroup.vue.d.ts +19 -0
  9. package/dist/components/badge/JBadge.vue.d.ts +1 -1
  10. package/dist/components/banner/JBanner.vue.d.ts +30 -0
  11. package/dist/components/breadcrumb/JBreadcrumb.vue.d.ts +29 -0
  12. package/dist/components/button/JButton.vue.d.ts +1 -1
  13. package/dist/components/card/JCard.vue.d.ts +1 -1
  14. package/dist/components/collapsible/JCollapsible.vue.d.ts +28 -0
  15. package/dist/components/command-palette/JCommandPalette.vue.d.ts +1 -1
  16. package/dist/components/dropdown-menu/JDropdownMenu.vue.d.ts +1 -1
  17. package/dist/components/empty-state/JEmptyState.vue.d.ts +23 -0
  18. package/dist/components/field/JFieldShell.vue.d.ts +1 -1
  19. package/dist/components/input/JInput.vue.d.ts +2 -2
  20. package/dist/components/kbd/JKbd.vue.d.ts +22 -0
  21. package/dist/components/pagination/JPagination.vue.d.ts +25 -0
  22. package/dist/components/popover/JPopover.vue.d.ts +43 -0
  23. package/dist/components/primitives/JSlot.d.ts +1 -1
  24. package/dist/components/progress/JProgress.vue.d.ts +20 -0
  25. package/dist/components/radio/JRadio.vue.d.ts +20 -0
  26. package/dist/components/radio/JRadioGroup.vue.d.ts +38 -0
  27. package/dist/components/radio/context.d.ts +11 -0
  28. package/dist/components/rating/JRating.vue.d.ts +27 -0
  29. package/dist/components/select/JSelect.vue.d.ts +1 -1
  30. package/dist/components/separator/JSeparator.vue.d.ts +25 -0
  31. package/dist/components/sheet/JSheet.vue.d.ts +53 -0
  32. package/dist/components/skeleton/JSkeleton.vue.d.ts +15 -0
  33. package/dist/components/slider/JSlider.vue.d.ts +31 -0
  34. package/dist/components/spinner/JSpinner.vue.d.ts +11 -0
  35. package/dist/components/stat/JStat.vue.d.ts +22 -0
  36. package/dist/components/switch/JSwitch.vue.d.ts +1 -1
  37. package/dist/components/tabs/JTabs.vue.d.ts +1 -1
  38. package/dist/components/tag/JTag.vue.d.ts +28 -0
  39. package/dist/components/timeline/JTimeline.vue.d.ts +12 -0
  40. package/dist/components/timeline/JTimelineItem.vue.d.ts +24 -0
  41. package/dist/components/toast/JToaster.vue.d.ts +1 -1
  42. package/dist/components/toggle-group/JToggleGroup.vue.d.ts +33 -0
  43. package/dist/components/toggle-group/JToggleGroupItem.vue.d.ts +19 -0
  44. package/dist/components/toggle-group/context.d.ts +9 -0
  45. package/dist/components/tooltip/JTooltip.vue.d.ts +1 -1
  46. package/dist/components/visually-hidden/JVisuallyHidden.vue.d.ts +19 -0
  47. package/dist/components.d.ts +28 -0
  48. package/dist/composables/useModal.d.ts +20 -0
  49. package/dist/composables/useToast.d.ts +1 -1
  50. package/dist/icons.d.ts +4 -0
  51. package/dist/index.d.ts +29 -0
  52. package/dist/index.js +3914 -2165
  53. package/dist/index.js.map +1 -1
  54. package/dist/nuxt.js +29 -1
  55. package/dist/nuxt.js.map +1 -1
  56. package/dist/style.css +1874 -139
  57. package/dist/tokens.css +5 -5
  58. package/package.json +1 -1
package/dist/style.css CHANGED
@@ -4,7 +4,7 @@
4
4
  /*
5
5
  * Juxt's component styles live in the `juxt` cascade layer. The order below
6
6
  * puts it above CSS resets (Tailwind's `base`) and below utilities, so a
7
- * class like `hidden` or `w-full` on a component always wins — and any
7
+ * class like `hidden` or `w-full` on a component always wins | and any
8
8
  * unlayered CSS of your own does too. Without Tailwind the extra names are
9
9
  * simply empty layers.
10
10
  */
@@ -13,7 +13,7 @@
13
13
  * Juxt design tokens
14
14
  *
15
15
  * One source of truth for colour, space, radius, type, elevation, motion and
16
- * layering. Components never hardcode these values — they read them here.
16
+ * layering. Components never hardcode these values | they read them here.
17
17
  *
18
18
  * Light is the default. Dark applies under `.dark` or `[data-theme="dark"]`
19
19
  * on any ancestor (usually <html>).
@@ -44,7 +44,7 @@
44
44
  --juxt-fg-muted: #71717a;
45
45
  --juxt-fg-disabled: #a1a1aa;
46
46
 
47
- /* Ink — the inverted neutral used by primary actions */
47
+ /* Ink | the inverted neutral used by primary actions */
48
48
  --juxt-ink: #09090b;
49
49
  --juxt-ink-hover: #27272a;
50
50
  --juxt-ink-fg: #fafafa;
@@ -84,7 +84,7 @@
84
84
  --juxt-success-soft: var(--juxt-accent-soft);
85
85
  --juxt-success-border: var(--juxt-accent-border);
86
86
 
87
- /* Elevation — borders do most of the work, shadows only lift */
87
+ /* Elevation | borders do most of the work, shadows only lift */
88
88
  --juxt-shadow-xs: 0 1px 1px rgb(9 9 11 / 0.04);
89
89
  --juxt-shadow-sm: 0 1px 2px rgb(9 9 11 / 0.05), 0 1px 1px rgb(9 9 11 / 0.03);
90
90
  --juxt-shadow-md: 0 4px 12px -2px rgb(9 9 11 / 0.08), 0 2px 4px -2px rgb(9 9 11 / 0.05);
@@ -186,7 +186,7 @@
186
186
  --juxt-tracking-tight: -0.011em;
187
187
  --juxt-tracking-tighter: -0.022em;
188
188
 
189
- /* Space — a 4px grid */
189
+ /* Space | a 4px grid */
190
190
  --juxt-space-0-5: 0.125rem; /* 2 */
191
191
  --juxt-space-1: 0.25rem; /* 4 */
192
192
  --juxt-space-1-5: 0.375rem; /* 6 */
@@ -239,7 +239,7 @@
239
239
 
240
240
  @media (prefers-reduced-motion: reduce) {
241
241
  :root {
242
- /* Things still fade — they just stop travelling. */
242
+ /* Things still fade | they just stop travelling. */
243
243
  --juxt-motion-shift: 0px;
244
244
  --juxt-motion-scale: 1;
245
245
  --juxt-duration-slow: 140ms;
@@ -462,6 +462,235 @@
462
462
  }
463
463
  }
464
464
 
465
+ @layer theme, base, juxt, components, utilities;
466
+ @layer juxt {
467
+ .j-accordion {
468
+ display: flex;
469
+ flex-direction: column;
470
+ font-family: var(--juxt-font-sans);
471
+ }
472
+ }
473
+
474
+ @layer theme, base, juxt, components, utilities;
475
+ @layer juxt {
476
+ .j-accordion__item {
477
+ border-bottom: 1px solid var(--juxt-border-subtle);
478
+ }
479
+ .dark .j-accordion__item,
480
+ [data-theme='dark'] .j-accordion__item {
481
+ border-bottom-color: var(--juxt-border);
482
+ }
483
+ .j-accordion__heading {
484
+ margin: 0;
485
+ font: inherit;
486
+ }
487
+ .j-accordion__trigger {
488
+ display: flex;
489
+ align-items: center;
490
+ justify-content: space-between;
491
+ gap: var(--juxt-space-4);
492
+ width: 100%;
493
+ min-height: 3rem;
494
+ padding: var(--juxt-space-3) 0;
495
+ border: 0;
496
+ border-radius: var(--juxt-radius-xs);
497
+ background: transparent;
498
+ color: var(--juxt-fg);
499
+ font: inherit;
500
+ font-size: var(--juxt-text-md);
501
+ font-weight: var(--juxt-weight-medium);
502
+ letter-spacing: var(--juxt-tracking-tight);
503
+ text-align: left;
504
+ cursor: pointer;
505
+ outline: 2px solid transparent;
506
+ outline-offset: 0;
507
+ -webkit-tap-highlight-color: transparent;
508
+ transition:
509
+ color var(--juxt-duration-fast) var(--juxt-ease-standard),
510
+ outline-color var(--juxt-duration-fast) var(--juxt-ease-out),
511
+ outline-offset var(--juxt-duration-fast) var(--juxt-ease-out);
512
+ }
513
+ .j-accordion__trigger:focus-visible {
514
+ outline-color: var(--juxt-ring);
515
+ outline-offset: 2px;
516
+ }
517
+ .j-accordion__trigger:disabled {
518
+ color: var(--juxt-fg-disabled);
519
+ cursor: not-allowed;
520
+ }
521
+ .j-accordion__chevron {
522
+ flex: none;
523
+ width: 1rem;
524
+ height: 1rem;
525
+ color: var(--juxt-fg-muted);
526
+ transition:
527
+ transform var(--juxt-duration-normal) var(--juxt-ease-out),
528
+ color var(--juxt-duration-fast) var(--juxt-ease-standard);
529
+ }
530
+ .j-accordion__trigger:hover:not(:disabled) .j-accordion__chevron {
531
+ color: var(--juxt-fg);
532
+ }
533
+ .j-accordion__item[data-state='open'] .j-accordion__chevron {
534
+ transform: rotate(180deg);
535
+ }
536
+
537
+ /* Height follows content via grid rows | no measuring, no magic numbers. */
538
+ .j-accordion__panel {
539
+ display: grid;
540
+ grid-template-rows: 0fr;
541
+ transition: grid-template-rows var(--juxt-duration-slow) var(--juxt-ease-out);
542
+ }
543
+ .j-accordion__item[data-state='open'] .j-accordion__panel {
544
+ grid-template-rows: 1fr;
545
+ }
546
+ .j-accordion__panel-inner {
547
+ min-height: 0;
548
+ overflow: hidden;
549
+ }
550
+ .j-accordion__content {
551
+ padding-bottom: var(--juxt-space-4);
552
+ color: var(--juxt-fg-secondary);
553
+ font-size: var(--juxt-text-md);
554
+ line-height: var(--juxt-leading-normal);
555
+ opacity: 0;
556
+ transition: opacity var(--juxt-duration-fast) var(--juxt-ease-standard);
557
+ }
558
+ .j-accordion__item[data-state='open'] .j-accordion__content {
559
+ opacity: 1;
560
+ transition-delay: 60ms;
561
+ }
562
+ @media (prefers-reduced-motion: reduce) {
563
+ .j-accordion__panel,
564
+ .j-accordion__chevron {
565
+ transition: none;
566
+ }
567
+ }
568
+ }
569
+
570
+ @layer theme, base, juxt, components, utilities;
571
+ @layer juxt {
572
+ /*
573
+ * Alerts stay on the page's surface. Colour lives in the icon and a hairline
574
+ * of the border | enough to be noticed, never enough to shout.
575
+ */
576
+ .j-alert {
577
+ --j-alert-accent: var(--juxt-fg-muted);
578
+ --j-alert-border: var(--juxt-border);
579
+
580
+ position: relative;
581
+ display: flex;
582
+ align-items: flex-start;
583
+ gap: var(--juxt-space-3);
584
+ padding: var(--juxt-space-3) var(--juxt-space-4);
585
+ border: 1px solid var(--j-alert-border);
586
+ border-radius: var(--juxt-radius-md);
587
+ background: var(--juxt-surface);
588
+ color: var(--juxt-fg);
589
+ font-family: var(--juxt-font-sans);
590
+ }
591
+ .j-alert--info {
592
+ --j-alert-accent: var(--juxt-info-text);
593
+ }
594
+ .j-alert--success {
595
+ --j-alert-accent: var(--juxt-success-text);
596
+ }
597
+ .j-alert--warning {
598
+ --j-alert-accent: var(--juxt-warning-text);
599
+ --j-alert-border: var(--juxt-warning-border);
600
+ }
601
+ .j-alert--destructive {
602
+ --j-alert-accent: var(--juxt-danger-text);
603
+ --j-alert-border: var(--juxt-danger-border);
604
+ }
605
+ .j-alert__icon {
606
+ display: grid;
607
+ flex: none;
608
+ place-items: center;
609
+ height: 1.25rem;
610
+ color: var(--j-alert-accent);
611
+ }
612
+ .j-alert__icon > svg {
613
+ width: 1rem;
614
+ height: 1rem;
615
+ }
616
+ .j-alert__body {
617
+ display: flex;
618
+ flex: 1;
619
+ flex-direction: column;
620
+ gap: var(--juxt-space-0-5);
621
+ min-width: 0;
622
+ }
623
+ .j-alert__title {
624
+ margin: 0;
625
+ font-size: var(--juxt-text-md);
626
+ font-weight: var(--juxt-weight-medium);
627
+ line-height: 1.25rem;
628
+ letter-spacing: var(--juxt-tracking-tight);
629
+ }
630
+ .j-alert__description {
631
+ color: var(--juxt-fg-secondary);
632
+ font-size: var(--juxt-text-sm);
633
+ line-height: var(--juxt-leading-normal);
634
+ }
635
+ .j-alert__description > p {
636
+ margin: 0;
637
+ }
638
+ .j-alert__actions {
639
+ display: flex;
640
+ flex-wrap: wrap;
641
+ gap: var(--juxt-space-2);
642
+ margin-top: var(--juxt-space-2);
643
+ }
644
+ .j-alert:has(.j-alert__close) {
645
+ padding-right: var(--juxt-space-10);
646
+ }
647
+ .j-alert__close {
648
+ position: absolute;
649
+ top: var(--juxt-space-2-5);
650
+ right: var(--juxt-space-2-5);
651
+ display: grid;
652
+ place-items: center;
653
+ width: 1.5rem;
654
+ height: 1.5rem;
655
+ padding: 0;
656
+ border: 0;
657
+ border-radius: var(--juxt-radius-xs);
658
+ background: transparent;
659
+ color: var(--juxt-fg-muted);
660
+ cursor: pointer;
661
+ transition-property: background-color, color, outline-color, outline-offset;
662
+ }
663
+ .j-alert__close:hover {
664
+ background: var(--juxt-surface-hover);
665
+ color: var(--juxt-fg);
666
+ }
667
+ .j-alert__close > svg {
668
+ width: 0.875rem;
669
+ height: 0.875rem;
670
+ }
671
+ }
672
+
673
+ @layer theme, base, juxt, components, utilities;
674
+ @layer juxt {
675
+ .j-aspect-ratio {
676
+ position: relative;
677
+ width: 100%;
678
+ aspect-ratio: var(--j-aspect-ratio, 16 / 9);
679
+ }
680
+ .j-aspect-ratio__content {
681
+ position: absolute;
682
+ inset: 0;
683
+ overflow: hidden;
684
+ }
685
+ .j-aspect-ratio__content > :where(img, video, iframe, canvas) {
686
+ display: block;
687
+ width: 100%;
688
+ height: 100%;
689
+ object-fit: cover;
690
+ }
691
+ }
692
+
693
+ @layer theme, base, juxt, components, utilities;
465
694
  @layer juxt {
466
695
  .j-avatar {
467
696
  --j-avatar-size: 2rem;
@@ -574,9 +803,65 @@
574
803
  }
575
804
  }
576
805
 
806
+ @layer theme, base, juxt, components, utilities;
807
+ @layer juxt {
808
+ .j-avatar-group {
809
+ --j-avatar-group-overlap: 0.5em;
810
+
811
+ display: inline-flex;
812
+ align-items: center;
813
+ font-family: var(--juxt-font-sans);
814
+ }
815
+ .j-avatar-group__item {
816
+ position: relative;
817
+ display: inline-flex;
818
+ flex: none;
819
+ border-radius: var(--juxt-radius-full);
820
+ box-shadow: 0 0 0 2px var(--juxt-bg);
821
+ }
822
+ .j-avatar-group__item:not(:first-child) {
823
+ margin-left: calc(var(--j-avatar-group-overlap) * -1);
824
+ }
825
+ .j-avatar-group__overflow {
826
+ display: grid;
827
+ place-items: center;
828
+ width: 2rem;
829
+ height: 2rem;
830
+ background: var(--juxt-surface-active);
831
+ color: var(--juxt-fg-secondary);
832
+ font-size: var(--juxt-text-xs);
833
+ font-weight: var(--juxt-weight-medium);
834
+ font-variant-numeric: tabular-nums;
835
+ }
836
+ .j-avatar-group--xs .j-avatar-group__overflow {
837
+ width: 1.25rem;
838
+ height: 1.25rem;
839
+ font-size: var(--juxt-text-2xs);
840
+ }
841
+ .j-avatar-group--sm .j-avatar-group__overflow {
842
+ width: 1.5rem;
843
+ height: 1.5rem;
844
+ font-size: 0.625rem;
845
+ }
846
+ .j-avatar-group--lg .j-avatar-group__overflow {
847
+ width: 2.5rem;
848
+ height: 2.5rem;
849
+ font-size: var(--juxt-text-sm);
850
+ }
851
+ .j-avatar-group--xl .j-avatar-group__overflow {
852
+ width: 3.5rem;
853
+ height: 3.5rem;
854
+ font-size: var(--juxt-text-lg);
855
+ }
856
+ .j-avatar-group__overflow--square {
857
+ border-radius: 22%;
858
+ }
859
+ }
860
+
861
+ @layer theme, base, juxt, components, utilities;
577
862
  @layer juxt {
578
863
  /*
579
- * Badges are small, square-shouldered labels — closer to a stamp than a pill.
864
+ * Badges are small, square-shouldered labels | closer to a stamp than a pill.
580
865
  * No borders: a quiet tint and the text colour carry the meaning.
581
866
  */
582
867
  .j-badge {
@@ -623,7 +908,7 @@
623
908
  --j-badge-marker: var(--juxt-danger);
624
909
  }
625
910
 
626
- /* Accent is the only solid badge — reserve it for the thing that matters. */
911
+ /* Accent is the only solid badge | reserve it for the thing that matters. */
627
912
  .j-badge--accent {
628
913
  --j-badge-fg: var(--juxt-accent-fg);
629
914
  --j-badge-bg: var(--juxt-accent-strong);
@@ -657,69 +942,225 @@
657
942
  }
658
943
  }
659
944
 
660
- @layer juxt {
661
- .j-button {
662
- --j-button-height: var(--juxt-control-md);
663
- --j-button-px: var(--juxt-space-3);
664
- --j-button-gap: var(--juxt-space-1-5);
665
- --j-button-font: var(--juxt-text-md);
666
- --j-button-radius: var(--juxt-radius-sm);
945
+ @layer theme, base, juxt, components, utilities;
946
+ @layer juxt {
947
+ /*
948
+ * Banners run edge-to-edge across a page or section, unlike JAlert which sits
949
+ * inline in a card or form. A flat tinted surface and a left accent bar
950
+ * distinguish them from the bordered, neutral surface of an alert.
951
+ */
952
+ .j-banner {
953
+ --j-banner-accent: var(--juxt-fg-muted);
954
+ --j-banner-bg: var(--juxt-surface-sunken);
667
955
 
668
956
  position: relative;
669
- display: inline-flex;
957
+ display: flex;
670
958
  align-items: center;
671
- justify-content: center;
672
- height: var(--j-button-height);
673
- padding: 0 var(--j-button-px);
674
- border: 1px solid transparent;
675
- border-radius: var(--j-button-radius);
676
- font-family: var(--juxt-font-sans);
677
- font-size: var(--j-button-font);
678
- font-weight: var(--juxt-weight-medium);
679
- line-height: 1;
680
- letter-spacing: var(--juxt-tracking-tight);
681
- white-space: nowrap;
682
- text-decoration: none;
683
- cursor: pointer;
684
- user-select: none;
685
- -webkit-tap-highlight-color: transparent;
686
- touch-action: manipulation;
687
- transition-property: background-color, border-color, color, box-shadow, transform, outline-color, outline-offset;
688
- transition-duration: var(--juxt-duration-fast);
689
- transition-timing-function: var(--juxt-ease-standard);
690
- }
691
-
692
- /* Pressed: a short, physical dip. Released slower than pressed. */
693
- .j-button:active:not([aria-disabled='true'], :disabled) {
694
- transform: scale(0.97);
695
- transition-duration: var(--juxt-duration-instant);
959
+ gap: var(--juxt-space-3);
960
+ padding: var(--juxt-space-3) var(--juxt-space-5);
961
+ border-left: 3px solid var(--j-banner-accent);
962
+ background: var(--j-banner-bg);
963
+ color: var(--juxt-fg);
964
+ font-family: var(--juxt-font-sans);
696
965
  }
697
- @media (prefers-reduced-motion: reduce) {
698
- .j-button:active:not([aria-disabled='true'], :disabled) {
699
- transform: none;
966
+ .j-banner--info {
967
+ --j-banner-accent: var(--juxt-info);
968
+ --j-banner-bg: var(--juxt-info-soft);
700
969
  }
970
+ .j-banner--success {
971
+ --j-banner-accent: var(--juxt-success);
972
+ --j-banner-bg: var(--juxt-success-soft);
701
973
  }
702
- .j-button__content {
703
- display: inline-flex;
704
- align-items: center;
705
- gap: var(--j-button-gap);
706
- transition:
707
- opacity var(--juxt-duration-fast) var(--juxt-ease-standard),
708
- transform var(--juxt-duration-normal) var(--juxt-ease-out);
974
+ .j-banner--warning {
975
+ --j-banner-accent: var(--juxt-warning);
976
+ --j-banner-bg: var(--juxt-warning-soft);
709
977
  }
710
- .j-button__icon {
711
- display: inline-flex;
712
- margin-inline: -0.125rem;
713
- opacity: 0.85;
978
+ .j-banner--destructive {
979
+ --j-banner-accent: var(--juxt-danger);
980
+ --j-banner-bg: var(--juxt-danger-soft);
714
981
  }
715
- .j-button__icon > svg {
716
- width: 1em;
717
- height: 1em;
982
+ .j-banner__icon {
983
+ display: grid;
984
+ flex: none;
985
+ place-items: center;
986
+ height: 1.25rem;
987
+ color: var(--j-banner-accent);
718
988
  }
719
- .j-button.is-loading {
720
- cursor: progress;
989
+ .j-banner__icon > svg {
990
+ width: 1rem;
991
+ height: 1rem;
721
992
  }
722
- .j-button.is-loading .j-button__content {
993
+ .j-banner__body {
994
+ display: flex;
995
+ flex: 1;
996
+ flex-wrap: wrap;
997
+ align-items: baseline;
998
+ gap: var(--juxt-space-1) var(--juxt-space-2);
999
+ min-width: 0;
1000
+ }
1001
+ .j-banner__title {
1002
+ margin: 0;
1003
+ color: var(--juxt-fg);
1004
+ font-size: var(--juxt-text-md);
1005
+ font-weight: var(--juxt-weight-medium);
1006
+ letter-spacing: var(--juxt-tracking-tight);
1007
+ }
1008
+ .j-banner__description {
1009
+ color: var(--juxt-fg-secondary);
1010
+ font-size: var(--juxt-text-sm);
1011
+ line-height: var(--juxt-leading-normal);
1012
+ }
1013
+ .j-banner__description > p {
1014
+ margin: 0;
1015
+ }
1016
+ .j-banner__actions {
1017
+ display: flex;
1018
+ flex: none;
1019
+ flex-wrap: wrap;
1020
+ gap: var(--juxt-space-2);
1021
+ }
1022
+ .j-banner__close {
1023
+ display: grid;
1024
+ flex: none;
1025
+ place-items: center;
1026
+ width: 1.5rem;
1027
+ height: 1.5rem;
1028
+ padding: 0;
1029
+ border: 0;
1030
+ border-radius: var(--juxt-radius-xs);
1031
+ background: transparent;
1032
+ color: var(--juxt-fg-muted);
1033
+ cursor: pointer;
1034
+ transition-property: background-color, color, outline-color, outline-offset;
1035
+ }
1036
+ .j-banner__close:hover {
1037
+ background: var(--juxt-surface-hover);
1038
+ color: var(--juxt-fg);
1039
+ }
1040
+ .j-banner__close > svg {
1041
+ width: 0.875rem;
1042
+ height: 0.875rem;
1043
+ }
1044
+ }
1045
+
1046
+ @layer theme, base, juxt, components, utilities;
1047
+ @layer juxt {
1048
+ .j-breadcrumb {
1049
+ font-family: var(--juxt-font-sans);
1050
+ }
1051
+ .j-breadcrumb__list {
1052
+ display: flex;
1053
+ flex-wrap: wrap;
1054
+ align-items: center;
1055
+ gap: var(--juxt-space-1-5);
1056
+ margin: 0;
1057
+ padding: 0;
1058
+ list-style: none;
1059
+ }
1060
+ .j-breadcrumb__item {
1061
+ display: flex;
1062
+ align-items: center;
1063
+ gap: var(--juxt-space-1-5);
1064
+ color: var(--juxt-fg-muted);
1065
+ font-size: var(--juxt-text-sm);
1066
+ line-height: var(--juxt-leading-snug);
1067
+ }
1068
+ .j-breadcrumb__item:not(:first-child)::before {
1069
+ content: '';
1070
+ display: inline-block;
1071
+ width: 0.3125rem;
1072
+ height: 0.3125rem;
1073
+ margin-right: var(--juxt-space-1-5);
1074
+ border-top: 1.5px solid var(--juxt-fg-disabled);
1075
+ border-right: 1.5px solid var(--juxt-fg-disabled);
1076
+ transform: rotate(45deg);
1077
+ }
1078
+ .j-breadcrumb__link {
1079
+ border-radius: var(--juxt-radius-xs);
1080
+ color: var(--juxt-fg-muted);
1081
+ text-decoration: none;
1082
+ transition: color var(--juxt-duration-fast) var(--juxt-ease-standard);
1083
+ }
1084
+ .j-breadcrumb__link:hover {
1085
+ color: var(--juxt-fg);
1086
+ text-decoration: underline;
1087
+ text-underline-offset: 2px;
1088
+ }
1089
+ .j-breadcrumb__current {
1090
+ color: var(--juxt-fg);
1091
+ font-weight: var(--juxt-weight-medium);
1092
+ letter-spacing: var(--juxt-tracking-tight);
1093
+ }
1094
+ .j-breadcrumb__ellipsis {
1095
+ color: var(--juxt-fg-disabled);
1096
+ user-select: none;
1097
+ }
1098
+ }
1099
+
1100
+ @layer theme, base, juxt, components, utilities;
1101
+ @layer juxt {
1102
+ .j-button {
1103
+ --j-button-height: var(--juxt-control-md);
1104
+ --j-button-px: var(--juxt-space-3);
1105
+ --j-button-gap: var(--juxt-space-1-5);
1106
+ --j-button-font: var(--juxt-text-md);
1107
+ --j-button-radius: var(--juxt-radius-sm);
1108
+
1109
+ position: relative;
1110
+ display: inline-flex;
1111
+ align-items: center;
1112
+ justify-content: center;
1113
+ height: var(--j-button-height);
1114
+ padding: 0 var(--j-button-px);
1115
+ border: 1px solid transparent;
1116
+ border-radius: var(--j-button-radius);
1117
+ font-family: var(--juxt-font-sans);
1118
+ font-size: var(--j-button-font);
1119
+ font-weight: var(--juxt-weight-medium);
1120
+ line-height: 1;
1121
+ letter-spacing: var(--juxt-tracking-tight);
1122
+ white-space: nowrap;
1123
+ text-decoration: none;
1124
+ cursor: pointer;
1125
+ user-select: none;
1126
+ -webkit-tap-highlight-color: transparent;
1127
+ touch-action: manipulation;
1128
+ transition-property: background-color, border-color, color, box-shadow, transform, outline-color, outline-offset;
1129
+ transition-duration: var(--juxt-duration-fast);
1130
+ transition-timing-function: var(--juxt-ease-standard);
1131
+ }
1132
+
1133
+ /* Pressed: a short, physical dip. Released slower than pressed. */
1134
+ .j-button:active:not([aria-disabled='true'], :disabled) {
1135
+ transform: scale(0.97);
1136
+ transition-duration: var(--juxt-duration-instant);
1137
+ }
1138
+ @media (prefers-reduced-motion: reduce) {
1139
+ .j-button:active:not([aria-disabled='true'], :disabled) {
1140
+ transform: none;
1141
+ }
1142
+ }
1143
+ .j-button__content {
1144
+ display: inline-flex;
1145
+ align-items: center;
1146
+ gap: var(--j-button-gap);
1147
+ transition:
1148
+ opacity var(--juxt-duration-fast) var(--juxt-ease-standard),
1149
+ transform var(--juxt-duration-normal) var(--juxt-ease-out);
1150
+ }
1151
+ .j-button__icon {
1152
+ display: inline-flex;
1153
+ margin-inline: -0.125rem;
1154
+ opacity: 0.85;
1155
+ }
1156
+ .j-button__icon > svg {
1157
+ width: 1em;
1158
+ height: 1em;
1159
+ }
1160
+ .j-button.is-loading {
1161
+ cursor: progress;
1162
+ }
1163
+ .j-button.is-loading .j-button__content {
723
1164
  opacity: 0;
724
1165
  transform: scale(0.96);
725
1166
  }
@@ -844,6 +1285,7 @@
844
1285
  }
845
1286
  }
846
1287
 
1288
+ @layer theme, base, juxt, components, utilities;
847
1289
  @layer juxt {
848
1290
  .j-card {
849
1291
  --j-card-p: var(--juxt-space-5);
@@ -936,6 +1378,7 @@
936
1378
  }
937
1379
  }
938
1380
 
1381
+ @layer theme, base, juxt, components, utilities;
939
1382
  @layer juxt {
940
1383
  .j-checkbox {
941
1384
  --j-checkbox-size: 1rem;
@@ -1076,6 +1519,79 @@
1076
1519
  }
1077
1520
  }
1078
1521
 
1522
+ @layer theme, base, juxt, components, utilities;
1523
+ @layer juxt {
1524
+ .j-collapsible {
1525
+ font-family: var(--juxt-font-sans);
1526
+ }
1527
+ .j-collapsible__trigger {
1528
+ display: inline-flex;
1529
+ align-items: center;
1530
+ gap: var(--juxt-space-1-5);
1531
+ padding: var(--juxt-space-1) 0;
1532
+ border: 0;
1533
+ border-radius: var(--juxt-radius-xs);
1534
+ background: transparent;
1535
+ color: var(--juxt-fg);
1536
+ font: inherit;
1537
+ font-size: var(--juxt-text-md);
1538
+ font-weight: var(--juxt-weight-medium);
1539
+ letter-spacing: var(--juxt-tracking-tight);
1540
+ cursor: pointer;
1541
+ outline: 2px solid transparent;
1542
+ outline-offset: 2px;
1543
+ -webkit-tap-highlight-color: transparent;
1544
+ transition:
1545
+ color var(--juxt-duration-fast) var(--juxt-ease-standard),
1546
+ outline-color var(--juxt-duration-fast) var(--juxt-ease-out);
1547
+ }
1548
+ .j-collapsible__trigger:disabled {
1549
+ color: var(--juxt-fg-disabled);
1550
+ cursor: not-allowed;
1551
+ }
1552
+ .j-collapsible__chevron {
1553
+ flex: none;
1554
+ width: 1rem;
1555
+ height: 1rem;
1556
+ color: var(--juxt-fg-muted);
1557
+ transition: transform var(--juxt-duration-normal) var(--juxt-ease-out);
1558
+ }
1559
+ .j-collapsible[data-state='open'] .j-collapsible__chevron {
1560
+ transform: rotate(180deg);
1561
+ }
1562
+ .j-collapsible__panel {
1563
+ display: grid;
1564
+ grid-template-rows: 0fr;
1565
+ transition: grid-template-rows var(--juxt-duration-slow) var(--juxt-ease-out);
1566
+ }
1567
+ .j-collapsible[data-state='open'] .j-collapsible__panel {
1568
+ grid-template-rows: 1fr;
1569
+ }
1570
+ .j-collapsible__panel-inner {
1571
+ min-height: 0;
1572
+ overflow: hidden;
1573
+ }
1574
+ .j-collapsible__content {
1575
+ padding-top: var(--juxt-space-2);
1576
+ color: var(--juxt-fg-secondary);
1577
+ font-size: var(--juxt-text-md);
1578
+ line-height: var(--juxt-leading-normal);
1579
+ opacity: 0;
1580
+ transition: opacity var(--juxt-duration-fast) var(--juxt-ease-standard);
1581
+ }
1582
+ .j-collapsible[data-state='open'] .j-collapsible__content {
1583
+ opacity: 1;
1584
+ transition-delay: 60ms;
1585
+ }
1586
+ @media (prefers-reduced-motion: reduce) {
1587
+ .j-collapsible__panel,
1588
+ .j-collapsible__chevron {
1589
+ transition: none;
1590
+ }
1591
+ }
1592
+ }
1593
+
1594
+ @layer theme, base, juxt, components, utilities;
1079
1595
  @layer juxt {
1080
1596
  .j-command__overlay {
1081
1597
  position: fixed;
@@ -1392,6 +1908,7 @@ to {
1392
1908
  }
1393
1909
  }
1394
1910
 
1911
+ @layer theme, base, juxt, components, utilities;
1395
1912
  @layer juxt {
1396
1913
  .j-dialog__overlay {
1397
1914
  position: fixed;
@@ -1561,6 +2078,7 @@ to {
1561
2078
  }
1562
2079
  }
1563
2080
 
2081
+ @layer theme, base, juxt, components, utilities;
1564
2082
  @layer juxt {
1565
2083
  .j-menu {
1566
2084
  z-index: var(--juxt-z-popover);
@@ -1666,6 +2184,74 @@ to {
1666
2184
  }
1667
2185
  }
1668
2186
 
2187
+ @layer theme, base, juxt, components, utilities;
2188
+ @layer juxt {
2189
+ .j-empty-state {
2190
+ display: flex;
2191
+ flex-direction: column;
2192
+ align-items: center;
2193
+ max-width: 24rem;
2194
+ margin: 0 auto;
2195
+ padding: var(--juxt-space-8) var(--juxt-space-4);
2196
+ text-align: center;
2197
+ font-family: var(--juxt-font-sans);
2198
+ }
2199
+ .j-empty-state--sm {
2200
+ max-width: 18rem;
2201
+ padding: var(--juxt-space-6) var(--juxt-space-3);
2202
+ }
2203
+ .j-empty-state--lg {
2204
+ max-width: 28rem;
2205
+ padding: var(--juxt-space-12) var(--juxt-space-4);
2206
+ }
2207
+ .j-empty-state__icon {
2208
+ display: grid;
2209
+ place-items: center;
2210
+ width: 2.75rem;
2211
+ height: 2.75rem;
2212
+ margin-bottom: var(--juxt-space-4);
2213
+ border-radius: var(--juxt-radius-full);
2214
+ background: var(--juxt-surface-sunken);
2215
+ color: var(--juxt-fg-muted);
2216
+ }
2217
+ .j-empty-state--lg .j-empty-state__icon {
2218
+ width: 3.5rem;
2219
+ height: 3.5rem;
2220
+ }
2221
+ .j-empty-state__icon > svg {
2222
+ width: 1.25rem;
2223
+ height: 1.25rem;
2224
+ }
2225
+ .j-empty-state--lg .j-empty-state__icon > svg {
2226
+ width: 1.5rem;
2227
+ height: 1.5rem;
2228
+ }
2229
+ .j-empty-state__title {
2230
+ margin: 0;
2231
+ color: var(--juxt-fg);
2232
+ font-size: var(--juxt-text-lg);
2233
+ font-weight: var(--juxt-weight-semibold);
2234
+ letter-spacing: var(--juxt-tracking-tight);
2235
+ }
2236
+ .j-empty-state__description {
2237
+ margin-top: var(--juxt-space-1-5);
2238
+ color: var(--juxt-fg-muted);
2239
+ font-size: var(--juxt-text-sm);
2240
+ line-height: var(--juxt-leading-normal);
2241
+ }
2242
+ .j-empty-state__description > p {
2243
+ margin: 0;
2244
+ }
2245
+ .j-empty-state__actions {
2246
+ display: flex;
2247
+ flex-wrap: wrap;
2248
+ justify-content: center;
2249
+ gap: var(--juxt-space-2);
2250
+ margin-top: var(--juxt-space-5);
2251
+ }
2252
+ }
2253
+
2254
+ @layer theme, base, juxt, components, utilities;
1669
2255
  @layer juxt {
1670
2256
  .j-field {
1671
2257
  display: flex;
@@ -1724,6 +2310,7 @@ to {
1724
2310
  }
1725
2311
  }
1726
2312
 
2313
+ @layer theme, base, juxt, components, utilities;
1727
2314
  @layer juxt {
1728
2315
  .j-input__native {
1729
2316
  flex: 1;
@@ -1750,117 +2337,980 @@ to {
1750
2337
  }
1751
2338
  }
1752
2339
 
2340
+ @layer theme, base, juxt, components, utilities;
1753
2341
  @layer juxt {
1754
- .j-select__trigger {
1755
- width: 100%;
1756
- justify-content: space-between;
1757
- text-align: left;
1758
- cursor: pointer;
1759
- -webkit-tap-highlight-color: transparent;
1760
- }
1761
- .j-select__trigger:focus-visible {
1762
- outline: none;
1763
- }
1764
- .j-select__trigger:focus-visible:not(.is-invalid) {
1765
- border-color: var(--juxt-accent);
1766
- box-shadow: 0 0 0 3px var(--juxt-ring-soft);
2342
+ .j-kbd-group {
2343
+ display: inline-flex;
2344
+ gap: 3px;
2345
+ vertical-align: middle;
1767
2346
  }
1768
- .j-select__trigger:disabled {
1769
- cursor: not-allowed;
2347
+ .j-kbd-group--sm .j-kbd,
2348
+ .j-kbd--sm {
2349
+ min-width: 1.0625rem;
2350
+ height: 1.0625rem;
2351
+ font-size: 0.625rem;
1770
2352
  }
1771
- .j-select__value {
1772
- overflow: hidden;
1773
- min-width: 0;
1774
- text-overflow: ellipsis;
1775
- white-space: nowrap;
1776
- letter-spacing: var(--juxt-tracking-tight);
2353
+ }
2354
+
2355
+ @layer theme, base, juxt, components, utilities;
2356
+ @layer juxt {
2357
+ .j-pagination {
2358
+ --j-pagination-size: var(--juxt-control-md);
2359
+
2360
+ display: flex;
2361
+ align-items: center;
2362
+ gap: var(--juxt-space-1);
2363
+ font-family: var(--juxt-font-sans);
1777
2364
  }
1778
- .j-select__value.is-placeholder {
1779
- color: var(--juxt-fg-muted);
2365
+ .j-pagination--sm {
2366
+ --j-pagination-size: var(--juxt-control-sm);
2367
+ }
2368
+ .j-pagination__list {
2369
+ display: flex;
2370
+ align-items: center;
2371
+ gap: var(--juxt-space-1);
2372
+ margin: 0;
2373
+ padding: 0;
2374
+ list-style: none;
2375
+ }
2376
+ .j-pagination__nav,
2377
+ .j-pagination__page {
2378
+ display: grid;
2379
+ flex: none;
2380
+ place-items: center;
2381
+ width: var(--j-pagination-size);
2382
+ height: var(--j-pagination-size);
2383
+ border: 1px solid transparent;
2384
+ border-radius: var(--juxt-radius-sm);
2385
+ background: transparent;
2386
+ color: var(--juxt-fg-secondary);
2387
+ font-family: inherit;
2388
+ font-size: var(--juxt-text-sm);
2389
+ font-weight: var(--juxt-weight-medium);
2390
+ font-variant-numeric: tabular-nums;
2391
+ cursor: pointer;
2392
+ transition:
2393
+ background-color var(--juxt-duration-fast) var(--juxt-ease-standard),
2394
+ border-color var(--juxt-duration-fast) var(--juxt-ease-standard),
2395
+ color var(--juxt-duration-fast) var(--juxt-ease-standard);
2396
+ }
2397
+ .j-pagination__nav > svg {
2398
+ width: 1rem;
2399
+ height: 1rem;
2400
+ }
2401
+ .j-pagination__nav:hover:not(:disabled),
2402
+ .j-pagination__page:hover:not(:disabled) {
2403
+ background: var(--juxt-surface-hover);
2404
+ color: var(--juxt-fg);
2405
+ }
2406
+ .j-pagination__nav:disabled {
2407
+ color: var(--juxt-fg-disabled);
2408
+ cursor: not-allowed;
2409
+ }
2410
+ .j-pagination__page.is-current {
2411
+ border-color: var(--juxt-border);
2412
+ background: var(--juxt-surface-active);
2413
+ color: var(--juxt-fg);
2414
+ }
2415
+ .j-pagination__page:disabled {
2416
+ color: var(--juxt-fg-disabled);
2417
+ cursor: not-allowed;
2418
+ }
2419
+ .j-pagination__ellipsis {
2420
+ display: grid;
2421
+ place-items: center;
2422
+ width: var(--j-pagination-size);
2423
+ height: var(--j-pagination-size);
2424
+ color: var(--juxt-fg-disabled);
2425
+ }
2426
+ .j-pagination__ellipsis > svg {
2427
+ width: 1rem;
2428
+ height: 1rem;
2429
+ }
2430
+ }
2431
+
2432
+ @layer theme, base, juxt, components, utilities;
2433
+ @layer juxt {
2434
+ .j-popover {
2435
+ z-index: var(--juxt-z-popover);
2436
+ box-sizing: border-box;
2437
+ max-width: calc(100vw - 16px);
2438
+ max-height: var(--j-available-height, 32rem);
2439
+ padding: var(--juxt-space-4);
2440
+ overflow: auto;
2441
+ outline: none;
2442
+ font-size: var(--juxt-text-md);
2443
+ line-height: var(--juxt-leading-normal);
2444
+ }
2445
+ }
2446
+
2447
+ @layer theme, base, juxt, components, utilities;
2448
+ @layer juxt {
2449
+ .j-progress {
2450
+ --j-progress-height: 0.375rem;
2451
+ --j-progress-fill: var(--juxt-accent);
2452
+
2453
+ display: flex;
2454
+ flex-direction: column;
2455
+ gap: var(--juxt-space-2);
2456
+ width: 100%;
2457
+ font-family: var(--juxt-font-sans);
2458
+ }
2459
+ .j-progress--sm {
2460
+ --j-progress-height: 0.25rem;
2461
+ }
2462
+ .j-progress--neutral {
2463
+ --j-progress-fill: var(--juxt-fg);
2464
+ }
2465
+ .j-progress__header {
2466
+ display: flex;
2467
+ align-items: baseline;
2468
+ justify-content: space-between;
2469
+ gap: var(--juxt-space-3);
2470
+ font-size: var(--juxt-text-sm);
2471
+ }
2472
+ .j-progress__label {
2473
+ color: var(--juxt-fg);
2474
+ font-weight: var(--juxt-weight-medium);
2475
+ letter-spacing: var(--juxt-tracking-tight);
2476
+ }
2477
+ .j-progress__value {
2478
+ color: var(--juxt-fg-muted);
2479
+ font-variant-numeric: tabular-nums;
2480
+ }
2481
+ .j-progress__track {
2482
+ position: relative;
2483
+ height: var(--j-progress-height);
2484
+ overflow: hidden;
2485
+ border-radius: var(--juxt-radius-full);
2486
+ background: var(--juxt-surface-active);
2487
+ }
2488
+
2489
+ /* Width changes are transforms, so updates glide without reflow. */
2490
+ .j-progress__fill {
2491
+ position: absolute;
2492
+ inset: 0;
2493
+ border-radius: inherit;
2494
+ background: var(--j-progress-fill);
2495
+ transform: scaleX(0);
2496
+ transform-origin: left;
2497
+ transition: transform var(--juxt-duration-slow) var(--juxt-ease-out);
2498
+ }
2499
+ .j-progress.is-indeterminate .j-progress__fill {
2500
+ width: 40%;
2501
+ transform: none;
2502
+ animation: j-progress-indeterminate 1.4s var(--juxt-ease-standard) infinite;
2503
+ }
2504
+ @keyframes j-progress-indeterminate {
2505
+ from {
2506
+ transform: translateX(-100%);
2507
+ }
2508
+ to {
2509
+ transform: translateX(250%);
2510
+ }
2511
+ }
2512
+ @media (prefers-reduced-motion: reduce) {
2513
+ .j-progress.is-indeterminate .j-progress__fill {
2514
+ width: 100%;
2515
+ animation: j-progress-pulse 1.6s ease-in-out infinite;
2516
+ }
2517
+ @keyframes j-progress-pulse {
2518
+ 50% {
2519
+ opacity: 0.35;
2520
+ }
2521
+ }
2522
+ }
2523
+ }
2524
+
2525
+ @layer theme, base, juxt, components, utilities;
2526
+ @layer juxt {
2527
+ .j-radio {
2528
+ --j-radio-size: 1rem;
2529
+
2530
+ display: inline-flex;
2531
+ align-items: flex-start;
2532
+ gap: var(--juxt-space-2-5);
2533
+ font-family: var(--juxt-font-sans);
2534
+ }
2535
+ .j-radio__control {
2536
+ position: relative;
2537
+ display: inline-flex;
2538
+ flex: none;
2539
+ margin-top: calc((var(--juxt-text-md) * var(--juxt-leading-snug) - var(--j-radio-size)) / 2);
2540
+ }
2541
+ .j-radio__input {
2542
+ position: absolute;
2543
+ inset: -4px;
2544
+ z-index: 1;
2545
+ width: calc(100% + 8px);
2546
+ height: calc(100% + 8px);
2547
+ margin: 0;
2548
+ opacity: 0;
2549
+ cursor: pointer;
2550
+ }
2551
+ .j-radio__input:disabled {
2552
+ cursor: not-allowed;
2553
+ }
2554
+ .j-radio__circle {
2555
+ position: relative;
2556
+ display: block;
2557
+ width: var(--j-radio-size);
2558
+ height: var(--j-radio-size);
2559
+ border: 1px solid var(--juxt-border-strong);
2560
+ border-radius: var(--juxt-radius-full);
2561
+ background: var(--juxt-surface);
2562
+ box-shadow: var(--juxt-shadow-xs);
2563
+ outline: 2px solid transparent;
2564
+ outline-offset: 0;
2565
+ transition:
2566
+ background-color var(--juxt-duration-fast) var(--juxt-ease-standard),
2567
+ border-color var(--juxt-duration-fast) var(--juxt-ease-standard),
2568
+ transform var(--juxt-duration-fast) var(--juxt-ease-out),
2569
+ outline-color var(--juxt-duration-fast) var(--juxt-ease-out),
2570
+ outline-offset var(--juxt-duration-fast) var(--juxt-ease-out);
2571
+ }
2572
+
2573
+ /* The inner dot grows out of the centre once the fill lands. */
2574
+ .j-radio__circle::after {
2575
+ content: '';
2576
+ position: absolute;
2577
+ inset: 0;
2578
+ margin: auto;
2579
+ width: 0.375rem;
2580
+ height: 0.375rem;
2581
+ border-radius: var(--juxt-radius-full);
2582
+ background: var(--juxt-accent-fg);
2583
+ opacity: 0;
2584
+ transform: scale(0.3);
2585
+ transition:
2586
+ opacity var(--juxt-duration-instant) var(--juxt-ease-standard),
2587
+ transform var(--juxt-duration-normal) var(--juxt-ease-out);
2588
+ }
2589
+ .j-radio__input:hover:not(:disabled) + .j-radio__circle {
2590
+ border-color: var(--juxt-fg-muted);
2591
+ }
2592
+ .j-radio__input:active:not(:disabled) + .j-radio__circle {
2593
+ transform: scale(0.9);
2594
+ }
2595
+ .j-radio__input:focus-visible + .j-radio__circle {
2596
+ outline-color: var(--juxt-ring);
2597
+ outline-offset: 2px;
2598
+ }
2599
+ .j-radio[data-state='checked'] .j-radio__circle {
2600
+ border-color: var(--juxt-accent);
2601
+ background: var(--juxt-accent);
2602
+ }
2603
+ .j-radio[data-state='checked'] .j-radio__input:hover:not(:disabled) + .j-radio__circle {
2604
+ border-color: var(--juxt-accent-hover);
2605
+ background: var(--juxt-accent-hover);
2606
+ }
2607
+ .j-radio[data-state='checked'] .j-radio__circle::after {
2608
+ opacity: 1;
2609
+ transform: none;
2610
+ transition-delay: 30ms;
2611
+ }
2612
+ .j-radio-group.is-invalid .j-radio:not([data-state='checked']) .j-radio__circle {
2613
+ border-color: var(--juxt-danger-border);
2614
+ }
2615
+ @media (prefers-reduced-motion: reduce) {
2616
+ .j-radio__input:active:not(:disabled) + .j-radio__circle {
2617
+ transform: none;
2618
+ }
2619
+ }
2620
+ .j-radio__text {
2621
+ display: flex;
2622
+ flex-direction: column;
2623
+ gap: var(--juxt-space-0-5);
2624
+ min-width: 0;
2625
+ }
2626
+ .j-radio__label {
2627
+ color: var(--juxt-fg);
2628
+ font-size: var(--juxt-text-md);
2629
+ line-height: var(--juxt-leading-snug);
2630
+ letter-spacing: var(--juxt-tracking-tight);
2631
+ cursor: pointer;
2632
+ user-select: none;
2633
+ }
2634
+ .j-radio__description {
2635
+ color: var(--juxt-fg-muted);
2636
+ font-size: var(--juxt-text-sm);
2637
+ line-height: var(--juxt-leading-normal);
2638
+ }
2639
+ .j-radio.is-disabled .j-radio__circle {
2640
+ opacity: 0.5;
2641
+ box-shadow: none;
2642
+ }
2643
+ .j-radio.is-disabled .j-radio__label {
2644
+ color: var(--juxt-fg-muted);
2645
+ cursor: not-allowed;
2646
+ }
2647
+ }
2648
+
2649
+ @layer theme, base, juxt, components, utilities;
2650
+ @layer juxt {
2651
+ .j-radio-group {
2652
+ display: flex;
2653
+ flex-direction: column;
2654
+ gap: var(--juxt-space-1-5);
2655
+ min-width: 0;
2656
+ margin: 0;
2657
+ padding: 0;
2658
+ border: 0;
2659
+ font-family: var(--juxt-font-sans);
2660
+ }
2661
+ .j-radio-group__legend {
2662
+ display: inline-flex;
2663
+ gap: var(--juxt-space-0-5);
2664
+ margin-bottom: var(--juxt-space-1-5);
2665
+ padding: 0;
2666
+ color: var(--juxt-fg);
2667
+ font-size: var(--juxt-text-sm);
2668
+ font-weight: var(--juxt-weight-medium);
2669
+ line-height: var(--juxt-leading-snug);
2670
+ letter-spacing: var(--juxt-tracking-tight);
2671
+ }
2672
+ .j-radio-group__description,
2673
+ .j-radio-group__error {
2674
+ margin: calc(var(--juxt-space-1) * -1) 0 var(--juxt-space-1-5);
2675
+ color: var(--juxt-fg-muted);
2676
+ font-size: var(--juxt-text-xs);
2677
+ line-height: var(--juxt-leading-normal);
2678
+ }
2679
+ .j-radio-group__error {
2680
+ margin: var(--juxt-space-1) 0 0;
2681
+ color: var(--juxt-danger-text);
2682
+ }
2683
+ .j-radio-group__items {
2684
+ display: flex;
2685
+ }
2686
+ .j-radio-group__items--vertical {
2687
+ flex-direction: column;
2688
+ gap: var(--juxt-space-3);
2689
+ }
2690
+ .j-radio-group__items--horizontal {
2691
+ flex-wrap: wrap;
2692
+ gap: var(--juxt-space-3) var(--juxt-space-6);
2693
+ }
2694
+ }
2695
+
2696
+ @layer theme, base, juxt, components, utilities;
2697
+ @layer juxt {
2698
+ .j-rating {
2699
+ --j-rating-size: 1.25rem;
2700
+
2701
+ display: inline-flex;
2702
+ align-items: center;
2703
+ gap: var(--juxt-space-0-5);
2704
+ font-family: var(--juxt-font-sans);
2705
+ }
2706
+ .j-rating--sm {
2707
+ --j-rating-size: 1rem;
2708
+ }
2709
+ .j-rating--lg {
2710
+ --j-rating-size: 1.5rem;
2711
+ }
2712
+ .j-rating__star,
2713
+ .j-rating__button {
2714
+ position: relative;
2715
+ display: inline-flex;
2716
+ flex: none;
2717
+ width: var(--j-rating-size);
2718
+ height: var(--j-rating-size);
2719
+ padding: 0;
2720
+ border: 0;
2721
+ background: transparent;
2722
+ color: var(--juxt-fg-disabled);
2723
+ cursor: default;
2724
+ }
2725
+ .j-rating__button {
2726
+ border-radius: var(--juxt-radius-xs);
2727
+ cursor: pointer;
2728
+ transition: transform var(--juxt-duration-fast) var(--juxt-ease-out);
2729
+ }
2730
+ .j-rating__button:hover:not(:disabled) {
2731
+ transform: scale(1.1);
2732
+ }
2733
+ .j-rating__button:disabled {
2734
+ cursor: not-allowed;
2735
+ }
2736
+ .j-rating.is-disabled .j-rating__button {
2737
+ opacity: 0.5;
2738
+ }
2739
+ .j-rating__star-bg,
2740
+ .j-rating__star-fill > svg {
2741
+ position: absolute;
2742
+ inset: 0;
2743
+ width: 100%;
2744
+ height: 100%;
2745
+ fill: currentColor;
2746
+ stroke: none;
2747
+ }
2748
+ .j-rating__star-fill {
2749
+ position: absolute;
2750
+ inset: 0;
2751
+ overflow: hidden;
2752
+ color: var(--juxt-warning);
2753
+ transition: width var(--juxt-duration-fast) var(--juxt-ease-out);
2754
+ }
2755
+ @media (prefers-reduced-motion: reduce) {
2756
+ .j-rating__button:hover:not(:disabled) {
2757
+ transform: none;
2758
+ }
2759
+ .j-rating__star-fill {
2760
+ transition: none;
2761
+ }
2762
+ }
2763
+ }
2764
+
2765
+ @layer theme, base, juxt, components, utilities;
2766
+ @layer juxt {
2767
+ .j-select__trigger {
2768
+ width: 100%;
2769
+ justify-content: space-between;
2770
+ text-align: left;
2771
+ cursor: pointer;
2772
+ -webkit-tap-highlight-color: transparent;
2773
+ }
2774
+ .j-select__trigger:focus-visible {
2775
+ outline: none;
2776
+ }
2777
+ .j-select__trigger:focus-visible:not(.is-invalid) {
2778
+ border-color: var(--juxt-accent);
2779
+ box-shadow: 0 0 0 3px var(--juxt-ring-soft);
2780
+ }
2781
+ .j-select__trigger:disabled {
2782
+ cursor: not-allowed;
2783
+ }
2784
+ .j-select__value {
2785
+ overflow: hidden;
2786
+ min-width: 0;
2787
+ text-overflow: ellipsis;
2788
+ white-space: nowrap;
2789
+ letter-spacing: var(--juxt-tracking-tight);
2790
+ }
2791
+ .j-select__value.is-placeholder {
2792
+ color: var(--juxt-fg-muted);
1780
2793
  }
1781
2794
  .j-select__trigger.is-disabled .j-select__value {
1782
2795
  color: var(--juxt-fg-disabled);
1783
2796
  }
1784
- .j-select__chevron {
2797
+ .j-select__chevron {
2798
+ flex: none;
2799
+ width: 0.875rem;
2800
+ height: 0.875rem;
2801
+ margin-right: -0.125rem;
2802
+ color: var(--juxt-fg-muted);
2803
+ }
2804
+ .j-select__listbox {
2805
+ z-index: var(--juxt-z-popover);
2806
+ box-sizing: border-box;
2807
+ max-width: calc(100vw - 16px);
2808
+ max-height: min(18rem, var(--j-available-height, 18rem));
2809
+ margin: 0;
2810
+ padding: var(--juxt-space-1);
2811
+ overflow-y: auto;
2812
+ overscroll-behavior: contain;
2813
+ list-style: none;
2814
+ outline: none;
2815
+ scroll-padding-block: var(--juxt-space-1);
2816
+ }
2817
+ .j-select__option {
2818
+ position: relative;
2819
+ display: flex;
2820
+ align-items: center;
2821
+ gap: var(--juxt-space-2);
2822
+ min-height: var(--juxt-control-sm);
2823
+ padding: var(--juxt-space-1-5) var(--juxt-space-2);
2824
+ border-radius: var(--juxt-radius-xs);
2825
+ color: var(--juxt-fg);
2826
+ font-size: var(--juxt-text-md);
2827
+ letter-spacing: var(--juxt-tracking-tight);
2828
+ cursor: pointer;
2829
+ user-select: none;
2830
+ }
2831
+ .j-select__option.is-active {
2832
+ background: var(--juxt-surface-hover);
2833
+ }
2834
+ .j-select__option[aria-disabled='true'] {
2835
+ color: var(--juxt-fg-disabled);
2836
+ cursor: not-allowed;
2837
+ }
2838
+ .j-select__option-text {
2839
+ display: flex;
2840
+ flex: 1;
2841
+ flex-direction: column;
2842
+ gap: 1px;
2843
+ min-width: 0;
2844
+ }
2845
+ .j-select__option-label {
2846
+ overflow: hidden;
2847
+ text-overflow: ellipsis;
2848
+ white-space: nowrap;
2849
+ }
2850
+ .j-select__option-description {
2851
+ color: var(--juxt-fg-muted);
2852
+ font-size: var(--juxt-text-xs);
2853
+ }
2854
+ .j-select__check {
1785
2855
  flex: none;
1786
2856
  width: 0.875rem;
1787
2857
  height: 0.875rem;
1788
- margin-right: -0.125rem;
1789
- color: var(--juxt-fg-muted);
2858
+ color: var(--juxt-accent-text);
2859
+ opacity: 0;
2860
+ transform: scale(0.8);
2861
+ transition:
2862
+ opacity var(--juxt-duration-fast) var(--juxt-ease-out),
2863
+ transform var(--juxt-duration-fast) var(--juxt-ease-out);
1790
2864
  }
1791
- .j-select__listbox {
1792
- z-index: var(--juxt-z-popover);
1793
- box-sizing: border-box;
1794
- max-width: calc(100vw - 16px);
1795
- max-height: min(18rem, var(--j-available-height, 18rem));
2865
+ .j-select__option.is-selected .j-select__check {
2866
+ opacity: 1;
2867
+ transform: none;
2868
+ }
2869
+ .j-select__empty {
2870
+ padding: var(--juxt-space-3) var(--juxt-space-2);
2871
+ color: var(--juxt-fg-muted);
2872
+ font-size: var(--juxt-text-sm);
2873
+ text-align: center;
2874
+ }
2875
+ }
2876
+
2877
+ @layer theme, base, juxt, components, utilities;
2878
+ @layer juxt {
2879
+ .j-separator {
2880
+ flex: none;
2881
+ background: var(--juxt-border-subtle);
2882
+ }
2883
+ .dark .j-separator,
2884
+ [data-theme='dark'] .j-separator {
2885
+ background: var(--juxt-border);
2886
+ }
2887
+ .j-separator--horizontal {
2888
+ width: 100%;
2889
+ height: 1px;
2890
+ }
2891
+ .j-separator--vertical {
2892
+ align-self: stretch;
2893
+ width: 1px;
2894
+ min-height: 1rem;
2895
+ }
2896
+ .j-separator--labelled {
2897
+ display: flex;
2898
+ align-items: center;
2899
+ gap: var(--juxt-space-3);
2900
+ height: auto;
2901
+ background: none !important;
2902
+ color: var(--juxt-fg-muted);
2903
+ font-family: var(--juxt-font-sans);
2904
+ font-size: var(--juxt-text-xs);
2905
+ }
2906
+ .j-separator--labelled::before,
2907
+ .j-separator--labelled::after {
2908
+ content: '';
2909
+ flex: 1;
2910
+ height: 1px;
2911
+ background: var(--juxt-border-subtle);
2912
+ }
2913
+ .dark .j-separator--labelled::before,
2914
+ .dark .j-separator--labelled::after,
2915
+ [data-theme='dark'] .j-separator--labelled::before,
2916
+ [data-theme='dark'] .j-separator--labelled::after {
2917
+ background: var(--juxt-border);
2918
+ }
2919
+ .j-separator__label {
2920
+ flex: none;
2921
+ }
2922
+ }
2923
+
2924
+ @layer theme, base, juxt, components, utilities;
2925
+ @layer juxt {
2926
+ .j-sheet__overlay {
2927
+ position: fixed;
2928
+ inset: 0;
2929
+ z-index: var(--juxt-z-overlay);
2930
+ background: var(--juxt-overlay);
2931
+ }
2932
+ .j-sheet__positioner {
2933
+ position: fixed;
2934
+ inset: 0;
2935
+ z-index: var(--juxt-z-modal);
2936
+ display: flex;
2937
+ padding: var(--juxt-space-2);
2938
+ }
2939
+ .j-sheet__positioner--right {
2940
+ justify-content: flex-end;
2941
+ }
2942
+ .j-sheet__positioner--left {
2943
+ justify-content: flex-start;
2944
+ }
2945
+ .j-sheet__positioner--bottom {
2946
+ align-items: flex-end;
2947
+ padding-bottom: max(var(--juxt-space-2), env(safe-area-inset-bottom));
2948
+ }
2949
+
2950
+ /* A floating panel with a small inset from the edges | calmer than edge-to-edge. */
2951
+ .j-sheet {
2952
+ position: relative;
2953
+ display: flex;
2954
+ flex-direction: column;
2955
+ width: 100%;
2956
+ border: 1px solid var(--juxt-border);
2957
+ border-radius: var(--juxt-radius-lg);
2958
+ background: var(--juxt-surface-raised);
2959
+ box-shadow: var(--juxt-shadow-lg);
2960
+ color: var(--juxt-fg);
2961
+ font-family: var(--juxt-font-sans);
2962
+ outline: none;
2963
+ }
2964
+ .j-sheet--right,
2965
+ .j-sheet--left {
2966
+ height: 100%;
2967
+ }
2968
+ .j-sheet--right.j-sheet--sm,
2969
+ .j-sheet--left.j-sheet--sm {
2970
+ max-width: 20rem;
2971
+ }
2972
+ .j-sheet--right.j-sheet--md,
2973
+ .j-sheet--left.j-sheet--md {
2974
+ max-width: 25rem;
2975
+ }
2976
+ .j-sheet--right.j-sheet--lg,
2977
+ .j-sheet--left.j-sheet--lg {
2978
+ max-width: 35rem;
2979
+ }
2980
+ .j-sheet--bottom.j-sheet--sm {
2981
+ max-height: 20rem;
2982
+ }
2983
+ .j-sheet--bottom.j-sheet--md {
2984
+ max-height: 25rem;
2985
+ }
2986
+ .j-sheet--bottom.j-sheet--lg {
2987
+ max-height: min(35rem, calc(100dvh - var(--juxt-space-12)));
2988
+ }
2989
+ .j-sheet__header {
2990
+ display: flex;
2991
+ flex-direction: column;
2992
+ gap: var(--juxt-space-1-5);
2993
+ padding: var(--juxt-space-5) var(--juxt-space-12) var(--juxt-space-4) var(--juxt-space-5);
2994
+ border-bottom: 1px solid var(--juxt-border-subtle);
2995
+ }
2996
+ .dark .j-sheet__header,
2997
+ [data-theme='dark'] .j-sheet__header {
2998
+ border-bottom-color: var(--juxt-border);
2999
+ }
3000
+ .j-sheet__title {
1796
3001
  margin: 0;
1797
- padding: var(--juxt-space-1);
3002
+ font-size: var(--juxt-text-lg);
3003
+ font-weight: var(--juxt-weight-semibold);
3004
+ line-height: var(--juxt-leading-snug);
3005
+ letter-spacing: var(--juxt-tracking-tight);
3006
+ }
3007
+ .j-sheet__description {
3008
+ margin: 0;
3009
+ color: var(--juxt-fg-secondary);
3010
+ font-size: var(--juxt-text-md);
3011
+ line-height: var(--juxt-leading-normal);
3012
+ }
3013
+ .j-sheet__body {
3014
+ flex: 1;
3015
+ min-height: 0;
3016
+ padding: var(--juxt-space-5);
1798
3017
  overflow-y: auto;
1799
3018
  overscroll-behavior: contain;
1800
- list-style: none;
1801
- outline: none;
1802
- scroll-padding-block: var(--juxt-space-1);
3019
+ color: var(--juxt-fg-secondary);
3020
+ font-size: var(--juxt-text-md);
3021
+ line-height: var(--juxt-leading-normal);
3022
+ }
3023
+ .j-sheet__footer {
3024
+ display: flex;
3025
+ justify-content: flex-end;
3026
+ gap: var(--juxt-space-2);
3027
+ padding: var(--juxt-space-4) var(--juxt-space-5);
3028
+ border-top: 1px solid var(--juxt-border-subtle);
3029
+ }
3030
+ .dark .j-sheet__footer,
3031
+ [data-theme='dark'] .j-sheet__footer {
3032
+ border-top-color: var(--juxt-border);
3033
+ }
3034
+ .j-sheet__close {
3035
+ position: absolute;
3036
+ top: var(--juxt-space-3);
3037
+ right: var(--juxt-space-3);
3038
+ display: grid;
3039
+ place-items: center;
3040
+ width: var(--juxt-control-sm);
3041
+ height: var(--juxt-control-sm);
3042
+ padding: 0;
3043
+ border: 0;
3044
+ border-radius: var(--juxt-radius-sm);
3045
+ background: transparent;
3046
+ color: var(--juxt-fg-muted);
3047
+ cursor: pointer;
3048
+ transition-property: background-color, color, outline-color, outline-offset;
3049
+ }
3050
+ .j-sheet__close:hover {
3051
+ background: var(--juxt-surface-hover);
3052
+ color: var(--juxt-fg);
3053
+ }
3054
+ .j-sheet__close > svg {
3055
+ width: 1rem;
3056
+ height: 1rem;
3057
+ }
3058
+ .j-sheet.is-nudging {
3059
+ animation: j-sheet-nudge 220ms var(--juxt-ease-out);
3060
+ }
3061
+ @keyframes j-sheet-nudge {
3062
+ 40% {
3063
+ transform: scale(1.006);
3064
+ }
3065
+ }
3066
+
3067
+ /* Motion: the backdrop fades; the sheet slides in from its edge. */
3068
+ .j-sheet-overlay-enter-active {
3069
+ transition: opacity var(--juxt-duration-normal) var(--juxt-ease-out);
3070
+ }
3071
+ .j-sheet-overlay-leave-active {
3072
+ transition: opacity var(--juxt-duration-fast) var(--juxt-ease-in);
3073
+ }
3074
+ .j-sheet-overlay-enter-from,
3075
+ .j-sheet-overlay-leave-to {
3076
+ opacity: 0;
3077
+ }
3078
+ .j-sheet-enter-active .j-sheet {
3079
+ transition: transform 280ms var(--juxt-ease-out);
3080
+ }
3081
+ .j-sheet-leave-active .j-sheet {
3082
+ transition: transform var(--juxt-duration-normal) var(--juxt-ease-in);
3083
+ }
3084
+ .j-sheet-enter-from .j-sheet--right,
3085
+ .j-sheet-leave-to .j-sheet--right {
3086
+ transform: translateX(calc(100% + var(--juxt-space-4)));
3087
+ }
3088
+ .j-sheet-enter-from .j-sheet--left,
3089
+ .j-sheet-leave-to .j-sheet--left {
3090
+ transform: translateX(calc(-100% - var(--juxt-space-4)));
3091
+ }
3092
+ .j-sheet-enter-from .j-sheet--bottom,
3093
+ .j-sheet-leave-to .j-sheet--bottom {
3094
+ transform: translateY(calc(100% + var(--juxt-space-4)));
3095
+ }
3096
+
3097
+ /* Reduced motion: the sheet fades in place instead of travelling. */
3098
+ @media (prefers-reduced-motion: reduce) {
3099
+ .j-sheet-enter-active .j-sheet,
3100
+ .j-sheet-leave-active .j-sheet {
3101
+ transition: opacity var(--juxt-duration-normal) var(--juxt-ease-standard);
3102
+ }
3103
+ .j-sheet-enter-from .j-sheet,
3104
+ .j-sheet-leave-to .j-sheet {
3105
+ opacity: 0;
3106
+ transform: none !important;
3107
+ }
3108
+ }
3109
+ }
3110
+
3111
+ @layer theme, base, juxt, components, utilities;
3112
+ @layer juxt {
3113
+ .j-skeleton {
3114
+ display: block;
3115
+ width: 100%;
3116
+ height: 1rem;
3117
+ border-radius: var(--juxt-radius-sm);
3118
+ background: var(--juxt-surface-active);
3119
+ animation: j-skeleton-pulse 1.8s var(--juxt-ease-standard) infinite;
3120
+ }
3121
+ .j-skeleton--circle {
3122
+ width: 2rem;
3123
+ height: 2rem;
3124
+ border-radius: var(--juxt-radius-full);
3125
+ }
3126
+ .j-skeleton--text {
3127
+ height: 0.75rem;
3128
+ border-radius: var(--juxt-radius-xs);
3129
+ }
3130
+ .j-skeleton-lines {
3131
+ display: flex;
3132
+ flex-direction: column;
3133
+ gap: var(--juxt-space-2);
3134
+ width: 100%;
3135
+ }
3136
+
3137
+ /* A slow breath, not a shimmer | loading shouldn't compete for attention. */
3138
+ @keyframes j-skeleton-pulse {
3139
+ 50% {
3140
+ opacity: 0.5;
3141
+ }
3142
+ }
3143
+ @media (prefers-reduced-motion: reduce) {
3144
+ .j-skeleton {
3145
+ animation: none;
3146
+ }
3147
+ }
3148
+ }
3149
+
3150
+ @layer theme, base, juxt, components, utilities;
3151
+ @layer juxt {
3152
+ .j-slider {
3153
+ --j-slider-track: 0.25rem;
3154
+ --j-slider-thumb: 1rem;
3155
+
3156
+ display: flex;
3157
+ align-items: center;
3158
+ width: 100%;
3159
+ padding: calc(var(--j-slider-thumb) / 2) 0;
3160
+ font-family: var(--juxt-font-sans);
3161
+ touch-action: none;
3162
+ }
3163
+ .j-slider--sm {
3164
+ --j-slider-track: 0.1875rem;
3165
+ --j-slider-thumb: 0.875rem;
3166
+ }
3167
+ .j-slider__track {
3168
+ position: relative;
3169
+ width: 100%;
3170
+ height: var(--j-slider-track);
3171
+ border-radius: var(--juxt-radius-full);
3172
+ background: var(--juxt-surface-active);
3173
+ cursor: pointer;
3174
+ }
3175
+ .j-slider.is-disabled .j-slider__track {
3176
+ cursor: not-allowed;
3177
+ opacity: 0.5;
3178
+ }
3179
+ .j-slider__range {
3180
+ position: absolute;
3181
+ top: 0;
3182
+ bottom: 0;
3183
+ border-radius: var(--juxt-radius-full);
3184
+ background: var(--juxt-accent);
3185
+ }
3186
+ .j-slider__thumb {
3187
+ position: absolute;
3188
+ top: 50%;
3189
+ width: var(--j-slider-thumb);
3190
+ height: var(--j-slider-thumb);
3191
+ border-radius: var(--juxt-radius-full);
3192
+ background: var(--juxt-surface);
3193
+ box-shadow: 0 0 0 1px var(--juxt-border-strong), var(--juxt-shadow-sm);
3194
+ cursor: grab;
3195
+ transform: translate(-50%, -50%);
3196
+ transition:
3197
+ box-shadow var(--juxt-duration-fast) var(--juxt-ease-out),
3198
+ left var(--juxt-duration-fast) var(--juxt-ease-out);
3199
+ }
3200
+ .j-slider__thumb.is-dragging {
3201
+ cursor: grabbing;
3202
+ transition: none;
3203
+ }
3204
+ .j-slider__thumb:hover {
3205
+ box-shadow: 0 0 0 1px var(--juxt-accent), var(--juxt-shadow-sm);
3206
+ }
3207
+ .j-slider__thumb:focus-visible {
3208
+ outline-color: var(--juxt-ring);
3209
+ outline-offset: 3px;
3210
+ }
3211
+ .j-slider.is-disabled .j-slider__thumb {
3212
+ cursor: not-allowed;
3213
+ }
3214
+ .j-slider__bubble {
3215
+ position: absolute;
3216
+ bottom: calc(100% + var(--juxt-space-2));
3217
+ left: 50%;
3218
+ padding: var(--juxt-space-0-5) var(--juxt-space-1-5);
3219
+ border-radius: var(--juxt-radius-xs);
3220
+ background: var(--juxt-tooltip-bg);
3221
+ color: var(--juxt-tooltip-fg);
3222
+ font-size: var(--juxt-text-2xs);
3223
+ font-weight: var(--juxt-weight-medium);
3224
+ font-variant-numeric: tabular-nums;
3225
+ white-space: nowrap;
3226
+ pointer-events: none;
3227
+ transform: translateX(-50%);
3228
+ }
3229
+ @media (prefers-reduced-motion: reduce) {
3230
+ .j-slider__thumb {
3231
+ transition: none;
3232
+ }
3233
+ }
3234
+ }
3235
+
3236
+ @layer theme, base, juxt, components, utilities;
3237
+ @layer juxt {
3238
+ .j-spinner-wrap {
3239
+ display: inline-flex;
3240
+ color: var(--juxt-fg-muted);
3241
+ vertical-align: middle;
3242
+ }
3243
+ }
3244
+
3245
+ @layer theme, base, juxt, components, utilities;
3246
+ @layer juxt {
3247
+ .j-stat {
3248
+ display: flex;
3249
+ flex-direction: column;
3250
+ gap: var(--juxt-space-1-5);
3251
+ font-family: var(--juxt-font-sans);
1803
3252
  }
1804
- .j-select__option {
1805
- position: relative;
3253
+ .j-stat__header {
1806
3254
  display: flex;
1807
3255
  align-items: center;
1808
- gap: var(--juxt-space-2);
1809
- min-height: var(--juxt-control-sm);
1810
- padding: var(--juxt-space-1-5) var(--juxt-space-2);
1811
- border-radius: var(--juxt-radius-xs);
1812
- color: var(--juxt-fg);
1813
- font-size: var(--juxt-text-md);
1814
- letter-spacing: var(--juxt-tracking-tight);
1815
- cursor: pointer;
1816
- user-select: none;
3256
+ gap: var(--juxt-space-1-5);
1817
3257
  }
1818
- .j-select__option.is-active {
1819
- background: var(--juxt-surface-hover);
3258
+ .j-stat__icon {
3259
+ display: grid;
3260
+ place-items: center;
3261
+ color: var(--juxt-fg-muted);
1820
3262
  }
1821
- .j-select__option[aria-disabled='true'] {
1822
- color: var(--juxt-fg-disabled);
1823
- cursor: not-allowed;
3263
+ .j-stat__icon > svg {
3264
+ width: 0.875rem;
3265
+ height: 0.875rem;
1824
3266
  }
1825
- .j-select__option-text {
3267
+ .j-stat__label {
3268
+ color: var(--juxt-fg-muted);
3269
+ font-size: var(--juxt-text-sm);
3270
+ font-weight: var(--juxt-weight-medium);
3271
+ letter-spacing: var(--juxt-tracking-tight);
3272
+ }
3273
+ .j-stat__row {
1826
3274
  display: flex;
1827
- flex: 1;
1828
- flex-direction: column;
1829
- gap: 1px;
1830
- min-width: 0;
3275
+ align-items: baseline;
3276
+ gap: var(--juxt-space-2);
1831
3277
  }
1832
- .j-select__option-label {
1833
- overflow: hidden;
1834
- text-overflow: ellipsis;
1835
- white-space: nowrap;
3278
+ .j-stat__value {
3279
+ color: var(--juxt-fg);
3280
+ font-size: var(--juxt-text-3xl);
3281
+ font-weight: var(--juxt-weight-semibold);
3282
+ line-height: var(--juxt-leading-tight);
3283
+ letter-spacing: var(--juxt-tracking-tighter);
3284
+ font-variant-numeric: tabular-nums;
1836
3285
  }
1837
- .j-select__option-description {
3286
+ .j-stat__delta {
3287
+ display: inline-flex;
3288
+ align-items: center;
3289
+ gap: 0.125rem;
1838
3290
  color: var(--juxt-fg-muted);
1839
- font-size: var(--juxt-text-xs);
3291
+ font-size: var(--juxt-text-sm);
3292
+ font-weight: var(--juxt-weight-medium);
3293
+ font-variant-numeric: tabular-nums;
1840
3294
  }
1841
- .j-select__check {
1842
- flex: none;
3295
+ .j-stat__delta > svg {
1843
3296
  width: 0.875rem;
1844
- height: 0.875rem;
1845
- color: var(--juxt-accent-text);
1846
- opacity: 0;
1847
- transform: scale(0.8);
1848
- transition:
1849
- opacity var(--juxt-duration-fast) var(--juxt-ease-out),
1850
- transform var(--juxt-duration-fast) var(--juxt-ease-out);
3297
+ height: 0.875rem;
1851
3298
  }
1852
- .j-select__option.is-selected .j-select__check {
1853
- opacity: 1;
1854
- transform: none;
3299
+ .j-stat__delta--up {
3300
+ color: var(--juxt-success-text);
1855
3301
  }
1856
- .j-select__empty {
1857
- padding: var(--juxt-space-3) var(--juxt-space-2);
3302
+ .j-stat__delta--down {
3303
+ color: var(--juxt-danger-text);
3304
+ }
3305
+ .j-stat__description {
3306
+ margin: 0;
1858
3307
  color: var(--juxt-fg-muted);
1859
- font-size: var(--juxt-text-sm);
1860
- text-align: center;
3308
+ font-size: var(--juxt-text-xs);
3309
+ line-height: var(--juxt-leading-normal);
1861
3310
  }
1862
3311
  }
1863
3312
 
3313
+ @layer theme, base, juxt, components, utilities;
1864
3314
  @layer juxt {
1865
3315
  .j-switch {
1866
3316
  --j-switch-w: 2rem;
@@ -1971,6 +3421,7 @@ to {
1971
3421
  }
1972
3422
  }
1973
3423
 
3424
+ @layer theme, base, juxt, components, utilities;
1974
3425
  @layer juxt {
1975
3426
  .j-tabs {
1976
3427
  --j-tab-height: var(--juxt-control-md);
@@ -2125,6 +3576,110 @@ from {
2125
3576
  }
2126
3577
  }
2127
3578
 
3579
+ @layer theme, base, juxt, components, utilities;
3580
+ @layer juxt {
3581
+ /*
3582
+ * Tags are pills, not stamps | fully rounded and carrying their own remove
3583
+ * affordance, which is what sets them apart from the static JBadge.
3584
+ */
3585
+ .j-tag {
3586
+ --j-tag-fg: var(--juxt-fg-secondary);
3587
+ --j-tag-bg: var(--juxt-surface-active);
3588
+
3589
+ display: inline-flex;
3590
+ flex: none;
3591
+ align-items: center;
3592
+ gap: 0.3125rem;
3593
+ height: 1.375rem;
3594
+ padding: 0 var(--juxt-space-1) 0 var(--juxt-space-2-5);
3595
+ border-radius: var(--juxt-radius-full);
3596
+ background: var(--j-tag-bg);
3597
+ color: var(--j-tag-fg);
3598
+ font-family: var(--juxt-font-sans);
3599
+ font-size: var(--juxt-text-xs);
3600
+ font-weight: var(--juxt-weight-medium);
3601
+ line-height: 1;
3602
+ white-space: nowrap;
3603
+ }
3604
+ .j-tag--sm {
3605
+ height: 1.125rem;
3606
+ padding: 0 0.1875rem 0 var(--juxt-space-2);
3607
+ font-size: var(--juxt-text-2xs);
3608
+ }
3609
+ .j-tag--success {
3610
+ --j-tag-fg: var(--juxt-success-text);
3611
+ --j-tag-bg: var(--juxt-success-soft);
3612
+ }
3613
+ .j-tag--warning {
3614
+ --j-tag-fg: var(--juxt-warning-text);
3615
+ --j-tag-bg: var(--juxt-warning-soft);
3616
+ }
3617
+ .j-tag--destructive {
3618
+ --j-tag-fg: var(--juxt-danger-text);
3619
+ --j-tag-bg: var(--juxt-danger-soft);
3620
+ }
3621
+ .j-tag--accent {
3622
+ --j-tag-fg: var(--juxt-accent-fg);
3623
+ --j-tag-bg: var(--juxt-accent-strong);
3624
+ }
3625
+ .j-tag__icon {
3626
+ display: inline-flex;
3627
+ margin-left: -0.0625rem;
3628
+ }
3629
+ .j-tag__icon > svg {
3630
+ width: 0.75rem;
3631
+ height: 0.75rem;
3632
+ }
3633
+ .j-tag__label {
3634
+ overflow: hidden;
3635
+ text-overflow: ellipsis;
3636
+ }
3637
+ .j-tag__remove {
3638
+ display: grid;
3639
+ flex: none;
3640
+ place-items: center;
3641
+ width: 1.125rem;
3642
+ height: 1.125rem;
3643
+ padding: 0;
3644
+ border: 0;
3645
+ border-radius: var(--juxt-radius-full);
3646
+ background: transparent;
3647
+ color: inherit;
3648
+ cursor: pointer;
3649
+ opacity: 0.7;
3650
+ transition:
3651
+ background-color var(--juxt-duration-fast) var(--juxt-ease-standard),
3652
+ opacity var(--juxt-duration-fast) var(--juxt-ease-standard);
3653
+ }
3654
+ .j-tag--sm .j-tag__remove {
3655
+ width: 0.875rem;
3656
+ height: 0.875rem;
3657
+ }
3658
+ .j-tag__remove:hover:not(:disabled) {
3659
+ background: rgb(0 0 0 / 0.08);
3660
+ opacity: 1;
3661
+ }
3662
+ .dark .j-tag__remove:hover:not(:disabled),
3663
+ [data-theme='dark'] .j-tag__remove:hover:not(:disabled) {
3664
+ background: rgb(255 255 255 / 0.12);
3665
+ }
3666
+ .j-tag__remove > svg {
3667
+ width: 0.625rem;
3668
+ height: 0.625rem;
3669
+ }
3670
+ .j-tag--sm .j-tag__remove > svg {
3671
+ width: 0.5rem;
3672
+ height: 0.5rem;
3673
+ }
3674
+ .j-tag.is-disabled {
3675
+ opacity: 0.5;
3676
+ }
3677
+ .j-tag__remove:disabled {
3678
+ cursor: not-allowed;
3679
+ }
3680
+ }
3681
+
3682
+ @layer theme, base, juxt, components, utilities;
2128
3683
  @layer juxt {
2129
3684
  .j-textarea {
2130
3685
  align-items: stretch;
@@ -2160,6 +3715,102 @@ from {
2160
3715
  }
2161
3716
  }
2162
3717
 
3718
+ @layer theme, base, juxt, components, utilities;
3719
+ @layer juxt {
3720
+ .j-timeline {
3721
+ display: flex;
3722
+ flex-direction: column;
3723
+ margin: 0;
3724
+ padding: 0;
3725
+ list-style: none;
3726
+ font-family: var(--juxt-font-sans);
3727
+ }
3728
+ }
3729
+
3730
+ @layer theme, base, juxt, components, utilities;
3731
+ @layer juxt {
3732
+ .j-timeline-item {
3733
+ position: relative;
3734
+ display: flex;
3735
+ gap: var(--juxt-space-3);
3736
+ padding-bottom: var(--juxt-space-5);
3737
+ }
3738
+ .j-timeline-item:last-child {
3739
+ padding-bottom: 0;
3740
+ }
3741
+ .j-timeline-item__rail {
3742
+ position: relative;
3743
+ display: flex;
3744
+ flex: none;
3745
+ justify-content: center;
3746
+ width: 1rem;
3747
+ }
3748
+ .j-timeline-item__rail::before {
3749
+ content: '';
3750
+ position: absolute;
3751
+ top: 1rem;
3752
+ bottom: calc(var(--juxt-space-5) * -1);
3753
+ width: 1px;
3754
+ background: var(--juxt-border);
3755
+ }
3756
+ .j-timeline-item:last-child .j-timeline-item__rail::before {
3757
+ display: none;
3758
+ }
3759
+ .j-timeline-item__marker {
3760
+ z-index: 1;
3761
+ display: grid;
3762
+ place-items: center;
3763
+ width: 0.625rem;
3764
+ height: 0.625rem;
3765
+ margin-top: 0.25rem;
3766
+ border: 2px solid var(--juxt-surface);
3767
+ border-radius: var(--juxt-radius-full);
3768
+ background: var(--juxt-fg-disabled);
3769
+ box-shadow: 0 0 0 1px var(--juxt-border);
3770
+ }
3771
+ .j-timeline-item--complete .j-timeline-item__marker {
3772
+ background: var(--juxt-accent);
3773
+ box-shadow: none;
3774
+ }
3775
+ .j-timeline-item--current .j-timeline-item__marker {
3776
+ background: var(--juxt-surface);
3777
+ box-shadow: 0 0 0 2px var(--juxt-accent);
3778
+ }
3779
+ .j-timeline-item__content {
3780
+ flex: 1;
3781
+ min-width: 0;
3782
+ padding-bottom: var(--juxt-space-0-5);
3783
+ }
3784
+ .j-timeline-item__header {
3785
+ display: flex;
3786
+ flex-wrap: wrap;
3787
+ align-items: baseline;
3788
+ gap: var(--juxt-space-2);
3789
+ }
3790
+ .j-timeline-item__title {
3791
+ margin: 0;
3792
+ color: var(--juxt-fg);
3793
+ font-size: var(--juxt-text-md);
3794
+ font-weight: var(--juxt-weight-medium);
3795
+ letter-spacing: var(--juxt-tracking-tight);
3796
+ }
3797
+ .j-timeline-item--upcoming .j-timeline-item__title {
3798
+ color: var(--juxt-fg-muted);
3799
+ }
3800
+ .j-timeline-item__time {
3801
+ color: var(--juxt-fg-muted);
3802
+ font-size: var(--juxt-text-xs);
3803
+ font-variant-numeric: tabular-nums;
3804
+ }
3805
+ .j-timeline-item__body {
3806
+ margin-top: var(--juxt-space-0-5);
3807
+ color: var(--juxt-fg-secondary);
3808
+ font-size: var(--juxt-text-sm);
3809
+ line-height: var(--juxt-leading-normal);
3810
+ }
3811
+ }
3812
+
3813
+ @layer theme, base, juxt, components, utilities;
2163
3814
  @layer juxt {
2164
3815
  .j-toaster {
2165
3816
  --j-toast-width: 22.5rem;
@@ -2414,6 +4065,78 @@ to {
2414
4065
  }
2415
4066
  }
2416
4067
 
4068
+ @layer theme, base, juxt, components, utilities;
4069
+ @layer juxt {
4070
+ .j-toggle-group {
4071
+ --j-toggle-height: var(--juxt-control-md);
4072
+
4073
+ display: inline-flex;
4074
+ align-items: center;
4075
+ gap: 2px;
4076
+ padding: 2px;
4077
+ border-radius: var(--juxt-radius-md);
4078
+ background: var(--juxt-surface-sunken);
4079
+ box-shadow: inset 0 0 0 1px var(--juxt-border-subtle);
4080
+ font-family: var(--juxt-font-sans);
4081
+ }
4082
+ .j-toggle-group--sm {
4083
+ --j-toggle-height: var(--juxt-control-sm);
4084
+ }
4085
+ .j-toggle-group.is-disabled {
4086
+ opacity: 0.6;
4087
+ }
4088
+ }
4089
+
4090
+ @layer theme, base, juxt, components, utilities;
4091
+ @layer juxt {
4092
+ .j-toggle-group__item {
4093
+ display: inline-flex;
4094
+ align-items: center;
4095
+ justify-content: center;
4096
+ gap: var(--juxt-space-1-5);
4097
+ height: var(--j-toggle-height, var(--juxt-control-md));
4098
+ padding: 0 var(--juxt-space-3);
4099
+ border: 0;
4100
+ border-radius: var(--juxt-radius-sm);
4101
+ background: transparent;
4102
+ color: var(--juxt-fg-secondary);
4103
+ font: inherit;
4104
+ font-size: var(--juxt-text-sm);
4105
+ font-weight: var(--juxt-weight-medium);
4106
+ letter-spacing: var(--juxt-tracking-tight);
4107
+ white-space: nowrap;
4108
+ cursor: pointer;
4109
+ outline: 2px solid transparent;
4110
+ outline-offset: 0;
4111
+ -webkit-tap-highlight-color: transparent;
4112
+ transition:
4113
+ background-color var(--juxt-duration-fast) var(--juxt-ease-standard),
4114
+ color var(--juxt-duration-fast) var(--juxt-ease-standard),
4115
+ box-shadow var(--juxt-duration-fast) var(--juxt-ease-standard);
4116
+ }
4117
+ .j-toggle-group__item > svg {
4118
+ width: 1rem;
4119
+ height: 1rem;
4120
+ }
4121
+ .j-toggle-group__item:hover:not(:disabled) {
4122
+ color: var(--juxt-fg);
4123
+ }
4124
+ .j-toggle-group__item.is-selected {
4125
+ background: var(--juxt-surface);
4126
+ box-shadow: var(--juxt-shadow-sm);
4127
+ color: var(--juxt-fg);
4128
+ }
4129
+ .dark .j-toggle-group__item.is-selected,
4130
+ [data-theme='dark'] .j-toggle-group__item.is-selected {
4131
+ background: var(--juxt-surface-active);
4132
+ }
4133
+ .j-toggle-group__item:disabled {
4134
+ color: var(--juxt-fg-disabled);
4135
+ cursor: not-allowed;
4136
+ }
4137
+ }
4138
+
4139
+ @layer theme, base, juxt, components, utilities;
2417
4140
  @layer juxt {
2418
4141
  .j-tooltip {
2419
4142
  z-index: var(--juxt-z-tooltip);
@@ -2460,4 +4183,16 @@ to {
2460
4183
  );
2461
4184
  }
2462
4185
  }
4186
+
4187
+ @layer theme, base, juxt, components, utilities;
4188
+ @layer juxt {
4189
+ /*
4190
+ * Visual hiding is handled entirely by the shared `.j-sr-only` utility in
4191
+ * base.css | this component just gives it a typed, composable wrapper so it
4192
+ * can be used as `<JVisuallyHidden as="label">…</JVisuallyHidden>`.
4193
+ */
4194
+ .j-visually-hidden {
4195
+ display: block;
4196
+ }
4197
+ }
2463
4198
  /*$vite$:1*/