@orangecheck/app-design 0.5.12 → 0.6.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/index.mjs CHANGED
@@ -2584,6 +2584,57 @@ function SectionSwitch({
2584
2584
  }
2585
2585
  );
2586
2586
  }
2587
+ function TabBar({ items }) {
2588
+ return /* @__PURE__ */ jsx(
2589
+ "nav",
2590
+ {
2591
+ "aria-label": "Pages",
2592
+ "data-oca-tabbar": "",
2593
+ className: "fixed inset-x-0 bottom-0 z-40 border-t border-border bg-background/90 pb-[env(safe-area-inset-bottom)] backdrop-blur-md md:hidden",
2594
+ children: /* @__PURE__ */ jsx(
2595
+ "div",
2596
+ {
2597
+ className: "mx-auto grid h-14 max-w-[32rem] px-1.5",
2598
+ style: { gridTemplateColumns: `repeat(${items.length}, minmax(0, 1fr))` },
2599
+ children: items.map((it) => /* @__PURE__ */ jsxs(
2600
+ Link2,
2601
+ {
2602
+ href: it.href,
2603
+ "aria-current": it.active ? "page" : void 0,
2604
+ className: cn(
2605
+ "flex min-w-0 flex-col items-center justify-center gap-1 rounded-2xl text-[0.6875rem] leading-none outline-none transition-colors [-webkit-tap-highlight-color:transparent] focus-visible:ring-2 focus-visible:ring-inset focus-visible:ring-ring",
2606
+ it.active ? "text-foreground" : "text-muted-foreground hover:text-foreground"
2607
+ ),
2608
+ children: [
2609
+ /* @__PURE__ */ jsxs(
2610
+ "span",
2611
+ {
2612
+ className: cn(
2613
+ "relative flex h-7 w-12 items-center justify-center rounded-full transition-[background-color,box-shadow] duration-200",
2614
+ "[&_svg]:size-[1.125rem] [&_svg]:shrink-0",
2615
+ it.active ? "bg-card shadow-sm ring-1 ring-border [&_svg]:stroke-2" : "[&_svg]:stroke-[1.75]"
2616
+ ),
2617
+ children: [
2618
+ it.icon,
2619
+ it.badge ? /* @__PURE__ */ jsx("span", { "aria-hidden": true, className: "absolute right-2.5 top-0.5 size-2 rounded-full bg-oca-orange ring-2 ring-background" }) : null
2620
+ ]
2621
+ }
2622
+ ),
2623
+ /* @__PURE__ */ jsx("span", { className: "max-w-full truncate px-0.5", children: it.label }),
2624
+ it.badge ? /* @__PURE__ */ jsx("span", { className: "sr-only", children: it.badge }) : null
2625
+ ]
2626
+ },
2627
+ it.href
2628
+ ))
2629
+ }
2630
+ )
2631
+ }
2632
+ );
2633
+ }
2634
+ function tabsFor(groups) {
2635
+ const items = groups.flatMap((g) => g.items);
2636
+ return items.length >= 2 && items.length <= 5 && items.every((it) => it.icon) ? items : null;
2637
+ }
2587
2638
  var activeItem = (groups) => groups.flatMap((g) => g.items).find((it) => it.active);
2588
2639
  var warned = /* @__PURE__ */ new Set();
