import clsx from "clsx"; import type { HTMLAttributes, TdHTMLAttributes, ThHTMLAttributes } from "react"; /* * One table treatment for the whole console. * * There were four: billing, licences, accounts and catalogue each wrote their * own thead, and they disagreed about the head's type size, its tracking, * whether it sat on --panel-2, and whether numbers were tabular. Catalogue's * heads were sentence-case body text. A registry whose columns are set four * ways does not read as one product. * * The head is the keyed idiom — mono, small, uppercase, widely tracked — which * is what a column head is: a key above a value, exactly as the record line is * a key beside one. * * MOBILE. `stack` collapses the table into one card per row below sm, each cell * becoming a label/value pair drawn from TD's `label`. The variants below hang * off a `stacked` class on the , so a table that does not opt in is * untouched at every width. * * It is opt-in rather than automatic because a stacked row whose cells have no * labels is worse than a scrolling one — the values lose the only thing naming * them. Customer screens stack; the staff console's wide registry tables scroll * sideways instead, which is the right trade for eight columns read at a desk. */ const STACK = "max-sm:[.stacked_&]:block"; export function Table({ stack, className, children, ...props }: HTMLAttributes & { stack?: boolean }) { return (
{children}
); } export function THead({ className, children, ...props }: HTMLAttributes) { return ( {children} ); } export function TBody({ className, children, ...props }: HTMLAttributes) { return ( {children} ); } export function TR({ className, children, ...props }: HTMLAttributes) { return ( {children} ); } interface CellProps { /** Right-aligns the cell. For quantities and money, which read down the column. */ numeric?: boolean; } export function TH({ className, numeric, children, ...props }: ThHTMLAttributes & CellProps) { return ( {children} ); } export function TD({ className, numeric, label, children, ...props }: TdHTMLAttributes & CellProps & { label?: string }) { return ( {label && ( {label} )} {children} ); } /** The secondary line under a cell's main value — an ID, a deployment, a date. */ export function Sub({ children }: { children: React.ReactNode }) { return
{children}
; }