feat(mui): kit — sortable DataTable headers (TableSortLabel), additive

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
BOHA
2026-06-06 21:22:25 +02:00
parent b76731d790
commit ca55529ff6

View File

@@ -5,6 +5,7 @@ import TableCell from "@mui/material/TableCell";
import TableContainer from "@mui/material/TableContainer"; import TableContainer from "@mui/material/TableContainer";
import TableHead from "@mui/material/TableHead"; import TableHead from "@mui/material/TableHead";
import TableRow from "@mui/material/TableRow"; import TableRow from "@mui/material/TableRow";
import TableSortLabel from "@mui/material/TableSortLabel";
export interface DataColumn<T> { export interface DataColumn<T> {
key: string; key: string;
@@ -14,6 +15,8 @@ export interface DataColumn<T> {
mono?: boolean; mono?: boolean;
/** Emphasize the cell (font-weight 500). */ /** Emphasize the cell (font-weight 500). */
bold?: boolean; bold?: boolean;
/** If set, the header becomes a clickable sort control (requires onSort). */
sortKey?: string;
render: (row: T) => ReactNode; render: (row: T) => ReactNode;
} }
@@ -23,6 +26,10 @@ export interface DataTableProps<T> {
rowKey: (row: T) => string | number; rowKey: (row: T) => string | number;
rowInactive?: (row: T) => boolean; rowInactive?: (row: T) => boolean;
empty?: ReactNode; empty?: ReactNode;
/** Server-sort wiring: active key (matches a column's sortKey), direction, handler. */
sortBy?: string;
sortDir?: "asc" | "desc";
onSort?: (key: string) => void;
} }
/** Dense, Soft-SaaS-styled data table. Styling only — never re-formats values. */ /** Dense, Soft-SaaS-styled data table. Styling only — never re-formats values. */
@@ -32,6 +39,9 @@ export default function DataTable<T>({
rowKey, rowKey,
rowInactive, rowInactive,
empty, empty,
sortBy,
sortDir,
onSort,
}: DataTableProps<T>) { }: DataTableProps<T>) {
if (rows.length === 0 && empty) return <>{empty}</>; if (rows.length === 0 && empty) return <>{empty}</>;
return ( return (
@@ -43,6 +53,9 @@ export default function DataTable<T>({
<TableCell <TableCell
key={c.key} key={c.key}
align={c.align} align={c.align}
sortDirection={
c.sortKey && sortBy === c.sortKey ? sortDir : false
}
sx={{ sx={{
textTransform: "uppercase", textTransform: "uppercase",
letterSpacing: ".05em", letterSpacing: ".05em",
@@ -50,8 +63,20 @@ export default function DataTable<T>({
fontWeight: 700, fontWeight: 700,
color: "text.secondary", color: "text.secondary",
}} }}
>
{c.sortKey && onSort ? (
<TableSortLabel
active={sortBy === c.sortKey}
direction={
sortBy === c.sortKey ? (sortDir ?? "asc") : "asc"
}
onClick={() => onSort(c.sortKey!)}
> >
{c.header} {c.header}
</TableSortLabel>
) : (
c.header
)}
</TableCell> </TableCell>
))} ))}
</TableRow> </TableRow>