From ca55529ff688ef8bff174d0e664181d4cb5a048e Mon Sep 17 00:00:00 2001 From: BOHA Date: Sat, 6 Jun 2026 21:22:25 +0200 Subject: [PATCH] =?UTF-8?q?feat(mui):=20kit=20=E2=80=94=20sortable=20DataT?= =?UTF-8?q?able=20headers=20(TableSortLabel),=20additive?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-Authored-By: Claude Opus 4.8 (1M context) --- src/admin/ui/DataTable.tsx | 27 ++++++++++++++++++++++++++- 1 file changed, 26 insertions(+), 1 deletion(-) diff --git a/src/admin/ui/DataTable.tsx b/src/admin/ui/DataTable.tsx index dfcc234..c0b2173 100644 --- a/src/admin/ui/DataTable.tsx +++ b/src/admin/ui/DataTable.tsx @@ -5,6 +5,7 @@ import TableCell from "@mui/material/TableCell"; import TableContainer from "@mui/material/TableContainer"; import TableHead from "@mui/material/TableHead"; import TableRow from "@mui/material/TableRow"; +import TableSortLabel from "@mui/material/TableSortLabel"; export interface DataColumn { key: string; @@ -14,6 +15,8 @@ export interface DataColumn { mono?: boolean; /** Emphasize the cell (font-weight 500). */ bold?: boolean; + /** If set, the header becomes a clickable sort control (requires onSort). */ + sortKey?: string; render: (row: T) => ReactNode; } @@ -23,6 +26,10 @@ export interface DataTableProps { rowKey: (row: T) => string | number; rowInactive?: (row: T) => boolean; 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. */ @@ -32,6 +39,9 @@ export default function DataTable({ rowKey, rowInactive, empty, + sortBy, + sortDir, + onSort, }: DataTableProps) { if (rows.length === 0 && empty) return <>{empty}; return ( @@ -43,6 +53,9 @@ export default function DataTable({ ({ color: "text.secondary", }} > - {c.header} + {c.sortKey && onSort ? ( + onSort(c.sortKey!)} + > + {c.header} + + ) : ( + c.header + )} ))}