import type { Config, Group, WorkApp } from "../types"; import { Back, Cog, Collapse, Forward, Reload } from "./icons"; import { Favicon, GROUP_LABEL, ICON_CHROME } from "./ui"; interface Props { config: Config; activeId: string | null; collapsed: boolean; /** How much has arrived in each app since it was last looked at. */ unread: Record; onSelect: (id: string) => void; onToggleCollapse: () => void; onOpenSettings: () => void; onToggleGroup: (g: Group) => void; onBack: () => void; onForward: () => void; onReload: () => void; /** Height of the title bar the window's content runs underneath. */ chrome: number; } /** * Wide enough that the macOS traffic lights fit inside the rail rather than * spilling over the page. Everything else about the rail follows from that. */ const RAIL = 72; const PANEL = 240; export const navWidth = (collapsed: boolean) => (collapsed ? RAIL : PANEL); export default function Nav({ config, activeId, collapsed, unread, onSelect, onToggleCollapse, onOpenSettings, onToggleGroup, onBack, onForward, onReload, chrome, }: Props) { const groups = [...config.groups].sort((a, b) => a.order - b.order); const inGroup = (id: string | null) => config.apps.filter((a) => a.groupId === id).sort((a, b) => a.order - b.order); const ungrouped = inGroup(null); const disabled = !activeId; const shell = "flex shrink-0 flex-col overflow-hidden border-r border-slate-200 bg-white " + "dark:border-slate-800 dark:bg-slate-900"; /* Back, forward, reload and settings. Nothing hides an element here — that lives on the right-click menu, where you are already pointing at the thing you want gone. */ const controls = ( <> ); /* Settings lives at the foot of both layouts: it is the thing you reach for least, and putting it there leaves the top for what you use constantly. */ const settingsButton = ( ); /* A count of what arrived while you were elsewhere. Absent, rather than zero, when there is nothing — a row of noughts is just noise. */ const badge = (id: string, active: boolean) => { const n = unread[id] ?? 0; if (n === 0) return null; return ( {n > 99 ? "99+" : n} ); }; // ------------------------------------------------------------ icon rail if (collapsed) { const railBtn = (app: WorkApp) => { const active = app.id === activeId; return ( ); }; return ( ); } // -------------------------------------------------------------- panel const row = "flex w-full cursor-pointer items-center gap-2 rounded-lg px-2 py-1.5 text-[13px] transition-colors"; const inactive = "text-slate-600 hover:bg-slate-100 dark:text-slate-300 dark:hover:bg-slate-800"; const active = "bg-slate-900 text-white dark:bg-white dark:text-slate-900"; const appRow = (app: WorkApp) => (
  • ); return ( ); }