@juxtui/ui 0.3.0 → 0.5.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/dist/nuxt.js CHANGED
@@ -10,6 +10,7 @@ var components = [
10
10
  "JBadge",
11
11
  "JBanner",
12
12
  "JBreadcrumb",
13
+ "JBurger",
13
14
  "JButton",
14
15
  "JCard",
15
16
  "JCheckbox",
@@ -22,8 +23,12 @@ var components = [
22
23
  "JDropdownMenuSeparator",
23
24
  "JDropdownMenuSub",
24
25
  "JEmptyState",
26
+ "JFooter",
27
+ "JFooterColumn",
25
28
  "JInput",
26
29
  "JKbd",
30
+ "JNavbar",
31
+ "JNavbarLink",
27
32
  "JPagination",
28
33
  "JPopover",
29
34
  "JProgress",
@@ -33,6 +38,9 @@ var components = [
33
38
  "JSelect",
34
39
  "JSeparator",
35
40
  "JSheet",
41
+ "JSidebar",
42
+ "JSidebarGroup",
43
+ "JSidebarItem",
36
44
  "JSkeleton",
37
45
  "JSlider",
38
46
  "JSpinner",
package/dist/nuxt.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"nuxt.js","names":[],"sources":["../src/nuxt.ts"],"sourcesContent":["import type { NuxtModule } from '@nuxt/schema'\r\nimport { addComponent, addImports, defineNuxtModule } from '@nuxt/kit'\r\n\r\nexport interface ModuleOptions {\r\n /** Inject Juxt's stylesheet (tokens + component styles). Defaults to true. */\r\n css?: boolean\r\n}\r\n\r\nconst components = [\r\n 'JAccordion',\r\n 'JAccordionItem',\r\n 'JAlert',\r\n 'JAspectRatio',\r\n 'JAvatar',\r\n 'JAvatarGroup',\r\n 'JBadge',\r\n 'JBanner',\r\n 'JBreadcrumb',\r\n 'JButton',\r\n 'JCard',\r\n 'JCheckbox',\r\n 'JCollapsible',\r\n 'JCommandPalette',\r\n 'JDialog',\r\n 'JDropdownMenu',\r\n 'JDropdownMenuItem',\r\n 'JDropdownMenuLabel',\r\n 'JDropdownMenuSeparator',\r\n 'JDropdownMenuSub',\r\n 'JEmptyState',\r\n 'JInput',\r\n 'JKbd',\r\n 'JPagination',\r\n 'JPopover',\r\n 'JProgress',\r\n 'JRadio',\r\n 'JRadioGroup',\r\n 'JRating',\r\n 'JSelect',\r\n 'JSeparator',\r\n 'JSheet',\r\n 'JSkeleton',\r\n 'JSlider',\r\n 'JSpinner',\r\n 'JStat',\r\n 'JSwitch',\r\n 'JTabs',\r\n 'JTag',\r\n 'JTextarea',\r\n 'JTimeline',\r\n 'JTimelineItem',\r\n 'JToaster',\r\n 'JToggleGroup',\r\n 'JToggleGroupItem',\r\n 'JTooltip',\r\n 'JVisuallyHidden',\r\n] as const\r\n\r\nconst composables = ['toast', 'useToast', 'useRecentCommands', 'useHotkey', 'formatHotkey'] as const\r\n\r\n/**\r\n * Nuxt module: auto-imports every Juxt component and composable, and adds the\r\n * stylesheet.\r\n *\r\n * export default defineNuxtConfig({ modules: ['@juxtui/ui/nuxt'] })\r\n */\r\nconst juxtModule: NuxtModule<ModuleOptions> = defineNuxtModule<ModuleOptions>({\r\n meta: {\r\n name: '@juxtui/ui',\r\n configKey: 'juxt',\r\n compatibility: { nuxt: '>=3.15.0' },\r\n },\r\n defaults: {\r\n css: true,\r\n },\r\n setup(options, nuxt) {\r\n for (const name of components) addComponent({ name, export: name, filePath: '@juxtui/ui' })\r\n addImports(composables.map(name => ({ name, from: '@juxtui/ui' })))\r\n if (options.css) nuxt.options.css.unshift('@juxtui/ui/style.css')\r\n nuxt.options.build.transpile.push('@juxtui/ui')\r\n },\r\n})\r\n\r\nexport default juxtModule\r\n"],"mappings":";;AAQA,IAAM,aAAa;CACjB;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;AACF;AAEA,IAAM,cAAc;CAAC;CAAS;CAAY;CAAqB;CAAa;AAAc;;;;;;;AAQ1F,IAAM,aAAwC,iBAAgC;CAC5E,MAAM;EACJ,MAAM;EACN,WAAW;EACX,eAAe,EAAE,MAAM,WAAW;CACpC;CACA,UAAU,EACR,KAAK,KACP;CACA,MAAM,SAAS,MAAM;EACnB,KAAK,MAAM,QAAQ,YAAY,aAAa;GAAE;GAAM,QAAQ;GAAM,UAAU;EAAa,CAAC;EAC1F,WAAW,YAAY,KAAI,UAAS;GAAE;GAAM,MAAM;EAAa,EAAE,CAAC;EAClE,IAAI,QAAQ,KAAK,KAAK,QAAQ,IAAI,QAAQ,sBAAsB;EAChE,KAAK,QAAQ,MAAM,UAAU,KAAK,YAAY;CAChD;AACF,CAAC"}
1
+ {"version":3,"file":"nuxt.js","names":[],"sources":["../src/nuxt.ts"],"sourcesContent":["import type { NuxtModule } from '@nuxt/schema'\nimport { addComponent, addImports, defineNuxtModule } from '@nuxt/kit'\n\nexport interface ModuleOptions {\n /** Inject Juxt's stylesheet (tokens + component styles). Defaults to true. */\n css?: boolean\n}\n\nconst components = [\n 'JAccordion',\n 'JAccordionItem',\n 'JAlert',\n 'JAspectRatio',\n 'JAvatar',\n 'JAvatarGroup',\n 'JBadge',\n 'JBanner',\n 'JBreadcrumb',\n 'JBurger',\n 'JButton',\n 'JCard',\n 'JCheckbox',\n 'JCollapsible',\n 'JCommandPalette',\n 'JDialog',\n 'JDropdownMenu',\n 'JDropdownMenuItem',\n 'JDropdownMenuLabel',\n 'JDropdownMenuSeparator',\n 'JDropdownMenuSub',\n 'JEmptyState',\n 'JFooter',\n 'JFooterColumn',\n 'JInput',\n 'JKbd',\n 'JNavbar',\n 'JNavbarLink',\n 'JPagination',\n 'JPopover',\n 'JProgress',\n 'JRadio',\n 'JRadioGroup',\n 'JRating',\n 'JSelect',\n 'JSeparator',\n 'JSheet',\n 'JSidebar',\n 'JSidebarGroup',\n 'JSidebarItem',\n 'JSkeleton',\n 'JSlider',\n 'JSpinner',\n 'JStat',\n 'JSwitch',\n 'JTabs',\n 'JTag',\n 'JTextarea',\n 'JTimeline',\n 'JTimelineItem',\n 'JToaster',\n 'JToggleGroup',\n 'JToggleGroupItem',\n 'JTooltip',\n 'JVisuallyHidden',\n] as const\n\nconst composables = ['toast', 'useToast', 'useRecentCommands', 'useHotkey', 'formatHotkey'] as const\n\n/**\n * Nuxt module: auto-imports every Juxt component and composable, and adds the\n * stylesheet.\n *\n * export default defineNuxtConfig({ modules: ['@juxtui/ui/nuxt'] })\n */\nconst juxtModule: NuxtModule<ModuleOptions> = defineNuxtModule<ModuleOptions>({\n meta: {\n name: '@juxtui/ui',\n configKey: 'juxt',\n compatibility: { nuxt: '>=3.15.0' },\n },\n defaults: {\n css: true,\n },\n setup(options, nuxt) {\n for (const name of components) addComponent({ name, export: name, filePath: '@juxtui/ui' })\n addImports(composables.map(name => ({ name, from: '@juxtui/ui' })))\n if (options.css) nuxt.options.css.unshift('@juxtui/ui/style.css')\n nuxt.options.build.transpile.push('@juxtui/ui')\n },\n})\n\nexport default juxtModule\n"],"mappings":";;AAQA,IAAM,aAAa;CACjB;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;AACF;AAEA,IAAM,cAAc;CAAC;CAAS;CAAY;CAAqB;CAAa;AAAc;;;;;;;AAQ1F,IAAM,aAAwC,iBAAgC;CAC5E,MAAM;EACJ,MAAM;EACN,WAAW;EACX,eAAe,EAAE,MAAM,WAAW;CACpC;CACA,UAAU,EACR,KAAK,KACP;CACA,MAAM,SAAS,MAAM;EACnB,KAAK,MAAM,QAAQ,YAAY,aAAa;GAAE;GAAM,QAAQ;GAAM,UAAU;EAAa,CAAC;EAC1F,WAAW,YAAY,KAAI,UAAS;GAAE;GAAM,MAAM;EAAa,EAAE,CAAC;EAClE,IAAI,QAAQ,KAAK,KAAK,QAAQ,IAAI,QAAQ,sBAAsB;EAChE,KAAK,QAAQ,MAAM,UAAU,KAAK,YAAY;CAChD;AACF,CAAC"}
package/dist/style.css CHANGED
@@ -1097,6 +1097,79 @@
1097
1097
  }
1098
1098
  }
