feat: Revamp instance page
This commit is contained in:
@@ -13,12 +13,24 @@ import type { HTMLAttributes, TdHTMLAttributes, ThHTMLAttributes } from "react";
|
||||
* 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 <table>, 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.
|
||||
*/
|
||||
|
||||
export function Table({ className, children, ...props }: HTMLAttributes<HTMLTableElement>) {
|
||||
const STACK = "max-sm:[.stacked_&]:block";
|
||||
|
||||
export function Table({ stack, className, children, ...props }: HTMLAttributes<HTMLTableElement> & { stack?: boolean }) {
|
||||
return (
|
||||
<div className="overflow-x-auto">
|
||||
<table className={clsx("w-full border-collapse text-left text-[0.86rem]", className)} {...props}>
|
||||
<table className={clsx("w-full border-collapse text-left text-[0.86rem]", stack && "stacked max-sm:block", className)} {...props}>
|
||||
{children}
|
||||
</table>
|
||||
</div>
|
||||
@@ -27,7 +39,7 @@ export function Table({ className, children, ...props }: HTMLAttributes<HTMLTabl
|
||||
|
||||
export function THead({ className, children, ...props }: HTMLAttributes<HTMLTableSectionElement>) {
|
||||
return (
|
||||
<thead className={clsx("border-b border-rule", className)} {...props}>
|
||||
<thead className={clsx("border-b border-rule", "max-sm:[.stacked_&]:hidden", className)} {...props}>
|
||||
{children}
|
||||
</thead>
|
||||
);
|
||||
@@ -35,7 +47,7 @@ export function THead({ className, children, ...props }: HTMLAttributes<HTMLTabl
|
||||
|
||||
export function TBody({ className, children, ...props }: HTMLAttributes<HTMLTableSectionElement>) {
|
||||
return (
|
||||
<tbody className={className} {...props}>
|
||||
<tbody className={clsx(STACK, "max-sm:[.stacked_&]:space-y-3 max-sm:[.stacked_&]:p-3", className)} {...props}>
|
||||
{children}
|
||||
</tbody>
|
||||
);
|
||||
@@ -43,7 +55,19 @@ export function TBody({ className, children, ...props }: HTMLAttributes<HTMLTabl
|
||||
|
||||
export function TR({ className, children, ...props }: HTMLAttributes<HTMLTableRowElement>) {
|
||||
return (
|
||||
<tr className={clsx("border-b border-rule-soft last:border-0 hover:bg-panel-2", className)} {...props}>
|
||||
<tr
|
||||
className={clsx(
|
||||
"border-b border-rule-soft last:border-0 hover:bg-panel-2",
|
||||
STACK,
|
||||
// Plain bg-panel-2, not an opacity modifier: this app's tokens
|
||||
// are whole colours rather than RGB channels, so `/40` has
|
||||
// nothing to drop an alpha into. web/ stores channels precisely
|
||||
// because it leans on those modifiers; this one must not.
|
||||
"max-sm:[.stacked_&]:rounded max-sm:[.stacked_&]:border max-sm:[.stacked_&]:border-rule max-sm:[.stacked_&]:bg-panel-2 max-sm:[.stacked_&]:p-3",
|
||||
className,
|
||||
)}
|
||||
{...props}
|
||||
>
|
||||
{children}
|
||||
</tr>
|
||||
);
|
||||
@@ -69,9 +93,24 @@ export function TH({ className, numeric, children, ...props }: ThHTMLAttributes<
|
||||
);
|
||||
}
|
||||
|
||||
export function TD({ className, numeric, children, ...props }: TdHTMLAttributes<HTMLTableCellElement> & CellProps) {
|
||||
export function TD({ className, numeric, label, children, ...props }: TdHTMLAttributes<HTMLTableCellElement> & CellProps & { label?: string }) {
|
||||
return (
|
||||
<td className={clsx("px-4 py-3 align-middle", numeric && "text-right tabular-nums", className)} {...props}>
|
||||
<td
|
||||
className={clsx(
|
||||
"px-4 py-3 align-middle",
|
||||
numeric && "text-right tabular-nums",
|
||||
// Stacked, a cell is a label above its value and the right
|
||||
// alignment that made a money column read down the page is
|
||||
// meaningless, so it is dropped.
|
||||
STACK,
|
||||
"max-sm:[.stacked_&]:px-0 max-sm:[.stacked_&]:py-1 max-sm:[.stacked_&]:text-left",
|
||||
className,
|
||||
)}
|
||||
{...props}
|
||||
>
|
||||
{label && (
|
||||
<span className="mb-0.5 hidden font-mono text-[0.6rem] uppercase tracking-[0.13em] text-ink-3 max-sm:[.stacked_&]:block">{label}</span>
|
||||
)}
|
||||
{children}
|
||||
</td>
|
||||
);
|
||||
|
||||
Reference in New Issue
Block a user