@orangecheck/design 0.14.1 → 0.16.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/chrome.d.mts CHANGED
@@ -63,6 +63,7 @@ interface OcAccountMenuSession {
63
63
  roster?: OcAccountSummary[];
64
64
  switchAccount?: (didOc: string) => Promise<void>;
65
65
  addAccountUrl?: (returnTo?: string) => string;
66
+ tabPinned?: boolean;
66
67
  }
67
68
  interface OcAccountMenuProps {
68
69
  current: EcosystemSlug;
package/dist/chrome.d.ts CHANGED
@@ -63,6 +63,7 @@ interface OcAccountMenuSession {
63
63
  roster?: OcAccountSummary[];
64
64
  switchAccount?: (didOc: string) => Promise<void>;
65
65
  addAccountUrl?: (returnTo?: string) => string;
66
+ tabPinned?: boolean;
66
67
  }
67
68
  interface OcAccountMenuProps {
68
69
  current: EcosystemSlug;
package/dist/chrome.js CHANGED
@@ -1017,7 +1017,11 @@ function OcAccountMenu(props) {
1017
1017
  // context (oc-www) can opt in incrementally.
1018
1018
  roster: session.roster,
1019
1019
  switchAccount: session.switchAccount,
1020
- addAccountUrl: session.addAccountUrl
1020
+ addAccountUrl: session.addAccountUrl,
1021
+ // Structural read keeps the auth-client peer floor at
1022
+ // ^2.17.0 — `tabPinned` ships in 2.18.0 and is simply
1023
+ // undefined (no hint) on older providers.
1024
+ tabPinned: session.tabPinned
1021
1025
  }
1022
1026
  }
1023
1027
  );
