diff --git a/web/components/ui/Table.tsx b/web/components/ui/Table.tsx index d3b8094..df072da 100644 --- a/web/components/ui/Table.tsx +++ b/web/components/ui/Table.tsx @@ -1,11 +1,23 @@ import { clsx } from "clsx"; import { HTMLAttributes, TdHTMLAttributes, ThHTMLAttributes } from "react"; +/* + * Below sm the table stops being a table: the head is hidden, each row becomes + * a bordered card and each cell becomes a label/value pair. That lives here + * rather than in the six pages that render tables — two markup trees per page + * would drift apart on the first edit, and every one of those trees would mean + * the same thing. + * + * The mobile label uses Th's exact keyed-label idiom (mono, small, widely + * tracked, dimmed) because a key beside a value on a phone is the same device + * as a column head above it on a desktop. + */ + export function Table({ className, children, ...props }: HTMLAttributes) { return (
{children} @@ -16,7 +28,7 @@ export function Table({ className, children, ...props }: HTMLAttributes) { return ( - + {children} ); @@ -24,7 +36,14 @@ export function Thead({ className, children, ...props }: HTMLAttributes) { return ( - + {children} ); @@ -33,7 +52,11 @@ export function Tbody({ className, children, ...props }: HTMLAttributes) { return ( {children} @@ -59,12 +82,34 @@ export function Th({ className, children, ...props }: ThHTMLAttributes) { +interface TdProps extends TdHTMLAttributes { + /** + * The column head this cell belongs to, shown beside the value below sm + * where the real head is hidden. Omit on a trailing action cell — an action + * needs no key, and the button then sits alone on its own row in the card. + */ + label?: string; +} + +export function Td({ className, label, children, ...props }: TdProps) { return ( );
+ {label && ( + + {label} + + )} {children}