gridsmith-ui 0.6.4 → 0.6.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -122,6 +122,12 @@ Wrap your app in `<IconProvider>` to select a pack:
122
122
  </IconProvider>
123
123
  ```
124
124
 
125
+ ## Troubleshooting
126
+
127
+ - **Import errors after installing a package while `vite` is running** — restart with `npm run dev -- --force` (or delete `node_modules/.vite`); Vite's dependency cache otherwise serves the pre-install module graph.
128
+ - **Components render unstyled** — add `@source "../node_modules/gridsmith-ui/dist/*.js"` to your CSS entry point *after* every `@import`. Tailwind v4 needs it to scan the compiled components, and rejects an `@import` that follows it.
129
+ - **`IconProvider` is not exported** — upgrade to a current `gridsmith-ui`; the provider ships from the `gridsmith-ui/icons` entry point.
130
+
125
131
  ## Peer Dependencies
126
132
 
127
133
  | Package | Required |
package/dist/index.d.ts CHANGED
@@ -873,7 +873,6 @@ interface LinkProps extends AnchorHTMLAttributes<HTMLAnchorElement> {
873
873
  */
874
874
  declare const Link: react.ForwardRefExoticComponent<LinkProps & react.RefAttributes<HTMLAnchorElement>>;
875
875
 
876
- type TabsVariant = "underline" | "pill";
877
876
  type TabsOverflow = "scroll" | "hidden" | "truncate";
878
877
  interface Tab {
879
878
  id: string;
@@ -894,7 +893,6 @@ interface TabsArrayProps {
894
893
  orientation?: "horizontal" | "vertical" | "responsive";
895
894
  /** Below md, tabs either side-scroll (default) or collapse to a Dropdown. "responsive" implies "dropdown". */
896
895
  mobile?: "scroll" | "dropdown";
897
- variant?: TabsVariant;
898
896
  fullWidth?: boolean;
899
897
  overflow?: TabsOverflow;
900
898
  className?: string;
@@ -904,7 +902,6 @@ interface TabsCompoundProps {
904
902
  activeTab: string;
905
903
  onTabChange: (id: string) => void;
906
904
  orientation?: "horizontal" | "vertical";
907
- variant?: TabsVariant;
908
905
  fullWidth?: boolean;
909
906
  overflow?: TabsOverflow;
910
907
  className?: string;
@@ -1163,7 +1160,8 @@ interface DockProps {
1163
1160
  }
1164
1161
  declare function Dock({ items, magnification, baseSize, className, }: DockProps): react_jsx_runtime.JSX.Element;
1165
1162
 
1166
- type NavbarType = "default" | "underline" | "minimal";
1163
+ /** `tint` (soft accent fill), `underline`, `minimal`, `pill` (solid accent fill). `default` is the deprecated pre-20.8 name for `tint`. */
1164
+ type NavbarType = "tint" | "underline" | "minimal" | "pill" | "default";
1167
1165
  type NavbarAlign = "left" | "center" | "right";
1168
1166
  type NavbarVariant = "default" | "transparent" | "compact" | "elevated" | "blurred";
1169
1167
  type NavbarSize = "sm" | "md" | "lg";
@@ -1175,7 +1173,7 @@ interface NavbarProps {
1175
1173
  actions?: ReactNode;
1176
1174
  userMenu?: ReactNode;
1177
1175
  variant?: NavbarVariant;
1178
- /** Visual style type: default (ghost-button nav items), underline (tab-style with bottom indicator), minimal (transparent, borderless, text-only) */
1176
+ /** Visual style type: tint (ghost-button nav items with a soft accent fill), underline (tab-style with bottom indicator), minimal (transparent, borderless, text-only), pill (solid accent fill with on-primary text). This is a theme decision (navigation.headerType) — NavItem reads it from context. */
1179
1177
  type?: NavbarType;
1180
1178
  /** Horizontal alignment of nav links: left (default), center (viewport-centered), right (before actions) */
1181
1179
  align?: NavbarAlign;
@@ -1191,7 +1189,13 @@ interface NavbarProps {
1191
1189
  }
1192
1190
  declare const Navbar: react.ForwardRefExoticComponent<NavbarProps & react.RefAttributes<HTMLElement>>;
1193
1191
 
1194
- type NavItemType = "default" | "underline" | "minimal";
1192
+ /**
1193
+ * Navbar active style. `tint` is the soft accent fill (the pre-20.8 `default`),
1194
+ * `underline` the bottom indicator, `minimal` a text-only change, `pill` a solid
1195
+ * accent fill with on-primary text. `default` is accepted as a deprecated alias
1196
+ * for `tint` for one release.
1197
+ */
1198
+ type NavItemType = "tint" | "underline" | "minimal" | "pill" | "default";
1195
1199
  interface NavItemProps {
1196
1200
  label: string;
1197
1201
  icon?: IconName;
@@ -1219,14 +1223,15 @@ interface NavMenuProps {
1219
1223
  items: NavMenuItem[];
1220
1224
  /** Whether any child route is currently active (highlights the trigger) */
1221
1225
  active?: boolean;
1222
- /** Matches the parent Navbar type for consistent styling */
1226
+ /** Matches the parent Navbar type for consistent styling (`default` is the deprecated name for `tint`) */
1223
1227
  type?: NavbarType;
1224
1228
  onItemClick?: (item: NavMenuItem) => void;
1225
1229
  className?: string;
1226
1230
  }
1227
1231
  declare function NavMenu({ label, items, active, type, onItemClick, className, }: NavMenuProps): react_jsx_runtime.JSX.Element;
1228
1232
 
1229
- type MobileHeaderMenuType = "default" | "underline" | "minimal";
1233
+ /** Mirrors NavbarType. `default` is the deprecated pre-20.8 name for `tint`. */
1234
+ type MobileHeaderMenuType = "tint" | "underline" | "minimal" | "pill" | "default";
1230
1235
  interface MobileHeaderMenuItemData {
1231
1236
  label: string;
1232
1237
  icon?: IconName;
package/dist/index.js CHANGED
@@ -6846,7 +6846,9 @@ function TreeNodeRow({
6846
6846
  className: cn(
6847
6847
  "flex items-center gap-ds-2 py-ds-1.5 px-ds-2 rounded-[var(--ds-radius-md)] cursor-pointer transition-colors",
6848
6848
  "focus-visible:outline-none focus-visible:shadow-[var(--ds-shadow-focus)]",
6849
- isSelected ? "bg-[var(--ds-tab-active-bg)] text-[var(--ds-accent-primary)] font-medium border-l-2 border-[var(--ds-accent-primary)]" : "text-[var(--ds-text-primary)] hover:bg-[var(--ds-tab-hover-bg)] hover:text-[var(--ds-text-primary)]",
6849
+ // Active style comes from the theme's --ds-tree-* tokens (rail / tint;
6850
+ // pill degrades to tint). The rail is drawn on the selected row only.
6851
+ isSelected ? "bg-[var(--ds-tree-active-bg)] text-[var(--ds-tree-active-text)] font-medium border-l-[length:var(--ds-tree-active-rail)] border-[var(--ds-accent-primary)]" : "text-[var(--ds-text-primary)] hover:bg-[var(--ds-tab-hover-bg)] hover:text-[var(--ds-text-primary)]",
6850
6852
  node.disabled && "opacity-disabled pointer-events-none"
6851
6853
  ),
6852
6854
  style: { paddingLeft: `calc(var(--ds-space-5) * ${depth} + var(--ds-space-2))` },
@@ -6873,7 +6875,7 @@ function TreeNodeRow({
6873
6875
  {
6874
6876
  name: "chevron-right",
6875
6877
  size: 14,
6876
- className: cn("text-[var(--ds-text-muted)] transition-transform", isExpanded && "rotate-90")
6878
+ className: cn(isSelected ? "text-[var(--ds-tree-active-muted)]" : "text-[var(--ds-text-muted)]", "transition-transform", isExpanded && "rotate-90")
6877
6879
  }
6878
6880
  )
6879
6881
  }
@@ -6888,7 +6890,7 @@ function TreeNodeRow({
6888
6890
  }
6889
6891
  }
6890
6892
  ),
6891
- node.icon && /* @__PURE__ */ jsx(Icon, { name: node.icon, size: 16, className: cn("shrink-0", isSelected ? "text-[var(--ds-accent-primary)]" : "text-[var(--ds-text-muted)]") }),
6893
+ node.icon && /* @__PURE__ */ jsx(Icon, { name: node.icon, size: 16, className: cn("shrink-0", isSelected ? "text-[var(--ds-tree-active-text)]" : "text-[var(--ds-text-muted)]") }),
6892
6894
  /* @__PURE__ */ jsx(TruncLabel2, { children: node.label })
6893
6895
  ]
6894
6896
  }
@@ -7376,6 +7378,19 @@ function useTabsCtx() {
7376
7378
  if (!ctx) throw new Error("Tabs.List / Tabs.Trigger / Tabs.Content must be used inside <Tabs>");
7377
7379
  return ctx;
7378
7380
  }
7381
+ function trackClasses(orientation) {
7382
+ if (orientation === "vertical") {
7383
+ return cn(
7384
+ "flex flex-col gap-ds-0.5 min-w-[var(--ds-tab-rail-width)]",
7385
+ "border-r-[length:var(--ds-nav-v-track-border)] border-[var(--ds-border-default)]",
7386
+ "pr-[var(--ds-nav-v-track-padding)]"
7387
+ );
7388
+ }
7389
+ return cn(
7390
+ "flex gap-[var(--ds-nav-h-track-gap)]",
7391
+ "border-b-[length:var(--ds-nav-h-track-border)] border-[var(--ds-border-default)]"
7392
+ );
7393
+ }
7379
7394
  function getTabsFromDOM(el) {
7380
7395
  const tablist = el.closest('[role="tablist"]');
7381
7396
  if (!tablist) return [];
@@ -7423,7 +7438,6 @@ function TabButton({
7423
7438
  icon,
7424
7439
  disabled,
7425
7440
  orientation,
7426
- variant,
7427
7441
  activeTab,
7428
7442
  onTabChange,
7429
7443
  fullWidth,
@@ -7436,10 +7450,11 @@ function TabButton({
7436
7450
  const isActive = activeTab === id;
7437
7451
  const tabId = `ds-tab-${id}`;
7438
7452
  const panelId = hasPanel === false ? void 0 : `ds-tabpanel-${id}`;
7453
+ const badgeBg = orientation === "vertical" ? "bg-[var(--ds-nav-v-badge-bg)]" : "bg-[var(--ds-nav-h-badge-bg)]";
7439
7454
  const countBadge = count !== void 0 ? /* @__PURE__ */ jsx("span", { className: cn(
7440
7455
  orientation === "vertical" ? "ml-ds-2" : "",
7441
7456
  "px-ds-1.5 py-ds-0.5 text-xs rounded-[var(--ds-radius-sm)]",
7442
- variant === "pill" && isActive ? "bg-[var(--ds-bg-canvas)]/20 text-[var(--ds-text-on-primary)]" : isActive ? "bg-[var(--ds-accent-primary)] text-[var(--ds-text-on-primary)]" : "bg-[var(--ds-bg-emphasis)] text-[var(--ds-text-muted)]"
7457
+ isActive ? cn(badgeBg, "text-[var(--ds-text-on-primary)]") : "bg-[var(--ds-bg-emphasis)] text-[var(--ds-text-muted)]"
7443
7458
  ), children: count }) : null;
7444
7459
  if (orientation === "vertical") {
7445
7460
  const btn2 = /* @__PURE__ */ jsxs(
@@ -7456,10 +7471,12 @@ function TabButton({
7456
7471
  className: cn(
7457
7472
  "flex items-center justify-between px-ds-3 py-ds-2 text-sm font-medium text-left",
7458
7473
  disabled ? "cursor-not-allowed opacity-disabled" : "cursor-pointer",
7459
- "rounded-[var(--ds-radius-sm)]",
7474
+ "rounded-[var(--ds-nav-v-item-radius)]",
7460
7475
  "transition-colors duration-[var(--ds-transition-speed)]",
7461
7476
  "focus-visible:outline-none focus-visible:shadow-[var(--ds-shadow-focus)]",
7462
- variant === "pill" ? isActive ? "bg-[var(--ds-accent-primary)] text-[var(--ds-text-on-primary)]" : "text-[var(--ds-text-secondary)] hover:text-[var(--ds-text-primary)] hover:bg-[var(--ds-tab-hover-bg)]" : isActive ? "text-[var(--ds-accent-primary)] bg-[var(--ds-tab-active-bg)] border-l-[length:var(--ds-border-width-thicker)] border-[var(--ds-accent-primary)]" : "text-[var(--ds-text-secondary)] hover:text-[var(--ds-text-primary)] hover:bg-[var(--ds-tab-hover-bg)]",
7477
+ // The rail is drawn on the active item only (today's behaviour; a
7478
+ // transparent placeholder on every item is a future layout tweak).
7479
+ isActive ? "bg-[var(--ds-nav-v-active-bg)] text-[var(--ds-nav-v-active-text)] border-l-[length:var(--ds-nav-v-active-rail)] border-[var(--ds-accent-primary)]" : "text-[var(--ds-text-secondary)] hover:text-[var(--ds-text-primary)] hover:bg-[var(--ds-tab-hover-bg)]",
7463
7480
  className
7464
7481
  ),
7465
7482
  children: [
@@ -7492,13 +7509,11 @@ function TabButton({
7492
7509
  "focus-visible:outline-none focus-visible:shadow-[var(--ds-shadow-focus)]",
7493
7510
  fullWidth && "flex-1",
7494
7511
  truncate && "flex-1 min-w-0 flex items-center",
7495
- variant === "pill" ? cn(
7496
- "rounded-[var(--ds-radius-md)]",
7497
- isActive ? "bg-[var(--ds-accent-primary)] text-[var(--ds-text-on-primary)]" : "text-[var(--ds-text-secondary)] hover:text-[var(--ds-text-primary)] hover:bg-[var(--ds-tab-hover-bg)]"
7498
- ) : isActive ? "text-[var(--ds-text-primary)] border-b-[length:var(--ds-border-width)] border-[var(--ds-accent-primary)]" : "text-[var(--ds-text-muted)] hover:text-[var(--ds-text-primary)]",
7512
+ "rounded-[var(--ds-nav-h-item-radius)]",
7513
+ isActive ? "bg-[var(--ds-nav-h-active-bg)] text-[var(--ds-nav-h-active-text)] border-[var(--ds-accent-primary)]" : "text-[var(--ds-nav-h-inactive-text)] hover:text-[var(--ds-text-primary)] hover:bg-[var(--ds-nav-h-hover-bg)]",
7499
7514
  className
7500
7515
  ),
7501
- style: variant === "underline" && orientation === "horizontal" && isActive ? { borderBottomWidth: "calc(var(--ds-border-width) * 3)", marginBottom: "calc(var(--ds-border-width) * -1)" } : void 0,
7516
+ style: isActive ? { borderBottomWidth: "var(--ds-nav-h-indicator)", marginBottom: "calc(var(--ds-nav-h-track-border) * -1)" } : void 0,
7502
7517
  children: truncate ? /* @__PURE__ */ jsxs(Fragment, { children: [
7503
7518
  icon && /* @__PURE__ */ jsx(Icon, { name: icon, size: 16, className: "shrink-0" }),
7504
7519
  /* @__PURE__ */ jsx("span", { ref: truncRef, className: "truncate min-w-0 flex-1", children: label }),
@@ -7514,18 +7529,14 @@ function TabButton({
7514
7529
  return btn;
7515
7530
  }
7516
7531
  function TabsList({ children, className }) {
7517
- const { orientation, variant, fullWidth, overflow } = useTabsCtx();
7532
+ const { orientation, fullWidth, overflow } = useTabsCtx();
7518
7533
  if (orientation === "vertical") {
7519
7534
  return /* @__PURE__ */ jsx(
7520
7535
  "div",
7521
7536
  {
7522
7537
  role: "tablist",
7523
7538
  "aria-orientation": "vertical",
7524
- className: cn(
7525
- "flex flex-col gap-ds-0.5 min-w-[var(--ds-tab-rail-width)]",
7526
- variant === "underline" && "border-r-[length:var(--ds-border-width)] border-[var(--ds-border-default)] pr-ds-1",
7527
- className
7528
- ),
7539
+ className: cn(trackClasses("vertical"), className),
7529
7540
  children
7530
7541
  }
7531
7542
  );
@@ -7535,10 +7546,9 @@ function TabsList({ children, className }) {
7535
7546
  {
7536
7547
  role: "tablist",
7537
7548
  className: cn(
7538
- "flex gap-0 max-w-full",
7549
+ trackClasses("horizontal"),
7550
+ "max-w-full",
7539
7551
  overflow === "hidden" ? "overflow-hidden" : overflow === "truncate" ? "overflow-hidden" : "overflow-x-auto overflow-y-hidden",
7540
- variant === "underline" && "border-b-[length:var(--ds-border-width)] border-[var(--ds-border-default)]",
7541
- variant === "pill" && "gap-ds-1 p-ds-0.5 bg-[var(--ds-bg-muted)] rounded-[var(--ds-radius-lg)]",
7542
7552
  fullWidth && "w-full",
7543
7553
  className
7544
7554
  ),
@@ -7547,7 +7557,7 @@ function TabsList({ children, className }) {
7547
7557
  );
7548
7558
  }
7549
7559
  function TabsTrigger({ value, children, count, icon, disabled, truncate, className }) {
7550
- const { activeTab, onTabChange, orientation, variant, fullWidth, overflow } = useTabsCtx();
7560
+ const { activeTab, onTabChange, orientation, fullWidth, overflow } = useTabsCtx();
7551
7561
  return /* @__PURE__ */ jsx(
7552
7562
  TabButton,
7553
7563
  {
@@ -7558,7 +7568,6 @@ function TabsTrigger({ value, children, count, icon, disabled, truncate, classNa
7558
7568
  disabled,
7559
7569
  truncate: overflow === "truncate" || truncate,
7560
7570
  orientation,
7561
- variant,
7562
7571
  activeTab,
7563
7572
  onTabChange,
7564
7573
  fullWidth,
@@ -7587,7 +7596,6 @@ function TabsRoot(props) {
7587
7596
  activeTab,
7588
7597
  onTabChange,
7589
7598
  orientation = "horizontal",
7590
- variant = "underline",
7591
7599
  fullWidth = false,
7592
7600
  overflow = "scroll",
7593
7601
  className
@@ -7614,11 +7622,7 @@ function TabsRoot(props) {
7614
7622
  {
7615
7623
  role: "tablist",
7616
7624
  "aria-orientation": "vertical",
7617
- className: cn(
7618
- "flex flex-col gap-ds-0.5 min-w-[var(--ds-tab-rail-width)]",
7619
- variant === "underline" && "border-r-[length:var(--ds-border-width)] border-[var(--ds-border-default)] pr-ds-1",
7620
- className
7621
- ),
7625
+ className: cn(trackClasses("vertical"), className),
7622
7626
  children: tabs.map((tab, i) => /* @__PURE__ */ jsxs(Fragment$1, { children: [
7623
7627
  tab.group && tab.group !== tabs[i - 1]?.group && /* @__PURE__ */ jsx(
7624
7628
  "span",
@@ -7631,7 +7635,7 @@ function TabsRoot(props) {
7631
7635
  children: tab.group
7632
7636
  }
7633
7637
  ),
7634
- /* @__PURE__ */ jsx(TabButton, { hasPanel: false, ...tab, orientation: effectiveOrientation, variant, activeTab, onTabChange, fullWidth, onKeyDown: (e) => handleTabKeyDown(e, tab.id, () => tabs, effectiveOrientation, onTabChange) })
7638
+ /* @__PURE__ */ jsx(TabButton, { hasPanel: false, ...tab, orientation: effectiveOrientation, activeTab, onTabChange, fullWidth, onKeyDown: (e) => handleTabKeyDown(e, tab.id, () => tabs, effectiveOrientation, onTabChange) })
7635
7639
  ] }, tab.id))
7636
7640
  }
7637
7641
  );
@@ -7642,18 +7646,16 @@ function TabsRoot(props) {
7642
7646
  {
7643
7647
  role: "tablist",
7644
7648
  className: cn(
7645
- "flex gap-0",
7649
+ trackClasses("horizontal"),
7646
7650
  effectiveOverflow === "scroll" ? "overflow-x-auto overflow-y-hidden" : "overflow-hidden",
7647
- variant === "underline" && "border-b-[length:var(--ds-border-width)] border-[var(--ds-border-default)]",
7648
- variant === "pill" && "gap-ds-1 p-ds-0.5 bg-[var(--ds-bg-muted)] rounded-[var(--ds-radius-lg)]",
7649
7651
  fullWidth && "w-full",
7650
7652
  className
7651
7653
  ),
7652
- children: tabs.map((tab) => /* @__PURE__ */ jsx(TabButton, { hasPanel: false, ...tab, orientation: effectiveOrientation, variant, activeTab, onTabChange, fullWidth, onKeyDown: (e) => handleTabKeyDown(e, tab.id, () => tabs, effectiveOrientation, onTabChange) }, tab.id))
7654
+ children: tabs.map((tab) => /* @__PURE__ */ jsx(TabButton, { hasPanel: false, ...tab, orientation: effectiveOrientation, activeTab, onTabChange, fullWidth, onKeyDown: (e) => handleTabKeyDown(e, tab.id, () => tabs, effectiveOrientation, onTabChange) }, tab.id))
7653
7655
  }
7654
7656
  );
7655
7657
  }
7656
- return /* @__PURE__ */ jsx(TabsContext.Provider, { value: { activeTab, onTabChange, orientation: effectiveOrientation, variant, fullWidth, overflow }, children: /* @__PURE__ */ jsx("div", { className, children: props.children }) });
7658
+ return /* @__PURE__ */ jsx(TabsContext.Provider, { value: { activeTab, onTabChange, orientation: effectiveOrientation, fullWidth, overflow }, children: /* @__PURE__ */ jsx("div", { className, children: props.children }) });
7657
7659
  }
7658
7660
  var Tabs = Object.assign(TabsRoot, {
7659
7661
  List: TabsList,
@@ -8567,7 +8569,7 @@ function CompactFlyout({
8567
8569
  },
8568
8570
  className: cn(
8569
8571
  "flex items-center gap-ds-2 px-ds-2 py-ds-1.5 text-xs rounded-[var(--ds-radius-sm)] transition-colors cursor-pointer",
8570
- child.active ? "bg-sidebar-accent-subtle text-[var(--ds-sidebar-accent)] font-medium" : "text-[var(--ds-sidebar-text-secondary)] hover:bg-[var(--ds-sidebar-item-hover)] hover:text-[var(--ds-sidebar-text)]"
8572
+ child.active ? "bg-[var(--ds-sidebar-active-bg)] text-[var(--ds-sidebar-active-accent)] font-medium" : "text-[var(--ds-sidebar-text-secondary)] hover:bg-[var(--ds-sidebar-item-hover)] hover:text-[var(--ds-sidebar-text)]"
8571
8573
  ),
8572
8574
  children: [
8573
8575
  child.icon && /* @__PURE__ */ jsx(Icon, { name: child.icon, size: 14 }),
@@ -8673,7 +8675,10 @@ function SidebarNav({
8673
8675
  "flex items-center gap-ds-2 transition-colors cursor-pointer",
8674
8676
  isRoot ? cn(rootPy, rootText, isMinimal ? "rounded-[var(--ds-radius-full)]" : "rounded-[var(--ds-radius-md)]") : cn(childPy, "text-xs rounded-[var(--ds-radius-sm)]"),
8675
8677
  isRoot ? collapsed ? "justify-center px-0" : "px-ds-3" : "px-ds-2",
8676
- item.active ? isRoot ? isMinimal ? "bg-sidebar-accent-subtle text-[var(--ds-sidebar-text)] font-medium" : "bg-sidebar-accent-subtle text-[var(--ds-sidebar-text)] font-medium border-l-2 border-[var(--ds-sidebar-accent)]" : "bg-sidebar-accent-subtle text-[var(--ds-sidebar-accent)] font-medium" : isRoot ? isMinimal ? "text-[var(--ds-sidebar-text-secondary)] hover:bg-[var(--ds-sidebar-item-hover)] hover:text-[var(--ds-sidebar-text)]" : "text-[var(--ds-sidebar-text-secondary)] hover:bg-[var(--ds-sidebar-item-hover)] hover:text-[var(--ds-sidebar-text)] border-l-2 border-transparent" : "text-[var(--ds-sidebar-text-muted)] hover:bg-[var(--ds-sidebar-item-hover)] hover:text-[var(--ds-sidebar-text)]"
8678
+ // Active style comes from the theme's --ds-sidebar-active-* tokens
8679
+ // (rail / tint / pill). The rail token is 0px for minimal sidebars,
8680
+ // so the transparent placeholder on inactive roots is harmless there.
8681
+ item.active ? isRoot ? "bg-[var(--ds-sidebar-active-bg)] text-[var(--ds-sidebar-active-text)] font-medium border-l-[length:var(--ds-sidebar-active-rail)] border-[var(--ds-sidebar-active-accent)]" : "bg-[var(--ds-sidebar-active-bg)] text-[var(--ds-sidebar-active-accent)] font-medium" : isRoot ? "text-[var(--ds-sidebar-text-secondary)] hover:bg-[var(--ds-sidebar-item-hover)] hover:text-[var(--ds-sidebar-text)] border-l-[length:var(--ds-sidebar-active-rail)] border-transparent" : "text-[var(--ds-sidebar-text-muted)] hover:bg-[var(--ds-sidebar-item-hover)] hover:text-[var(--ds-sidebar-text)]"
8677
8682
  ),
8678
8683
  children: [
8679
8684
  item.icon && /* @__PURE__ */ jsx(
@@ -8681,7 +8686,7 @@ function SidebarNav({
8681
8686
  {
8682
8687
  name: item.icon,
8683
8688
  size: isRoot ? rootIconSize : childIconSize,
8684
- className: cn("shrink-0", item.active && "text-[var(--ds-sidebar-accent)]")
8689
+ className: cn("shrink-0", item.active && "text-[var(--ds-sidebar-active-accent)]")
8685
8690
  }
8686
8691
  ),
8687
8692
  !collapsed && /* @__PURE__ */ jsxs(Fragment, { children: [
@@ -8753,7 +8758,10 @@ function SidebarNav({
8753
8758
  "flex items-center gap-ds-2 w-full text-left transition-colors cursor-pointer",
8754
8759
  isRoot ? cn(rootPy, rootText, isMinimal ? "rounded-[var(--ds-radius-full)]" : "rounded-[var(--ds-radius-md)]") : cn(childPy, "text-xs rounded-[var(--ds-radius-sm)]"),
8755
8760
  isRoot ? collapsed ? "justify-center px-0" : "px-ds-3" : "px-ds-2",
8756
- item.active || childActive ? isRoot ? isMinimal ? "text-[var(--ds-sidebar-text)] font-medium" : "text-[var(--ds-sidebar-text)] font-medium border-l-2 border-transparent" : "text-[var(--ds-sidebar-text)] font-medium" : isRoot ? isMinimal ? "text-[var(--ds-sidebar-text-secondary)] hover:bg-[var(--ds-sidebar-item-hover)] hover:text-[var(--ds-sidebar-text)]" : "text-[var(--ds-sidebar-text-secondary)] hover:bg-[var(--ds-sidebar-item-hover)] hover:text-[var(--ds-sidebar-text)] border-l-2 border-transparent" : "text-[var(--ds-sidebar-text-muted)] hover:bg-[var(--ds-sidebar-item-hover)] hover:text-[var(--ds-sidebar-text)]"
8761
+ // This row has no fill, so its label, icon and chevron keep the plain
8762
+ // sidebar tokens: --ds-sidebar-active-accent is on-primary white under
8763
+ // `pill` and would vanish here. Only filled elements read the active set.
8764
+ item.active || childActive ? isRoot ? "text-[var(--ds-sidebar-text)] font-medium border-l-[length:var(--ds-sidebar-active-rail)] border-transparent" : "text-[var(--ds-sidebar-text)] font-medium" : isRoot ? "text-[var(--ds-sidebar-text-secondary)] hover:bg-[var(--ds-sidebar-item-hover)] hover:text-[var(--ds-sidebar-text)] border-l-[length:var(--ds-sidebar-active-rail)] border-transparent" : "text-[var(--ds-sidebar-text-muted)] hover:bg-[var(--ds-sidebar-item-hover)] hover:text-[var(--ds-sidebar-text)]"
8757
8765
  ),
8758
8766
  children: [
8759
8767
  item.icon && /* @__PURE__ */ jsx(
@@ -8944,7 +8952,9 @@ function CompactNavItem({
8944
8952
  "aria-expanded": hasChildren ? mobile ? expanded : isOpen : void 0,
8945
8953
  className: cn(
8946
8954
  "relative flex flex-col items-center justify-center gap-[3px] w-full py-ds-3 px-ds-1 rounded-[var(--ds-radius-md)] transition-colors cursor-pointer",
8947
- item.active || childActive ? "bg-sidebar-accent-subtle text-[var(--ds-sidebar-accent)]" : "text-[var(--ds-sidebar-text-secondary)] hover:bg-[var(--ds-sidebar-item-hover)] hover:text-[var(--ds-sidebar-text)]"
8955
+ // Compact tiles have no edge to stroke: they read the fill and text
8956
+ // tokens only, never --ds-sidebar-active-rail.
8957
+ item.active || childActive ? "bg-[var(--ds-sidebar-active-bg)] text-[var(--ds-sidebar-active-accent)]" : "text-[var(--ds-sidebar-text-secondary)] hover:bg-[var(--ds-sidebar-item-hover)] hover:text-[var(--ds-sidebar-text)]"
8948
8958
  ),
8949
8959
  children: [
8950
8960
  item.icon && /* @__PURE__ */ jsx(
@@ -8952,7 +8962,7 @@ function CompactNavItem({
8952
8962
  {
8953
8963
  name: item.icon,
8954
8964
  size: 20,
8955
- className: cn((item.active || childActive) && "text-[var(--ds-sidebar-accent)]")
8965
+ className: cn((item.active || childActive) && "text-[var(--ds-sidebar-active-accent)]")
8956
8966
  }
8957
8967
  ),
8958
8968
  /* @__PURE__ */ jsx(TruncLabel3, { className: "text-[clamp(9px,var(--ds-font-size-2xs),12px)] leading-tight max-w-full", side: "right", container: portalContainer ?? void 0, children: item.label }),
@@ -8963,7 +8973,7 @@ function CompactNavItem({
8963
8973
  size: 10,
8964
8974
  className: cn(
8965
8975
  "absolute right-1 top-1/2 -translate-y-1/2 transition-transform",
8966
- item.active || childActive ? "text-[var(--ds-sidebar-accent)]" : "text-[var(--ds-sidebar-text-muted)]",
8976
+ item.active || childActive ? "text-[var(--ds-sidebar-active-accent)]" : "text-[var(--ds-sidebar-text-muted)]",
8967
8977
  expanded && "rotate-180"
8968
8978
  )
8969
8979
  }
@@ -8990,7 +9000,7 @@ function CompactNavItem({
8990
9000
  onClick: () => onItemClick?.(child, ci),
8991
9001
  className: cn(
8992
9002
  "flex items-center gap-ds-2 px-ds-3 py-ds-1.5 text-[length:var(--ds-font-size-xs)] rounded-[var(--ds-radius-sm)] transition-colors cursor-pointer w-full",
8993
- child.active ? "bg-sidebar-accent-subtle text-[var(--ds-sidebar-accent)] font-medium" : "text-[var(--ds-sidebar-text-muted)] hover:bg-[var(--ds-sidebar-item-hover)] hover:text-[var(--ds-sidebar-text)]"
9003
+ child.active ? "bg-[var(--ds-sidebar-active-bg)] text-[var(--ds-sidebar-active-accent)] font-medium" : "text-[var(--ds-sidebar-text-muted)] hover:bg-[var(--ds-sidebar-item-hover)] hover:text-[var(--ds-sidebar-text)]"
8994
9004
  ),
8995
9005
  children: [
8996
9006
  child.icon && /* @__PURE__ */ jsx(Icon, { name: child.icon, size: 14, className: "shrink-0" }),
@@ -10385,10 +10395,13 @@ var AppShell = forwardRef(function AppShell2({
10385
10395
  }
10386
10396
  );
10387
10397
  });
10388
- var NavbarTypeContext = createContext("default");
10398
+ function resolveNavItemType(type) {
10399
+ return type === "default" ? "tint" : type;
10400
+ }
10401
+ var NavbarTypeContext = createContext("tint");
10389
10402
  var NavItem = forwardRef(function NavItem2({ label, icon, active = false, href, onClick, type: typeProp, className, children }, ref) {
10390
10403
  const contextType = useContext(NavbarTypeContext);
10391
- const type = typeProp ?? contextType;
10404
+ const type = resolveNavItemType(typeProp ?? contextType);
10392
10405
  const baseClasses = cn(
10393
10406
  "inline-flex items-center gap-ds-2 cursor-pointer select-none",
10394
10407
  "transition-colors duration-[var(--ds-transition-speed)] ease-[var(--ds-transition-ease)]",
@@ -10420,6 +10433,11 @@ var NavItem = forwardRef(function NavItem2({ label, icon, active = false, href,
10420
10433
  });
10421
10434
  function getTypeClasses(type, active) {
10422
10435
  switch (type) {
10436
+ case "pill":
10437
+ return cn(
10438
+ "px-ds-2 py-ds-1 rounded-[var(--ds-radius-sm)]",
10439
+ active ? "bg-[var(--ds-accent-primary)] text-[var(--ds-text-on-primary)] font-[var(--ds-weight-heading)]" : "text-[var(--ds-text-secondary)] hover:text-[var(--ds-text-primary)] hover:bg-[var(--ds-bg-muted)]"
10440
+ );
10423
10441
  case "underline":
10424
10442
  return cn(
10425
10443
  "px-ds-2 py-ds-2 relative",
@@ -10430,7 +10448,7 @@ function getTypeClasses(type, active) {
10430
10448
  "px-ds-2 py-ds-1",
10431
10449
  active ? "text-[var(--ds-accent-primary)] font-medium" : "text-[var(--ds-text-muted)] hover:text-[var(--ds-text-secondary)]"
10432
10450
  );
10433
- default:
10451
+ case "tint":
10434
10452
  return cn(
10435
10453
  "px-ds-2 py-ds-1 rounded-[var(--ds-radius-sm)]",
10436
10454
  active ? "bg-[var(--ds-accent-subtle)] text-[var(--ds-accent-primary)] font-[var(--ds-weight-heading)]" : "text-[var(--ds-text-secondary)] hover:text-[var(--ds-text-primary)] hover:bg-[var(--ds-bg-muted)]"
@@ -10464,7 +10482,7 @@ var Navbar = forwardRef(function Navbar2({
10464
10482
  actions,
10465
10483
  userMenu,
10466
10484
  variant = "default",
10467
- type = "default",
10485
+ type: typeProp = "tint",
10468
10486
  align = "left",
10469
10487
  size,
10470
10488
  position = "flush",
@@ -10478,6 +10496,7 @@ var Navbar = forwardRef(function Navbar2({
10478
10496
  const showHamburger = appShell?.isMobile && appShell.hasMobileMenu && !(isSmallPhone && appShell.hasMobileNav) || !!onMenuClick;
10479
10497
  const handleHamburger = () => onMenuClick ? onMenuClick() : appShell?.setSidebarOpen(!appShell.sidebarOpen);
10480
10498
  const hideNavLinks = appShell?.isMobile && (appShell.hasMobileMenu || appShell.hasMobileNav);
10499
+ const type = resolveNavItemType(typeProp);
10481
10500
  const isMinimal = type === "minimal";
10482
10501
  const isFloating = position === "floating";
10483
10502
  const resolvedSize = size ?? (variant === "compact" ? "sm" : "md");
@@ -10584,7 +10603,7 @@ function NavMenu({
10584
10603
  label,
10585
10604
  items,
10586
10605
  active = false,
10587
- type = "default",
10606
+ type = "tint",
10588
10607
  onItemClick,
10589
10608
  className
10590
10609
  }) {
@@ -10624,6 +10643,7 @@ function NavMenu({
10624
10643
  );
10625
10644
  const isUnderline = type === "underline";
10626
10645
  const isMinimal = type === "minimal";
10646
+ const isPill = type === "pill";
10627
10647
  const triggerClasses = cn(
10628
10648
  "inline-flex items-center gap-ds-1 cursor-pointer transition-colors whitespace-nowrap",
10629
10649
  "focus-visible:outline-none focus-visible:shadow-[var(--ds-shadow-focus)]",
@@ -10633,9 +10653,14 @@ function NavMenu({
10633
10653
  ) : isMinimal ? cn(
10634
10654
  "px-ds-2 py-ds-1 text-sm",
10635
10655
  hasActiveChild ? "text-[var(--ds-text-primary)] font-medium" : "text-[var(--ds-text-secondary)] hover:text-[var(--ds-text-primary)]"
10656
+ ) : isPill ? cn(
10657
+ "px-ds-3 py-ds-1.5 text-sm rounded-[var(--ds-radius-md)]",
10658
+ hasActiveChild ? "bg-[var(--ds-accent-primary)] text-[var(--ds-text-on-primary)] font-medium" : "text-[var(--ds-text-secondary)] hover:bg-[var(--ds-bg-muted)] hover:text-[var(--ds-text-primary)]"
10636
10659
  ) : cn(
10660
+ // tint (and the deprecated `default` alias) — the same soft accent fill
10661
+ // NavItem uses, so a menu trigger and a link read as one row (decision 30).
10637
10662
  "px-ds-3 py-ds-1.5 text-sm rounded-[var(--ds-radius-md)]",
10638
- hasActiveChild ? "bg-[var(--ds-bg-muted)] text-[var(--ds-text-primary)] font-medium" : "text-[var(--ds-text-secondary)] hover:bg-[var(--ds-bg-muted)] hover:text-[var(--ds-text-primary)]"
10663
+ hasActiveChild ? "bg-[var(--ds-accent-subtle)] text-[var(--ds-accent-primary)] font-medium" : "text-[var(--ds-text-secondary)] hover:bg-[var(--ds-bg-muted)] hover:text-[var(--ds-text-primary)]"
10639
10664
  ),
10640
10665
  className
10641
10666
  );
@@ -10722,7 +10747,9 @@ function NavMenuItemRow({
10722
10747
  },
10723
10748
  className: cn(
10724
10749
  "flex items-center gap-ds-2 mx-ds-1 px-ds-2 py-ds-1.5 rounded-[var(--ds-radius-sm)] transition-colors cursor-pointer",
10725
- item.active ? "bg-[var(--ds-bg-muted)] text-[var(--ds-text-primary)] font-medium" : "text-[var(--ds-text-secondary)] hover:bg-[var(--ds-bg-muted)] hover:text-[var(--ds-text-primary)]"
10750
+ // The active row takes the accent tint like an active NavItem; it marks
10751
+ // the current page, not a hover.
10752
+ item.active ? "bg-[var(--ds-accent-subtle)] text-[var(--ds-accent-primary)] font-medium" : "text-[var(--ds-text-secondary)] hover:bg-[var(--ds-bg-muted)] hover:text-[var(--ds-text-primary)]"
10726
10753
  ),
10727
10754
  children: [
10728
10755
  item.icon && /* @__PURE__ */ jsx(
@@ -10765,7 +10792,7 @@ function NavMenuGroup({
10765
10792
  ))
10766
10793
  ] });
10767
10794
  }
10768
- function MobileHeaderMenu({ items, type = "default", onItemClick, className }) {
10795
+ function MobileHeaderMenu({ items, type = "tint", onItemClick, className }) {
10769
10796
  return /* @__PURE__ */ jsx("nav", { className: cn("flex flex-col", className), style: { padding: "var(--ds-space-4)" }, children: /* @__PURE__ */ jsx("div", { className: "flex flex-col", style: { gap: type === "underline" ? 0 : "var(--ds-space-1)" }, children: items.map((item, i) => /* @__PURE__ */ jsx(
10770
10797
  MobileMenuItem,
10771
10798
  {
@@ -10822,6 +10849,23 @@ function MobileMenuItem({
10822
10849
  }
10823
10850
  );
10824
10851
  }
10852
+ if (type === "pill") {
10853
+ return /* @__PURE__ */ jsxs(
10854
+ "button",
10855
+ {
10856
+ onClick,
10857
+ className: cn(
10858
+ "flex items-center gap-ds-3 px-ds-3 py-ds-2.5 text-sm rounded-[var(--ds-radius-md)] cursor-pointer w-full text-left",
10859
+ "transition-colors duration-[var(--ds-transition-speed)]",
10860
+ item.active ? "bg-[var(--ds-accent-primary)] text-[var(--ds-text-on-primary)] font-[var(--ds-weight-heading)]" : "text-[var(--ds-text-secondary)] hover:text-[var(--ds-text-primary)] hover:bg-[var(--ds-bg-muted)]"
10861
+ ),
10862
+ children: [
10863
+ item.icon && /* @__PURE__ */ jsx(Icon, { name: item.icon, size: 18, className: "shrink-0" }),
10864
+ /* @__PURE__ */ jsx("span", { children: item.label })
10865
+ ]
10866
+ }
10867
+ );
10868
+ }
10825
10869
  return /* @__PURE__ */ jsxs(
10826
10870
  "button",
10827
10871
  {