style(mobile): responsive tabs + table overflow + hub flex-wrap (Phase A)

Adds <ResponsiveTabs> primitive that swaps the TabsList for a native Select on
phone-sized viewports (<640px). DetailLayout now routes its tab strip through it,
so every tabbed detail page gets the collapse for free. DataTable wraps the
Table in overflow-x-auto so wide column sets scroll horizontally instead of
breaking the layout under 768px. Documents-hub row swaps the fixed
grid-cols-[auto_1fr_auto_auto_auto_auto] for flex-wrap below sm: so signers /
status / dates stack instead of clipping.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
Matt Ciaccio
2026-04-28 12:10:21 +02:00
parent 40ae860a88
commit 2d1b50745a
4 changed files with 92 additions and 44 deletions

View File

@@ -115,17 +115,14 @@ export function DataTable<TData>({
: undefined,
},
onRowSelectionChange: (updater) => {
const newSelection =
typeof updater === 'function' ? updater(rowSelectionState) : updater;
const newSelection = typeof updater === 'function' ? updater(rowSelectionState) : updater;
setRowSelection(newSelection);
},
getRowId: getRowId as (row: TData, index: number) => string,
enableRowSelection: !!bulkActions?.length,
});
const selectedIds = Object.keys(rowSelectionState).filter(
(k) => rowSelectionState[k],
);
const selectedIds = Object.keys(rowSelectionState).filter((k) => rowSelectionState[k]);
function handleSort(columnId: string) {
if (!onSortChange) return;
@@ -147,7 +144,7 @@ export function DataTable<TData>({
return (
<div className="space-y-2">
<div className="rounded-md border">
<div className="rounded-md border overflow-x-auto">
<Table>
<TableHeader className="sticky top-0 z-10 bg-muted/50">
{table.getHeaderGroups().map((headerGroup) => (
@@ -160,7 +157,11 @@ export function DataTable<TData>({
header.column.getCanSort() && onSortChange && 'cursor-pointer select-none',
)}
onClick={() => {
if (header.column.getCanSort() && onSortChange && header.column.id !== 'select') {
if (
header.column.getCanSort() &&
onSortChange &&
header.column.id !== 'select'
) {
handleSort(header.column.id);
}
}}