feat(web): card-stack tables below sm
This commit is contained in:
@@ -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<HTMLTableElement>) {
|
||||
return (
|
||||
<div className="overflow-x-auto">
|
||||
<table
|
||||
className={clsx("w-full border-collapse text-sm", className)}
|
||||
className={clsx("w-full border-collapse text-sm max-sm:block", className)}
|
||||
{...props}
|
||||
>
|
||||
{children}
|
||||
@@ -16,7 +28,7 @@ export function Table({ className, children, ...props }: HTMLAttributes<HTMLTabl
|
||||
|
||||
export function Thead({ className, children, ...props }: HTMLAttributes<HTMLTableSectionElement>) {
|
||||
return (
|
||||
<thead className={clsx("border-b border-border", className)} {...props}>
|
||||
<thead className={clsx("border-b border-border max-sm:hidden", className)} {...props}>
|
||||
{children}
|
||||
</thead>
|
||||
);
|
||||
@@ -24,7 +36,14 @@ export function Thead({ className, children, ...props }: HTMLAttributes<HTMLTabl
|
||||
|
||||
export function Tbody({ className, children, ...props }: HTMLAttributes<HTMLTableSectionElement>) {
|
||||
return (
|
||||
<tbody className={clsx("divide-y divide-border", className)} {...props}>
|
||||
<tbody
|
||||
className={clsx(
|
||||
"divide-y divide-border",
|
||||
"max-sm:block max-sm:space-y-3 max-sm:divide-y-0 max-sm:p-3",
|
||||
className
|
||||
)}
|
||||
{...props}
|
||||
>
|
||||
{children}
|
||||
</tbody>
|
||||
);
|
||||
@@ -33,7 +52,11 @@ export function Tbody({ className, children, ...props }: HTMLAttributes<HTMLTabl
|
||||
export function Tr({ className, children, ...props }: HTMLAttributes<HTMLTableRowElement>) {
|
||||
return (
|
||||
<tr
|
||||
className={clsx("transition-colors hover:bg-surface-2/50", className)}
|
||||
className={clsx(
|
||||
"transition-colors hover:bg-surface-2/50",
|
||||
"max-sm:block max-sm:rounded max-sm:border max-sm:border-border max-sm:bg-surface-2/40 max-sm:p-3",
|
||||
className
|
||||
)}
|
||||
{...props}
|
||||
>
|
||||
{children}
|
||||
@@ -59,12 +82,34 @@ export function Th({ className, children, ...props }: ThHTMLAttributes<HTMLTable
|
||||
);
|
||||
}
|
||||
|
||||
export function Td({ className, children, ...props }: TdHTMLAttributes<HTMLTableCellElement>) {
|
||||
interface TdProps extends TdHTMLAttributes<HTMLTableCellElement> {
|
||||
/**
|
||||
* 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 (
|
||||
<td
|
||||
className={clsx("px-4 py-3 text-text-primary", className)}
|
||||
className={clsx(
|
||||
"px-4 py-3 text-text-primary",
|
||||
"max-sm:flex max-sm:items-start max-sm:gap-4 max-sm:px-0 max-sm:py-1.5",
|
||||
// Exactly one justify class — clsx picks it. Emitting both and relying
|
||||
// on string order would not work: Tailwind's output order decides which
|
||||
// of two same-property utilities wins, not the order in this array.
|
||||
label ? "max-sm:justify-between" : "max-sm:justify-end max-sm:pt-2.5",
|
||||
className
|
||||
)}
|
||||
{...props}
|
||||
>
|
||||
{label && (
|
||||
<span className="hidden font-mono text-[0.68rem] uppercase leading-5 tracking-[0.13em] text-text-secondary max-sm:inline">
|
||||
{label}
|
||||
</span>
|
||||
)}
|
||||
{children}
|
||||
</td>
|
||||
);
|
||||
|
||||
Reference in New Issue
Block a user