UNPKG

wcz-layout

Version:

230 lines (176 loc) 6.08 kB
--- name: data-grid description: > MUI X DataGrid Premium with wcz-layout helpers. ChipInputCell for chip rendering in cells (getLabel for complex objects). EditableColumnHeader for pencil icon headers. RouterGridActionsCellItem for type-safe row action navigation. Column definitions with renderCell/renderHeader. Feed rows from useLiveQuery collection data. Activate when building data tables or grids. type: composition library: wcz-layout library_version: "7.6.1" requires: - tanstack-db-collections - ui-pages sources: - "wcz-layout:src/components/data-grid/ChipInputCell.tsx" - "wcz-layout:src/components/data-grid/EditableColumnHeader.tsx" - "wcz-layout:src/components/router/RouterGridActionsCellItem.tsx" --- # Data Grid ## Setup Install `@mui/x-data-grid-premium` (peer dependency). Use `DataGridPremium`, not the community `DataGrid`. ## Core Patterns ### Basic data grid with collection data ```typescript import { DataGridPremium, type GridColDef } from "@mui/x-data-grid-premium"; import { useLiveQuery } from "@tanstack/react-db"; import { todoCollection } from "~/lib/db/collections/todoCollection"; import type { Todo } from "~/schemas/todo"; const columns: GridColDef<Todo>[] = [ { field: "name", headerName: "Name", flex: 1 }, { field: "isCompleted", headerName: "Completed", type: "boolean", width: 120 }, { field: "createdAt", headerName: "Created", type: "dateTime", width: 180 }, ]; function TodoGrid() { const { data: todos } = useLiveQuery((query) => query.from({ todos: todoCollection }) ); return ( <DataGridPremium rows={todos} columns={columns} getRowId={(row) => row.id} autoHeight /> ); } ``` ### Row actions with RouterGridActionsCellItem ```typescript import { RouterGridActionsCellItem } from "wcz-layout/components"; import EditIcon from "@mui/icons-material/Edit"; import DeleteIcon from "@mui/icons-material/Delete"; import type { GridColDef } from "@mui/x-data-grid-premium"; const columns: GridColDef<Todo>[] = [ { field: "name", headerName: "Name", flex: 1 }, { field: "actions", type: "actions", width: 100, getActions: (params) => [ <RouterGridActionsCellItem key="edit" icon={<EditIcon />} label="Edit" to="/todos/edit/$id" params={{ id: params.row.id }} />, <RouterGridActionsCellItem key="delete" icon={<DeleteIcon />} label="Delete" onClick={() => handleDelete(params.row)} showInMenu />, ], }, ]; ``` `RouterGridActionsCellItem` wraps MUI's `GridActionsCellItem` with TanStack Router's `createLink` for type-safe SPA navigation. ### ChipInputCell for array/tag columns ```typescript import { ChipInputCell } from "wcz-layout/components"; import type { GridColDef } from "@mui/x-data-grid-premium"; const columns: GridColDef<Todo>[] = [ { field: "tags", headerName: "Tags", flex: 1, renderCell: (params) => <ChipInputCell params={params} />, }, ]; ``` For complex objects (not plain strings), provide `getLabel`: ```typescript renderCell: (params) => ( <ChipInputCell params={params} getLabel={(item) => item.displayName} slotProps={{ size: "small", color: "primary" }} /> ), ``` `ChipInputCell` renders a horizontal scrollable stack of `Chip` components. It handles both scalar and array values automatically. ### EditableColumnHeader ```typescript import { EditableColumnHeader } from "wcz-layout/components"; const columns: GridColDef<Todo>[] = [ { field: "name", headerName: "Name", flex: 1, editable: true, renderHeader: (params) => <EditableColumnHeader {...params} />, }, ]; ``` Renders the column header text with a trailing pencil (Edit) icon to visually indicate editable columns. Purely visual no interaction. ## Common Mistakes ### HIGH Using DataGrid instead of DataGridPremium Wrong: ```typescript import { DataGrid } from "@mui/x-data-grid"; ``` Correct: ```typescript import { DataGridPremium } from "@mui/x-data-grid-premium"; ``` The library peer-depends on `@mui/x-data-grid-premium`. Using the community `DataGrid` loses Premium features like column grouping, row grouping, tree data, and aggregation. Source: package.json peerDependencies ### HIGH Using GridActionsCellItem instead of RouterGridActionsCellItem Wrong: ```typescript import { GridActionsCellItem } from "@mui/x-data-grid-premium"; <GridActionsCellItem icon={<EditIcon />} label="Edit" onClick={() => navigate({ to: `/todos/${id}` })} /> ``` Correct: ```typescript import { RouterGridActionsCellItem } from "wcz-layout/components"; <RouterGridActionsCellItem icon={<EditIcon />} label="Edit" to="/todos/edit/$id" params={{ id }} /> ``` Plain `GridActionsCellItem` doesn't support TanStack Router navigation. `RouterGridActionsCellItem` wraps it with `createLink` for type-safe routing without manual `onClick` + `navigate`. Source: wcz-layout:src/components/router/RouterGridActionsCellItem.tsx ### MEDIUM Not passing getLabel to ChipInputCell for complex objects Wrong: ```typescript // params.value is Array<{ id: string; name: string }> <ChipInputCell params={params} /> // Renders [object Object] chips ``` Correct: ```typescript <ChipInputCell params={params} getLabel={(item) => item.name} /> ``` `ChipInputCell` defaults `getLabel` to identity (value as-is). For objects, you must provide `getLabel` to extract the display string. Source: wcz-layout:src/components/data-grid/ChipInputCell.tsx ### HIGH Tension: MUI component API vs. TanStack Router types `RouterGridActionsCellItem` merges MUI grid action props with TanStack Router `LinkProps`. Use `to` + `params` for internal navigation. Using `onClick` + `navigate` bypasses the type-safe link and router prefetching. See also: skills/ui-pages/SKILL.md § Common Mistakes --- See also: - skills/tanstack-db-collections/SKILL.md Grid rows come from useLiveQuery results. - skills/ui-pages/SKILL.md Grid pages follow the same routing patterns.