@@ -1046,7 +1050,8 @@ function OcAccountMenuView({
1046
1050
  setDisplayIdentity,
1047
1051
  roster,
1048
1052
  switchAccount,
1049
- addAccountUrl
1053
+ addAccountUrl,
1054
+ tabPinned
1050
1055
  } = session;
1051
1056
  const [hydrated, setHydrated] = React.useState(false);
1052
1057
  const [open, setOpen] = React.useState(false);
@@ -1116,11 +1121,11 @@ function OcAccountMenuView({
1116
1121
  "aria-haspopup": "menu",
1117
1122
  "aria-expanded": open,
1118
1123
  "aria-label": `Signed in as ${account.didOc}. Open account menu.`,
1119
- className: triggerClassName ?? "border-primary/40 bg-card hover:bg-accent inline-flex h-8 items-center gap-1.5 rounded-md border px-3 font-mono text-[11px] tracking-wide transition-colors",
1124
+ className: triggerClassName ?? "border-primary/40 bg-card hover:bg-accent inline-flex h-8 items-center gap-1.5 rounded-md border px-2 font-mono text-[11px] tracking-wide transition-colors sm:px-3",
1120
1125
  "data-oc-account-menu-trigger": "",
1121
1126
  children: [
1122
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: "bg-primary inline-block size-1.5 rounded-full", "aria-hidden": true }),
1123
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-foreground", children: label }),
1127
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "bg-primary inline-block size-1.5 shrink-0 rounded-full", "aria-hidden": true }),
1128
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-foreground hidden max-w-[16ch] truncate sm:inline", children: label }),
1124
1129
  /* @__PURE__ */ jsxRuntime.jsx(
1125
1130
  "svg",
1126
1131
  {
@@ -1155,7 +1160,19 @@ function OcAccountMenuView({
1155
1160
  /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "border-border border-b p-3", children: [
1156
1161
  /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "text-primary mb-1 font-mono text-[10px] tracking-widest uppercase", children: [
1157
1162
  "\xA7 signed in \xB7 ",
1158
- hostname
1163
+ hostname,
1164
+ tabPinned ? /* @__PURE__ */ jsxRuntime.jsxs(
1165
+ "span",
1166
+ {
1167
+ className: "text-muted-foreground/70 normal-case",
1168
+ "data-oc-account-menu-tab-pin": "",
1169
+ title: "This tab keeps this account even if you switch accounts in another tab",
1170
+ children: [
1171
+ " ",
1172
+ "\xB7 this tab"
1173
+ ]
1174
+ }
1175
+ ) : null
1159
1176
  ] }),
1160
1177
  /* @__PURE__ */ jsxRuntime.jsx(CopyableDid, { did: account.didOc }),
1161
1178
  displayName ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "text-muted-foreground/80 mt-1 font-mono text-[10px] tracking-wide", children: displayName }) : null
@@ -1510,54 +1527,146 @@ function isActive(pathname, link) {
1510
1527
  if (link.href === "/") return pathname === "/";
1511
1528
  return pathname === link.href || pathname.startsWith(link.href + "/");
1512
1529
  }
1530
+ function ExternalGlyph() {
1531
+ return /* @__PURE__ */ jsxRuntime.jsx("span", { "aria-hidden": true, className: "text-muted-foreground/60 ml-1 text-[9px]", children: "\u2197" });
1532
+ }
1513
1533
  function OcPrimaryNav({
1514
1534
  activePath,
1515
1535
  links,
1516
1536
  className
1517
1537
  }) {
1518
- return /* @__PURE__ */ jsxRuntime.jsx(
1519
- "nav",
1538
+ const [open, setOpen] = React.useState(false);
1539
+ const ref = React.useRef(null);
1540
+ const menuId = React.useId();
1541
+ React.useEffect(() => {
1542
+ setOpen(false);
1543
+ }, [activePath]);
1544
+ React.useEffect(() => {
1545
+ if (!open) return;
1546
+ const onClick = (e) => {
1547
+ if (ref.current && !ref.current.contains(e.target)) setOpen(false);
1548
+ };
1549
+ const onKey = (e) => {
1550
+ if (e.key === "Escape") setOpen(false);
1551
+ };
1552
+ document.addEventListener("mousedown", onClick);
1553
+ document.addEventListener("keydown", onKey);
1554
+ return () => {
1555
+ document.removeEventListener("mousedown", onClick);
1556
+ document.removeEventListener("keydown", onKey);
1557
+ };
1558
+ }, [open]);
1559
+ const inlineClass = (active) => "font-display shrink-0 px-2 py-1 sm:px-3 text-[11px] sm:text-[12px] font-semibold tracking-wider uppercase transition-colors " + (active ? "text-primary" : "text-muted-foreground hover:text-foreground");
1560
+ const rowClass = (active) => "font-display flex items-center gap-2 px-3 py-2 text-[12px] font-semibold tracking-wider uppercase transition-colors " + (active ? "text-primary" : "text-muted-foreground hover:text-foreground hover:bg-accent");
1561
+ function renderInline(link) {
1562
+ const active = isActive(activePath, link);
1563
+ const inner = /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
1564
+ link.label,
1565
+ link.external ? /* @__PURE__ */ jsxRuntime.jsx(ExternalGlyph, {}) : null
1566
+ ] });
1567
+ return link.external ? /* @__PURE__ */ jsxRuntime.jsx(
1568
+ "a",
1569
+ {
1570
+ href: link.href,
1571
+ target: "_blank",
1572
+ rel: "noreferrer",
1573
+ className: inlineClass(false),
1574
+ "data-oc-primary-nav-item": "",
1575
+ children: inner
1576
+ },
1577
+ link.href
1578
+ ) : /* @__PURE__ */ jsxRuntime.jsx(
1579
+ Link5__default.default,
1580
+ {
1581
+ href: link.href,
1582
+ "aria-current": active ? "page" : void 0,
1583
+ className: inlineClass(active),
1584
+ "data-oc-primary-nav-item": active ? "active" : "sibling",
1585
+ children: inner
1586
+ },
1587
+ link.href
1588
+ );
1589
+ }
1590
+ function renderRow(link) {
1591
+ const active = isActive(activePath, link);
1592
+ const inner = /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
1593
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-muted-foreground", "aria-hidden": true, children: "\u2192" }),
1594
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "flex-1", children: link.label }),
1595
+ link.external ? /* @__PURE__ */ jsxRuntime.jsx(ExternalGlyph, {}) : null
1596
+ ] });
1597
+ return link.external ? /* @__PURE__ */ jsxRuntime.jsx(
1598
+ "a",
1599
+ {
1600
+ href: link.href,
1601
+ target: "_blank",
1602
+ rel: "noreferrer",
1603
+ role: "menuitem",
1604
+ onClick: () => setOpen(false),
1605
+ className: rowClass(false),
1606
+ "data-oc-primary-nav-item": "",
1607
+ children: inner
1608
+ },
1609
+ link.href
1610
+ ) : /* @__PURE__ */ jsxRuntime.jsx(
1611
+ Link5__default.default,
1612
+ {
1613
+ href: link.href,
1614
+ role: "menuitem",
1615
+ "aria-current": active ? "page" : void 0,
1616
+ onClick: () => setOpen(false),
1617
+ className: rowClass(active),
1618
+ "data-oc-primary-nav-item": active ? "active" : "sibling",
1619
+ children: inner
1620
+ },
1621
+ link.href
1622
+ );
1623
+ }
1624
+ return /* @__PURE__ */ jsxRuntime.jsxs(
1625
+ "div",
1520
1626
  {
1521
- "aria-label": "primary",
1522
- className: "flex min-w-0 items-center justify-start overflow-x-auto gap-0.5 sm:gap-1 whitespace-nowrap [scrollbar-width:none] [&::-webkit-scrollbar]:hidden " + (className ?? ""),
1627
+ ref,
1628
+ className: "relative flex items-center justify-center " + (className ?? ""),
1523
1629
  "data-oc-primary-nav": "",
1524
- children: links.map((link) => {
1525
- const active = isActive(activePath, link);
1526
- const className2 = "font-display shrink-0 px-2 py-1 sm:px-3 text-[11px] sm:text-[12px] font-semibold tracking-wider uppercase transition-colors " + (active ? "text-primary" : "text-muted-foreground hover:text-foreground");
1527
- const content = /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
1528
- link.label,
1529
- link.external ? /* @__PURE__ */ jsxRuntime.jsx(
1530
- "span",
1630
+ children: [
1631
+ /* @__PURE__ */ jsxRuntime.jsx(
1632
+ "nav",
1633
+ {
1634
+ "aria-label": "primary",
1635
+ className: "hidden items-center gap-0.5 sm:gap-1 md:flex",
1636
+ children: links.map(renderInline)
1637
+ }
1638
+ ),
1639
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "md:hidden", children: [
1640
+ /* @__PURE__ */ jsxRuntime.jsx(
1641
+ "button",
1531
1642
  {
1532
- "aria-hidden": true,
1533
- className: "text-muted-foreground/60 ml-1 text-[9px]",
1534
- children: "\u2197"
1643
+ type: "button",
1644
+ onClick: () => setOpen((v) => !v),
1645
+ "aria-haspopup": "menu",
1646
+ "aria-expanded": open,
1647
+ "aria-controls": menuId,
1648
+ "aria-label": "site navigation",
1649
+ className: "border-input bg-background hover:bg-accent text-muted-foreground inline-flex size-8 items-center justify-center rounded-md border transition-colors",
1650
+ "data-oc-primary-nav-toggle": "",
1651
+ children: open ? /* @__PURE__ */ jsxRuntime.jsx(lucideReact.X, { className: "size-4", "aria-hidden": true }) : /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Menu, { className: "size-4", "aria-hidden": true })
1535
1652
  }
1536
- ) : null
1537
- ] });
1538
- return link.external ? /* @__PURE__ */ jsxRuntime.jsx(
1539
- "a",
1540
- {
1541
- href: link.href,
1542
- target: "_blank",
1543
- rel: "noreferrer",
1544
- className: className2,
1545
- "data-oc-primary-nav-item": "",
1546
- children: content
1547
- },
1548
- link.href
1549
- ) : /* @__PURE__ */ jsxRuntime.jsx(
1550
- Link5__default.default,
1551
- {
1552
- href: link.href,
1553
- "aria-current": active ? "page" : void 0,
1554
- className: className2,
1555
- "data-oc-primary-nav-item": active ? "active" : "sibling",
1556
- children: content
1557
- },
1558
- link.href
1559
- );
1560
- })
1653
+ ),
1654
+ open && /* @__PURE__ */ jsxRuntime.jsxs(
1655
+ "div",
1656
+ {
1657
+ id: menuId,
1658
+ role: "menu",
1659
+ "aria-label": "primary",
1660
+ className: "border-border bg-popover text-popover-foreground absolute top-[calc(100%+8px)] left-1/2 z-50 w-[min(15rem,calc(100vw-1rem))] -translate-x-1/2 border p-1 shadow-xl",
1661
+ "data-oc-primary-nav-popover": "",
1662
+ children: [
1663
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "text-muted-foreground/60 px-3 pt-2 pb-1 font-mono text-[10px] tracking-widest uppercase", children: "\xA7 navigate" }),
1664
+ links.map(renderRow)
1665
+ ]
1666
+ }
1667
+ )
1668
+ ] })
1669
+ ]
1561
1670
  }
