import * as React from 'react'; import { ChevronRight } from 'lucide-react'; import { cn } from '@/lib/utils'; /** * Shared page furniture for the Admin product. * * Admin pages are dense and numerous, so the header, the section labels and the * vertical rhythm are defined once here. That is what makes seven independently * built pages read as one product rather than seven takes on a dashboard. */ /** * AdminPage — the standard page frame: title, subtitle, right-aligned controls, * then stacked sections. * * Controls live in the page rather than in the global chrome, which is why the * Admin header only needs one 56px bar. */ interface AdminPageProps { title?: string; subtitle?: string; meta?: any; actions?: any; tabs?: any; children: React.ReactNode; className?: string; } export function AdminPage({ title, subtitle, meta, actions, tabs, children, className }: AdminPageProps) { return (
{/* Wraps rather than compresses. The row carries three things of very different lengths — the page name, its count and the status pill — and on a 390px screen holding them on one line meant the count breaking mid-phrase and the pill splitting into "Live / System". Nothing wraps at any width where all three fit, so every desktop layout is untouched. */}

{title}

{/* A count of whatever the page is a list of, stated beside its name rather than only inside the list. */} {meta && {meta}} Live System
{subtitle &&

{subtitle}

}
{actions &&
{actions}
}
{tabs} {children}
); } /** * SectionTitle — the label above a region. * * Sentence-case and small rather than a heavy all-caps overline: on a page with * four or five sections, loud labels compete with the data they introduce. */ interface SectionTitleProps { id?: any; title?: string; meta?: any; action?: any; className?: string; } export function SectionTitle({ id, title, meta, action, className }: SectionTitleProps) { return (
{/* The count wraps under the section name rather than competing with it for a 390px line. On any width where both fit — every desktop and tablet layout — nothing wraps and the row is the row it always was. */}

{title}

{meta && {meta}}
{action && ( )}
); } /** * Toolbar — the controls row above a table or list. * * Search takes the remaining space, filters keep their natural width, and the * primary action is pushed to the end, so every management page has the same * control geometry. */ interface ToolbarProps { search?: any; filters?: any; actions?: any; meta?: any; className?: string; } export function Toolbar({ search = null, filters = null, actions = null, meta = null, className = '' }: ToolbarProps) { return (
{search &&
{search}
} {filters &&
{filters}
} {actions &&
{actions}
}
{meta &&

{meta}

}
); }