1099
1099
 
1100
+ @layer theme, base, juxt, components, utilities;
1101
+ @layer juxt {
1102
+ .j-burger {
1103
+ --j-burger-size: var(--juxt-control-md);
1104
+ --j-burger-width: 1rem;
1105
+ --j-burger-gap: 0.3125rem;
1106
+
1107
+ display: inline-grid;
1108
+ place-items: center;
1109
+ width: var(--j-burger-size);
1110
+ height: var(--j-burger-size);
1111
+ padding: 0;
1112
+ border: 0;
1113
+ border-radius: var(--juxt-radius-sm);
1114
+ background: transparent;
1115
+ color: var(--juxt-fg);
1116
+ cursor: pointer;
1117
+ -webkit-tap-highlight-color: transparent;
1118
+ transition-property: background-color, outline-color, outline-offset;
1119
+ }
1120
+ .j-burger--sm {
1121
+ --j-burger-size: var(--juxt-control-sm);
1122
+ --j-burger-width: 0.875rem;
1123
+ --j-burger-gap: 0.25rem;
1124
+ }
1125
+ .j-burger:hover {
1126
+ background: var(--juxt-surface-hover);
1127
+ }
1128
+ .j-burger__lines {
1129
+ position: relative;
1130
+ display: block;
1131
+ width: var(--j-burger-width);
1132
+ height: calc(var(--j-burger-gap) * 2 + 1.5px);
1133
+ }
1134
+ .j-burger__line {
1135
+ position: absolute;
1136
+ left: 0;
1137
+ width: 100%;
1138
+ height: 1.5px;
1139
+ border-radius: 1px;
1140
+ background: currentColor;
1141
+ transition:
1142
+ transform var(--juxt-duration-normal) var(--juxt-ease-out),
1143
+ opacity var(--juxt-duration-fast) var(--juxt-ease-standard);
1144
+ }
1145
+ .j-burger__line:nth-child(1) {
1146
+ top: 0;
1147
+ }
1148
+ .j-burger__line:nth-child(2) {
1149
+ top: var(--j-burger-gap);
1150
+ }
1151
+ .j-burger__line:nth-child(3) {
1152
+ top: calc(var(--j-burger-gap) * 2);
1153
+ }
1154
+
1155
+ /* Outer lines meet in the middle and cross; the middle one fades. */
1156
+ .j-burger[data-state='open'] .j-burger__line:nth-child(1) {
1157
+ transform: translateY(var(--j-burger-gap)) rotate(45deg);
1158
+ }
1159
+ .j-burger[data-state='open'] .j-burger__line:nth-child(2) {
1160
+ opacity: 0;
1161
+ transform: scaleX(0.4);
1162
+ }
1163
+ .j-burger[data-state='open'] .j-burger__line:nth-child(3) {
1164
+ transform: translateY(calc(var(--j-burger-gap) * -1)) rotate(-45deg);
1165
+ }
1166
+ @media (prefers-reduced-motion: reduce) {
1167
+ .j-burger__line {
1168
+ transition-duration: 0ms;
1169
+ }
1170
+ }
1171
+ }
1172
+
1100
1173
  @layer theme, base, juxt, components, utilities;