1562
1671
  );
1563
1672
  }
@@ -1854,13 +1963,19 @@ function LayoutSubHeader({
1854
1963
  noHeartbeat = false,
1855
1964
  className
1856
1965
  }) {
1857
- return /* @__PURE__ */ jsxRuntime.jsx("div", { className: cn("border-b", className), children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "container flex flex-wrap items-center justify-between gap-x-6 gap-y-1 py-2 font-mono text-[11px]", children: [
1858
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-3", children: [
1859
- !noHeartbeat && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "bg-primary inline-block h-1.5 w-1.5 animate-pulse rounded-full" }),
1860
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-muted-foreground tracking-widest uppercase", children: status }),
1861
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-foreground", children: product })
1966
+ return /* @__PURE__ */ jsxRuntime.jsx("div", { className: cn("oc-substrip border-b", className), children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "container flex items-center justify-between gap-x-6 py-2 font-mono text-[11px]", children: [
1967
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex min-w-0 items-center gap-2.5", children: [
1968
+ !noHeartbeat && /* @__PURE__ */ jsxRuntime.jsx(
1969
+ "span",
1970
+ {
1971
+ className: "bg-primary inline-block size-1.5 shrink-0 animate-pulse rounded-full ring-2 ring-[color-mix(in_oklch,var(--primary),transparent_78%)]",
1972
+ "aria-hidden": true
1973
+ }
1974
+ ),
1975
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-muted-foreground hidden tracking-widest whitespace-nowrap uppercase sm:inline", children: status }),
1976
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-foreground truncate", children: product })
1862
1977
  ] }),
1863
- tags.length > 0 && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "text-muted-foreground flex flex-wrap items-center gap-x-4 gap-y-1 tracking-widest uppercase", children: tags.map((tag, i) => /* @__PURE__ */ jsxRuntime.jsx("span", { className: tag.hideBelow ? HIDE[tag.hideBelow] : void 0, children: tag.label }, i)) })
1978
+ tags.length > 0 && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "text-muted-foreground/55 hidden shrink-0 items-center gap-x-3 tracking-wider whitespace-nowrap uppercase sm:flex", children: tags.map((tag, i) => /* @__PURE__ */ jsxRuntime.jsx("span", { className: tag.hideBelow ? HIDE[tag.hideBelow] : void 0, children: tag.label }, i)) })
1864
1979
  ] }) });
1865
1980
  }
1866
1981
  function OcAppBar({