import clsx from "clsx"; import type { CSSProperties, ReactNode, Ref } from "react"; import type { LucideIcon } from "lucide-react"; import { Pressable } from "./Pressable"; import { SURFACE } from "./surfaces"; import Tooltip from "./Tooltip"; // B7 (docs/DESIGN.md): the app's primary navigation rail. Slim — 3.75rem wide whether or not the // labels are on (they add height, never width) — with "you are here" as a soft accent tint plus a 3px // edge bar, calmer than a solid fill beside the page's own solid accents. Labels under the icons are // a per-user setting (off by default); each module has a SHORT rail label that fits, and the full name // is the tooltip. /** The rail's column: the glass panel, the rail's width and its padding. */ export function NavRail({ label, className, children, }: { /** The landmark's accessible name ("Primary navigation"). */ label: string; /** Placement only (position, height); the look and width are the primitive's. */ className?: string; children: ReactNode; }) { return ( ); } /** The rail's scrolling list of pages. An overflow container clips on BOTH axes, so the list spans the * rail's padding (`-mx-1 px-1`): the active row's edge bar, which sits in that padding, stays inside * the list's box and is not cut off. */ export function NavRailList({ ref, style, children, }: { ref?: Ref; /** The scroll fade's mask. */ style?: CSSProperties; children: ReactNode; }) { return (
{children}
); } /** A short, thick centred rule: the "new section" cue on an icon rail (the system modules). */ export function NavRailDivider() { return
; } /** The glyph of every rail row: a page, an action, the language switcher. */ export const RAIL_GLYPH = "size-4.5"; /** The shape of one rail row, for a row that is not a page (the account button). */ export const RAIL_ROW = "relative flex w-full flex-col items-center justify-center gap-0.5 rounded-lg transition touch-target"; export function NavRailItem({ icon: Icon, label, shortLabel, showLabel, active = false, badge, onClick, testId, }: { icon: LucideIcon; /** The full name: the tooltip, and the accessible name while the label is hidden. */ label: string; /** What fits under the icon when labels are on. */ shortLabel: string; showLabel: boolean; active?: boolean; /** An unread / in-progress count on the icon's corner (0 hides it). */ badge?: number; onClick: () => void; testId?: string; }) { const shown = !!badge && badge > 0; return ( ); } /** A rail row that acts instead of navigating (About, Sign out): the page rows' geometry and glyph, so * the column keeps one rhythm (F32: toolbar icon buttons here drew 32 squares with 16px glyphs). */ export function NavRailAction({ icon: Icon, label, onClick, }: { icon: LucideIcon; /** The tooltip and the accessible name. */ label: string; onClick: () => void; }) { return ( ); }