1101
1174
  @layer juxt {
1102
1175
  .j-button {
@@ -2251,6 +2324,119 @@ to {
2251
2324
  }
2252
2325
  }
2253
2326
 
2327
+ @layer theme, base, juxt, components, utilities;
2328
+ @layer juxt {
2329
+ .j-footer {
2330
+ background: var(--juxt-bg);
2331
+ color: var(--juxt-fg-secondary);
2332
+ font-family: var(--juxt-font-sans);
2333
+ font-size: var(--juxt-text-sm);
2334
+ }
2335
+ .j-footer.is-bordered {
2336
+ border-top: 1px solid var(--juxt-border-subtle);
2337
+ }
2338
+ .dark .j-footer.is-bordered,
2339
+ [data-theme='dark'] .j-footer.is-bordered {
2340
+ border-top-color: var(--juxt-border);
2341
+ }
2342
+ .j-footer__inner {
2343
+ max-width: var(--j-footer-max);
2344
+ margin: 0 auto;
2345
+ padding: var(--juxt-space-12) var(--juxt-space-4) var(--juxt-space-8);
2346
+ }
2347
+ .j-footer__top {
2348
+ display: grid;
2349
+ grid-template-columns: minmax(0, 1fr);
2350
+ gap: var(--juxt-space-10);
2351
+ }
2352
+ .j-footer__brand {
2353
+ display: flex;
2354
+ flex-direction: column;
2355
+ gap: var(--juxt-space-3);
2356
+ max-width: 18rem;
2357
+ color: var(--juxt-fg-muted);
2358
+ line-height: var(--juxt-leading-normal);
2359
+ }
2360
+ .j-footer__columns {
2361
+ display: grid;
2362
+ grid-template-columns: repeat(2, minmax(0, 1fr));
2363
+ gap: var(--juxt-space-8) var(--juxt-space-6);
2364
+ }
2365
+ @media (min-width: 768px) {
2366
+ .j-footer__top {
2367
+ grid-template-columns: minmax(12rem, 1fr) minmax(0, 2fr);
2368
+ }
2369
+ .j-footer__columns {
2370
+ grid-template-columns: repeat(auto-fit, minmax(8rem, 1fr));
2371
+ }
2372
+ }
2373
+ .j-footer__bottom {
2374
+ display: flex;
2375
+ flex-wrap: wrap;
2376
+ align-items: center;
2377
+ justify-content: space-between;
2378
+ gap: var(--juxt-space-3) var(--juxt-space-6);
2379
+ margin-top: var(--juxt-space-12);
2380
+ padding-top: var(--juxt-space-6);
2381
+ border-top: 1px solid var(--juxt-border-subtle);
2382
+ color: var(--juxt-fg-muted);
2383
+ font-size: var(--juxt-text-xs);
2384
+ }
2385
+ .dark .j-footer__bottom,
2386
+ [data-theme='dark'] .j-footer__bottom {
2387
+ border-top-color: var(--juxt-border);
2388
+ }
2389
+ .j-footer__bottom a {
2390
+ color: inherit;
2391
+ text-decoration: none;
2392
+ transition: color var(--juxt-duration-fast) var(--juxt-ease-standard);
2393
+ }
2394
+ .j-footer__bottom a:hover {
2395
+ color: var(--juxt-fg);
2396
+ }
2397
+ }
2398
+
2399
+ @layer theme, base, juxt, components, utilities;
2400
+ @layer juxt {
2401
+ .j-footer-column {
2402
+ display: flex;
2403
+ flex-direction: column;
2404
+ gap: var(--juxt-space-3);
2405
+ min-width: 0;
2406
+ }
2407
+ .j-footer-column__title {
2408
+ margin: 0;
2409
+ color: var(--juxt-fg);
2410
+ font-size: var(--juxt-text-sm);
2411
+ font-weight: var(--juxt-weight-medium);
2412
+ letter-spacing: var(--juxt-tracking-tight);
2413
+ }
2414
+ .j-footer-column__links {
2415
+ display: flex;
2416
+ flex-direction: column;
2417
+ align-items: flex-start;
2418
+ gap: var(--juxt-space-2);
2419
+ }
2420
+ .j-footer-column__links a {
2421
+ border-radius: var(--juxt-radius-xs);
2422
+ color: var(--juxt-fg-muted);
2423
+ text-decoration: none;
2424
+ outline: 2px solid transparent;
2425
+ outline-offset: 0;
2426
+ transition:
2427
+ color var(--juxt-duration-fast) var(--juxt-ease-standard),
2428
+ outline-color var(--juxt-duration-fast) var(--juxt-ease-out),
2429
+ outline-offset var(--juxt-duration-fast) var(--juxt-ease-out);
2430
+ }
2431
+ .j-footer-column__links a:hover {
2432
+ color: var(--juxt-fg);
2433
+ }
2434
+ .j-footer-column__links a:focus-visible {
2435
+ outline-color: var(--juxt-ring);
2436
+ outline-offset: 2px;
2437
+ }
2438
+ }
2439
+
2254
2440
  @layer theme, base, juxt, components, utilities;
2255
2441
  @layer juxt {
2256
2442
  .j-field {
@@ -2352,6 +2538,193 @@ to {
2352
2538
  }
2353
2539
  }
2354
2540
 
2541
+ @layer theme, base, juxt, components, utilities;
2542
+ @layer juxt {
2543
+ .j-navbar {
2544
+ --j-navbar-height: 3.5rem;
2545
+
2546
+ position: relative;
2547
+ z-index: var(--juxt-z-sticky);
2548
+ background: var(--juxt-bg);
2549
+ color: var(--juxt-fg);
2550
+ font-family: var(--juxt-font-sans);
2551
+ }
2552
+ .j-navbar.is-sticky {
2553
+ position: sticky;
2554
+ top: 0;
2555
+ }
2556
+ .j-navbar.is-bordered {
2557
+ box-shadow: inset 0 -1px 0 var(--juxt-border-subtle);
2558
+ }
2559
+ .dark .j-navbar.is-bordered,
2560
+ [data-theme='dark'] .j-navbar.is-bordered {
2561
+ box-shadow: inset 0 -1px 0 var(--juxt-border);
2562
+ }
2563
+ .j-navbar__bar {
2564
+ display: flex;
2565
+ align-items: center;
2566
+ gap: var(--juxt-space-6);
2567
+ max-width: var(--j-navbar-max);
2568
+ height: var(--j-navbar-height);
2569
+ margin: 0 auto;
2570
+ padding: 0 var(--juxt-space-4);
2571
+ }
2572
+ .j-navbar__brand {
2573
+ display: flex;
2574
+ flex: none;
2575
+ align-items: center;
2576
+ }
2577
+ .j-navbar__links {
2578
+ display: flex;
2579
+ align-items: center;
2580
+ gap: var(--juxt-space-1);
2581
+ min-width: 0;
2582
+ }
2583
+ .j-navbar__end {
2584
+ display: flex;
2585
+ align-items: center;
2586
+ gap: var(--juxt-space-2);
2587
+ margin-left: auto;
2588
+ }
2589
+ .j-navbar__actions {
2590
+ display: flex;
2591
+ align-items: center;
2592
+ gap: var(--juxt-space-2);
2593
+ }
2594
+ .j-navbar__burger {
2595
+ display: none;
2596
+ margin-right: calc(var(--juxt-space-2) * -1);
2597
+ }
2598
+
2599
+ /* Mobile menu: a panel that drops from the bar, links stacked with big targets. */
2600
+ .j-navbar__menu {
2601
+ position: absolute;
2602
+ top: 100%;
2603
+ right: 0;
2604
+ left: 0;
2605
+ display: flex;
2606
+ flex-direction: column;
2607
+ gap: var(--juxt-space-4);
2608
+ max-height: calc(100dvh - var(--j-navbar-height));
2609
+ padding: var(--juxt-space-3) var(--juxt-space-4) var(--juxt-space-5);
2610
+ overflow-y: auto;
2611
+ border-bottom: 1px solid var(--juxt-border);
2612
+ background: var(--juxt-bg);
2613
+ box-shadow: var(--juxt-shadow-md);
2614
+ }
2615
+ .j-navbar__menu-links {
2616
+ display: flex;
2617
+ flex-direction: column;
2618
+ gap: var(--juxt-space-0-5);
2619
+ }
2620
+ .j-navbar__menu-links .j-navbar-link {
2621
+ justify-content: flex-start;
2622
+ height: 2.75rem;
2623
+ padding: 0 var(--juxt-space-3);
2624
+ font-size: var(--juxt-text-lg);
2625
+ }
2626
+ .j-navbar__menu-footer {
2627
+ display: flex;
2628
+ flex-direction: column;
2629
+ gap: var(--juxt-space-2);
2630
+ padding-top: var(--juxt-space-4);
2631
+ border-top: 1px solid var(--juxt-border-subtle);
2632
+ }
2633
+ .j-navbar__menu-footer > * {
2634
+ width: 100%;
2635
+ }
2636
+ .j-navbar-menu-enter-active {
2637
+ transition:
2638
+ opacity var(--juxt-duration-fast) var(--juxt-ease-out),
2639
+ transform var(--juxt-duration-normal) var(--juxt-ease-out);
2640
+ }
2641
+ .j-navbar-menu-leave-active {
2642
+ transition:
2643
+ opacity var(--juxt-duration-instant) var(--juxt-ease-in),
2644
+ transform var(--juxt-duration-instant) var(--juxt-ease-in);
2645
+ }
2646
+ .j-navbar-menu-enter-from,
2647
+ .j-navbar-menu-leave-to {
2648
+ opacity: 0;
2649
+ transform: translateY(calc(var(--juxt-motion-shift) * -1));
2650
+ }
2651
+
2652
+ /* Collapse points. Above them the menu never shows, below them the links hide. */
2653
+ .j-navbar--collapse-never .j-navbar__menu {
2654
+ display: none !important;
2655
+ }
2656
+ @media (max-width: 639.98px) {
2657
+ .j-navbar--collapse-sm .j-navbar__links { display: none;
2658
+ }
2659
+ .j-navbar--collapse-sm .j-navbar__burger { display: inline-grid;
2660
+ }
2661
+ }
2662
+ @media (min-width: 640px) {
2663
+ .j-navbar--collapse-sm .j-navbar__menu { display: none !important;
2664
+ }
2665
+ }
2666
+ @media (max-width: 767.98px) {
2667
+ .j-navbar--collapse-md .j-navbar__links { display: none;
2668
+ }
2669
+ .j-navbar--collapse-md .j-navbar__burger { display: inline-grid;
2670
+ }
2671
+ }
2672
+ @media (min-width: 768px) {
2673
+ .j-navbar--collapse-md .j-navbar__menu { display: none !important;
2674
+ }
2675
+ }
2676
+ @media (max-width: 1023.98px) {
2677
+ .j-navbar--collapse-lg .j-navbar__links { display: none;
2678
+ }
2679
+ .j-navbar--collapse-lg .j-navbar__burger { display: inline-grid;
2680
+ }
2681
+ }
2682
+ @media (min-width: 1024px) {
2683
+ .j-navbar--collapse-lg .j-navbar__menu { display: none !important;
2684
+ }
2685
+ }
2686
+ }
2687
+
2688
+ @layer theme, base, juxt, components, utilities;
2689
+ @layer juxt {
2690
+ .j-navbar-link {
2691
+ display: inline-flex;
2692
+ align-items: center;
2693
+ gap: var(--juxt-space-1-5);
2694
+ height: var(--juxt-control-sm);
2695
+ padding: 0 var(--juxt-space-2-5);
2696
+ border-radius: var(--juxt-radius-sm);
2697
+ color: var(--juxt-fg-muted);
2698
+ font-size: var(--juxt-text-sm);
2699
+ font-weight: var(--juxt-weight-medium);
2700
+ letter-spacing: var(--juxt-tracking-tight);
2701
+ text-decoration: none;
2702
+ white-space: nowrap;
2703
+ cursor: pointer;
2704
+ -webkit-tap-highlight-color: transparent;
2705
+ transition-property: color, background-color, outline-color, outline-offset;
2706
+ }
2707
+ .j-navbar-link:hover {
2708
+ color: var(--juxt-fg);
2709
+ }
2710
+ .j-navbar-link.is-active {
2711
+ color: var(--juxt-fg);
2712
+ }
2713
+
2714
+ /* In the mobile menu the current page gets a quiet fill, like a selected row. */
2715
+ .j-navbar__menu .j-navbar-link.is-active {
2716
+ background: var(--juxt-surface-hover);
2717
+ }
2718
+ .j-navbar-link__icon {
2719
+ display: inline-flex;
2720
+ color: var(--juxt-fg-muted);
2721
+ }
2722
+ .j-navbar-link__icon > svg {
2723
+ width: 1rem;
2724
+ height: 1rem;
2725
+ }
2726
+ }
2727
+
2355
2728
  @layer theme, base, juxt, components, utilities;
2356
2729
  @layer juxt {
2357
2730
  .j-pagination {
@@ -3108,6 +3481,205 @@ to {
3108
3481
  }
3109
3482
  }
3110
3483
 
3484
+ @layer theme, base, juxt, components, utilities;
3485
+ @layer juxt {
3486
+ .j-sidebar {
3487
+ display: flex;
3488
+ flex-direction: column;
3489
+ width: 100%;
3490
+ /*
3491
+ * Not `height: 100%`: inside a parent that only has a min-height (e.g. a
3492
+ * `min-h-screen` flex row) a percentage height can't resolve, and a set
3493
+ * height also stops the flex/grid parent from stretching the sidebar, so it
3494
+ * would collapse to its content. Min and max of 100% pin it to a parent with
3495
+ * a real height (nav scrolls inside), and leave it `auto` everywhere else, so
3496
+ * the parent stretches it to full height and the footer stays at the bottom.
3497
+ */
3498
+ height: auto;
3499
+ min-height: 100%;
3500
+ max-height: 100%;
3501
+ color: var(--juxt-fg);
3502
+ font-family: var(--juxt-font-sans);
3503
+ }
3504
+ .j-sidebar__header {
3505
+ display: flex;
3506
+ align-items: center;
3507
+ gap: var(--juxt-space-2);
3508
+ padding: var(--juxt-space-3) var(--juxt-space-3) var(--juxt-space-2);
3509
+ }
3510
+ .j-sidebar__nav {
3511
+ display: flex;
3512
+ flex: 1;
3513
+ flex-direction: column;
3514
+ gap: var(--juxt-space-4);
3515
+ min-height: 0;
3516
+ padding: var(--juxt-space-2);
3517
+ overflow-y: auto;
3518
+ overscroll-behavior: contain;
3519
+ }
3520
+ .j-sidebar__footer {
3521
+ display: flex;
3522
+ flex-direction: column;
3523
+ gap: var(--juxt-space-0-5);
3524
+ padding: var(--juxt-space-2);
3525
+ border-top: 1px solid var(--juxt-border-subtle);
3526
+ }
3527
+ .dark .j-sidebar__footer,
3528
+ [data-theme='dark'] .j-sidebar__footer {
3529
+ border-top-color: var(--juxt-border);
3530
+ }
3531
+ }
3532
+
3533
+ @layer theme, base, juxt, components, utilities;
3534
+ @layer juxt {
3535
+ .j-sidebar-group {
3536
+ display: flex;
3537
+ flex-direction: column;
3538
+ gap: var(--juxt-space-0-5);
3539
+ }
3540
+ .j-sidebar-group__title {
3541
+ display: flex;
3542
+ align-items: center;
3543
+ justify-content: space-between;
3544
+ gap: var(--juxt-space-2);
3545
+ margin: 0;
3546
+ padding: var(--juxt-space-1) var(--juxt-space-2);
3547
+ color: var(--juxt-fg-muted);
3548
+ font-size: var(--juxt-text-xs);
3549
+ font-weight: var(--juxt-weight-medium);
3550
+ line-height: var(--juxt-leading-snug);
3551
+ }
3552
+ .j-sidebar-group__toggle {
3553
+ width: 100%;
3554
+ border: 0;
3555
+ border-radius: var(--juxt-radius-xs);
3556
+ background: transparent;
3557
+ font-family: inherit;
3558
+ text-align: left;
3559
+ cursor: pointer;
3560
+ transition-property: color, outline-color, outline-offset;
3561
+ }
3562
+ .j-sidebar-group__toggle:hover {
3563
+ color: var(--juxt-fg-secondary);
3564
+ }
3565
+ .j-sidebar-group__chevron {
3566
+ flex: none;
3567
+ width: 0.75rem;
3568
+ height: 0.75rem;
3569
+ opacity: 0;
3570
+ transform: rotate(-90deg);
3571
+ transition:
3572
+ transform var(--juxt-duration-normal) var(--juxt-ease-out),
3573
+ opacity var(--juxt-duration-fast) var(--juxt-ease-standard);
3574
+ }
3575
+
3576
+ /* The chevron only appears on hover or focus, or while the group is folded. */
3577
+ .j-sidebar-group__toggle:hover .j-sidebar-group__chevron,
3578
+ .j-sidebar-group__toggle:focus-visible .j-sidebar-group__chevron,
3579
+ .j-sidebar-group[data-state='closed'] .j-sidebar-group__chevron {
3580
+ opacity: 1;
3581
+ }
3582
+ .j-sidebar-group[data-state='open'] .j-sidebar-group__chevron {
3583
+ transform: none;
3584
+ }
3585
+ .j-sidebar-group__panel {
3586
+ display: grid;
3587
+ grid-template-rows: 1fr;
3588
+ transition: grid-template-rows var(--juxt-duration-normal) var(--juxt-ease-out);
3589
+ }
3590
+ .j-sidebar-group[data-state='closed'] .j-sidebar-group__panel {
3591
+ grid-template-rows: 0fr;
3592
+ }
3593
+ .j-sidebar-group__panel-inner {
3594
+ min-height: 0;
3595
+ overflow: hidden;
3596
+ }
3597
+ .j-sidebar-group__items {
3598
+ display: flex;
3599
+ flex-direction: column;
3600
+ gap: var(--juxt-space-0-5);
3601
+ }
3602
+ @media (prefers-reduced-motion: reduce) {
3603
+ .j-sidebar-group__panel,
3604
+ .j-sidebar-group__chevron {
3605
+ transition: none;
3606
+ }
3607
+ }
3608
+ }
3609
+
3610
+ @layer theme, base, juxt, components, utilities;
3611
+ @layer juxt {
3612
+ .j-sidebar-item {
3613
+ position: relative;
3614
+ display: flex;
3615
+ align-items: center;
3616
+ gap: var(--juxt-space-2);
3617
+ min-height: var(--juxt-control-sm);
3618
+ padding: 0 var(--juxt-space-2);
3619
+ border-radius: var(--juxt-radius-sm);
3620
+ color: var(--juxt-fg-secondary);
3621
+ font-size: var(--juxt-text-sm);
3622
+ letter-spacing: var(--juxt-tracking-tight);
3623
+ text-decoration: none;
3624
+ cursor: pointer;
3625
+ -webkit-tap-highlight-color: transparent;
3626
+ transition-property: color, background-color, outline-color, outline-offset;
3627
+ }
3628
+ .j-sidebar-item:hover:not(.is-disabled) {
3629
+ background: var(--juxt-surface-hover);
3630
+ color: var(--juxt-fg);
3631
+ }
3632
+ .j-sidebar-item.is-active {
3633
+ background: var(--juxt-surface-hover);
3634
+ color: var(--juxt-fg);
3635
+ font-weight: var(--juxt-weight-medium);
3636
+ }
3637
+
3638
+ /* Same marker as the command palette: a short accent line where you are. */
3639
+ .j-sidebar-item.is-active::before {
3640
+ content: '';
3641
+ position: absolute;
3642
+ top: 0.4375rem;
3643
+ bottom: 0.4375rem;
3644
+ left: 0;
3645
+ width: 2px;
3646
+ border-radius: 0 2px 2px 0;
3647
+ background: var(--juxt-accent);
3648
+ }
3649
+ .j-sidebar-item.is-disabled {
3650
+ color: var(--juxt-fg-disabled);
3651
+ cursor: not-allowed;
3652
+ }
3653
+ .j-sidebar-item__icon {
3654
+ display: inline-flex;
3655
+ flex: none;
3656
+ color: var(--juxt-fg-muted);
3657
+ }
3658
+ .j-sidebar-item.is-active .j-sidebar-item__icon,
3659
+ .j-sidebar-item:hover:not(.is-disabled) .j-sidebar-item__icon {
3660
+ color: var(--juxt-fg);
3661
+ }
3662
+ .j-sidebar-item__icon > svg {
3663
+ width: 1rem;
3664
+ height: 1rem;
3665
+ }
3666
+ .j-sidebar-item__label {
3667
+ flex: 1;
3668
+ min-width: 0;
3669
+ overflow: hidden;
3670
+ text-overflow: ellipsis;
3671
+ white-space: nowrap;
3672
+ }
3673
+ .j-sidebar-item__trailing {
3674
+ display: inline-flex;
3675
+ flex: none;
3676
+ align-items: center;
3677
+ color: var(--juxt-fg-muted);
3678
+ font-size: var(--juxt-text-xs);
3679
+ font-variant-numeric: tabular-nums;
3680
+ }
3681
+ }
3682
+
3111
3683
  @layer theme, base, juxt, components, utilities;
3112
3684
  @layer juxt {
3113
3685
  .j-skeleton {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@juxtui/ui",
3
- "version": "0.3.0",
3
+ "version": "0.5.0",
4
4
  "description": "Thoughtfully crafted components for Nuxt & Vue.",
5
5
  "license": "MIT",
6
6
  "author": "Julius K.",