2589
2640
  function warnDuplicateLabels(groups) {
@@ -2614,6 +2665,7 @@ function AppShell({
2614
2665
  const current = sections && sections.length > 0 ? sections.find((sec) => sec.id === activeSection) ?? sections.find((sec) => activeItem(sec.groups)) ?? sections[0] : void 0;
2615
2666
  const groups = current ? [...current.groups, ...persistent] : [...nav ?? [], ...persistent];
2616
2667
  warnDuplicateLabels(groups);
2668
+ const tabs = current ? null : tabsFor(groups);
2617
2669
  const page = activeItem(groups);
2618
2670
  const place = useMemo(
2619
2671
  () => ({
@@ -2623,66 +2675,95 @@ function AppShell({
2623
2675
  [current, page?.label, pageOverride]
2624
2676
  );
2625
2677
  const switcher = sections && current && sections.length > 1 ? /* @__PURE__ */ jsx(SectionSwitch, { sections, current, onNavigate: () => setOpen(false) }) : null;
2626
- return /* @__PURE__ */ jsx(ShellContext.Provider, { value: place, children: /* @__PURE__ */ jsxs("div", { className: cn("min-h-dvh bg-background", className), children: [
2627
- /* @__PURE__ */ jsxs("div", { className: "sticky top-0 z-40 border-b border-border bg-background/90 backdrop-blur-md lg:hidden", children: [
2628
- /* @__PURE__ */ jsxs("div", { className: "flex h-14 items-center gap-2 px-3", children: [
2629
- /* @__PURE__ */ jsxs(Sheet, { open, onOpenChange: setOpen, children: [
2630
- /* @__PURE__ */ jsx(
2631
- SheetTrigger,
2678
+ return /* @__PURE__ */ jsx(ShellContext.Provider, { value: place, children: /* @__PURE__ */ jsxs(
2679
+ "div",
2680
+ {
2681
+ className: cn(
2682
+ "min-h-dvh bg-background",
2683
+ tabs && "max-md:pb-[calc(3.5rem_+_env(safe-area-inset-bottom))]",
2684
+ className
2685
+ ),
2686
+ children: [
2687
+ /* @__PURE__ */ jsxs("div", { className: "sticky top-0 z-40 border-b border-border bg-background/90 backdrop-blur-md lg:hidden", children: [
2688
+ /* @__PURE__ */ jsxs("div", { className: "flex h-14 items-center gap-2 px-3", children: [
2689
+ /* @__PURE__ */ jsxs(Sheet, { open, onOpenChange: setOpen, children: [
2690
+ /* @__PURE__ */ jsx(
2691
+ SheetTrigger,
2692
+ {
2693
+ className: cn(
2694
+ "inline-flex size-10 items-center justify-center rounded-full hover:bg-accent",
2695
+ // The tab bar holds every page; the sheet is left for a footer.
2696
+ tabs && !footer && "max-md:hidden"
2697
+ ),
2698
+ "aria-label": "Open navigation",
2699
+ children: /* @__PURE__ */ jsx(Menu, { className: "size-5" })
2700
+ }
2701
+ ),
2702
+ /* @__PURE__ */ jsxs(SheetContent, { side: "left", className: "flex flex-col gap-6 overflow-y-auto p-4 pt-16", children: [
2703
+ /* @__PURE__ */ jsx(SheetTitle, { className: "sr-only", children: "Navigation" }),
2704
+ switcher,
2705
+ /* @__PURE__ */ jsx("div", { className: tabs ? "max-md:hidden" : void 0, children: /* @__PURE__ */ jsx(SideNav, { groups, onNavigate: () => setOpen(false) }) }),
2706
+ footer ? /* @__PURE__ */ jsx("div", { className: "mt-auto flex flex-col gap-3", children: footer }) : null
2707
+ ] })
2708
+ ] }),
2709
+ /* @__PURE__ */ jsx(Link2, { href: home, "aria-label": "Home", className: "rounded-lg p-1", children: /* @__PURE__ */ jsx(Lockup, { size: 22 }) }),
2710
+ /* @__PURE__ */ jsx("div", { className: "ml-auto flex items-center", children: account })
2711
+ ] }),
2712
+ place.page ? /* @__PURE__ */ jsxs(
2713
+ "div",
2632
2714
  {
2633
- className: "inline-flex size-10 items-center justify-center rounded-full hover:bg-accent",
2634
- "aria-label": "Open navigation",
2635
- children: /* @__PURE__ */ jsx(Menu, { className: "size-5" })
2715
+ className: cn(
2716
+ "flex h-9 items-center gap-1.5 border-t border-border px-4 text-[0.875rem]",
2717
+ // The active tab already names the page.
2718
+ tabs && !pageOverride && "max-md:hidden"
2719
+ ),
2720
+ children: [
2721
+ place.section ? /* @__PURE__ */ jsxs(Fragment, { children: [
2722
+ /* @__PURE__ */ jsx("span", { className: "shrink-0 text-muted-foreground", children: place.section }),
2723
+ /* @__PURE__ */ jsx(ChevronRight, { "aria-hidden": true, className: "size-3.5 shrink-0 text-muted-foreground" })
2724
+ ] }) : null,
2725
+ /* @__PURE__ */ jsx("span", { className: "truncate font-medium", children: place.page })
2726
+ ]
2636
2727
  }
2637
- ),
2638
- /* @__PURE__ */ jsxs(SheetContent, { side: "left", className: "flex flex-col gap-6 overflow-y-auto p-4 pt-16", children: [
2639
- /* @__PURE__ */ jsx(SheetTitle, { className: "sr-only", children: "Navigation" }),
2728
+ ) : null
2729
+ ] }),
2730
+ /* @__PURE__ */ jsxs("div", { className: "mx-auto flex w-full max-w-[90rem]", children: [
2731
+ /* @__PURE__ */ jsxs("aside", { className: "sticky top-0 hidden h-dvh w-[17rem] shrink-0 flex-col gap-6 overflow-y-auto px-4 py-6 lg:flex", children: [
2732
+ /* @__PURE__ */ jsx(Link2, { href: home, className: "px-2", "aria-label": "Home", children: /* @__PURE__ */ jsx(Lockup, { size: 26 }) }),
2640
2733
  switcher,
2641
- /* @__PURE__ */ jsx(SideNav, { groups, onNavigate: () => setOpen(false) }),
2642
- footer ? /* @__PURE__ */ jsx("div", { className: "mt-auto flex flex-col gap-3", children: footer }) : null
2734
+ /* @__PURE__ */ jsx(SideNav, { groups }),
2735
+ /* @__PURE__ */ jsx("div", { className: "mt-auto flex flex-col gap-3", children: footer })
2736
+ ] }),
2737
+ /* @__PURE__ */ jsxs("div", { className: "flex min-w-0 flex-1 flex-col", children: [
2738
+ /* @__PURE__ */ jsx("div", { className: "hidden h-[4.5rem] items-center justify-end gap-3 px-8 lg:flex", children: account }),
2739
+ banner ? /* @__PURE__ */ jsx("div", { className: "px-4 pb-2 pt-4 md:px-8 lg:pt-0", children: banner }) : null,
2740
+ /* @__PURE__ */ jsx("main", { id: "main-content", className: "flex-1 px-4 pb-16 pt-6 md:px-8 lg:pt-2", children: /* @__PURE__ */ jsx("div", { className: "mx-auto w-full max-w-[72rem]", children }) })
2643
2741
  ] })
2644
2742
  ] }),
2645
- /* @__PURE__ */ jsx(Link2, { href: home, "aria-label": "Home", className: "rounded-lg p-1", children: /* @__PURE__ */ jsx(Lockup, { size: 22 }) }),
2646
- /* @__PURE__ */ jsx("div", { className: "ml-auto flex items-center", children: account })
2647
- ] }),
2648
- place.page ? /* @__PURE__ */ jsxs("div", { className: "flex h-9 items-center gap-1.5 border-t border-border px-4 text-[0.875rem]", children: [
2649
- place.section ? /* @__PURE__ */ jsxs(Fragment, { children: [
2650
- /* @__PURE__ */ jsx("span", { className: "shrink-0 text-muted-foreground", children: place.section }),
2651
- /* @__PURE__ */ jsx(ChevronRight, { "aria-hidden": true, className: "size-3.5 shrink-0 text-muted-foreground" })
2652
- ] }) : null,
2653
- /* @__PURE__ */ jsx("span", { className: "truncate font-medium", children: place.page })
2654
- ] }) : null
2655
- ] }),
2656
- /* @__PURE__ */ jsxs("div", { className: "mx-auto flex w-full max-w-[90rem]", children: [
2657
- /* @__PURE__ */ jsxs("aside", { className: "sticky top-0 hidden h-dvh w-[17rem] shrink-0 flex-col gap-6 overflow-y-auto px-4 py-6 lg:flex", children: [
2658
- /* @__PURE__ */ jsx(Link2, { href: home, className: "px-2", "aria-label": "Home", children: /* @__PURE__ */ jsx(Lockup, { size: 26 }) }),
2659
- switcher,
2660
- /* @__PURE__ */ jsx(SideNav, { groups }),
2661
- /* @__PURE__ */ jsx("div", { className: "mt-auto flex flex-col gap-3", children: footer })
2662
- ] }),
2663
- /* @__PURE__ */ jsxs("div", { className: "flex min-w-0 flex-1 flex-col", children: [
2664
- /* @__PURE__ */ jsx("div", { className: "hidden h-[4.5rem] items-center justify-end gap-3 px-8 lg:flex", children: account }),
2665
- banner ? /* @__PURE__ */ jsx("div", { className: "px-4 pb-2 pt-4 md:px-8 lg:pt-0", children: banner }) : null,
2666
- /* @__PURE__ */ jsx("main", { id: "main-content", className: "flex-1 px-4 pb-16 pt-6 md:px-8 lg:pt-2", children: /* @__PURE__ */ jsx("div", { className: "mx-auto w-full max-w-[72rem]", children }) })
2667
- ] })
2668
- ] })
2669
- ] }) });
2743
+ tabs ? /* @__PURE__ */ jsx(TabBar, { items: tabs }) : null
2744
+ ]
2745
+ }
2746
+ ) });
2670
2747
  }
2671
2748
  function AccountMenu({
2672
2749
  name,
2673
2750
  detail,
2674
- items
2751
+ items,
2752
+ nameFrom = "sm"
2675
2753
  }) {
2676
2754
  const initial = name.trim().charAt(0).toUpperCase() || "\xB7";
2677
2755
  return /* @__PURE__ */ jsxs(DropdownMenu, { children: [
2678
2756
  /* @__PURE__ */ jsxs(
2679
2757
  DropdownMenuTrigger,
2680
2758
  {
2681
- className: "inline-flex h-10 items-center gap-2.5 rounded-full border border-border bg-card pl-1 pr-1 text-[0.9375rem] outline-none transition-colors hover:border-oca-hairline-strong focus-visible:ring-2 focus-visible:ring-ring sm:pr-3.5",
2759
+ className: cn(
2760
+ "inline-flex h-10 items-center gap-2.5 rounded-full border border-border bg-card pl-1 pr-1 text-[0.9375rem] outline-none transition-colors hover:border-oca-hairline-strong focus-visible:ring-2 focus-visible:ring-ring",
2761
+ nameFrom === "lg" ? "lg:pr-3.5" : "sm:pr-3.5"
2762
+ ),
2682
2763
  "aria-label": `Account: ${name}`,
2683
2764
  children: [
2684
2765
  /* @__PURE__ */ jsx("span", { className: "flex size-8 items-center justify-center rounded-full bg-foreground text-[0.8125rem] font-medium text-background", children: initial }),
2685
- /* @__PURE__ */ jsx("span", { className: "max-w-[10rem] truncate max-sm:hidden", children: name })
2766
+ /* @__PURE__ */ jsx("span", { className: cn("max-w-[10rem] truncate", nameFrom === "lg" ? "max-lg:hidden" : "max-sm:hidden"), children: name })
2686
2767
  ]
2687
2768
  }
2688
2769
  ),