@redsift/ds-mcp-server 12.3.1-muiv6-alpha.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +203 -0
- package/consumer-instructions/.cursorrules +80 -0
- package/consumer-instructions/.windsurfrules +80 -0
- package/consumer-instructions/CLAUDE.md +87 -0
- package/consumer-instructions/redsift-design-system.instructions.md +87 -0
- package/data/demos/patterns/crossfiltered-datagrid-page/example.tsx +750 -0
- package/data/demos/patterns/crossfiltered-datagrid-page/with-empty-state.tsx +111 -0
- package/data/demos/patterns/crossfiltered-datagrid-page/with-error.tsx +122 -0
- package/data/demos/patterns/crossfiltered-datagrid-page/with-loading.tsx +88 -0
- package/data/demos/patterns/datagrid-page/example.tsx +521 -0
- package/data/demos/patterns/datagrid-page/with-empty-state.tsx +80 -0
- package/data/demos/patterns/datagrid-page/with-error.tsx +96 -0
- package/data/demos/patterns/datagrid-page/with-loading.tsx +57 -0
- package/data/demos/patterns/drilldown-datagrid-page/example.tsx +715 -0
- package/data/demos/patterns/drilldown-datagrid-page/with-empty-state.tsx +113 -0
- package/data/demos/patterns/drilldown-datagrid-page/with-error.tsx +125 -0
- package/data/demos/patterns/drilldown-datagrid-page/with-loading.tsx +90 -0
- package/data/demos/patterns/server-datagrid-page/example.tsx +757 -0
- package/data/demos/patterns/server-datagrid-page/with-empty-state.tsx +107 -0
- package/data/demos/patterns/server-datagrid-page/with-error.tsx +107 -0
- package/data/demos/patterns/server-datagrid-page/with-loading.tsx +63 -0
- package/data/docs/components/charts/Arc.json +179 -0
- package/data/docs/components/charts/Arcs.json +104 -0
- package/data/docs/components/charts/Axis.json +269 -0
- package/data/docs/components/charts/Bar.json +236 -0
- package/data/docs/components/charts/BarChart.json +852 -0
- package/data/docs/components/charts/BarChartBars.json +18 -0
- package/data/docs/components/charts/BarChartGroupedTooltip.json +9 -0
- package/data/docs/components/charts/BarChartOverlay.json +34 -0
- package/data/docs/components/charts/BarChartSection.json +94 -0
- package/data/docs/components/charts/BaseBarChart.json +852 -0
- package/data/docs/components/charts/ChartContainerTitle.json +574 -0
- package/data/docs/components/charts/DataPoint.json +160 -0
- package/data/docs/components/charts/Dot.json +191 -0
- package/data/docs/components/charts/EmptyBarChart.json +852 -0
- package/data/docs/components/charts/EmptyLineChart.json +753 -0
- package/data/docs/components/charts/EmptyPieChart.json +826 -0
- package/data/docs/components/charts/EmptyScatterPlot.json +802 -0
- package/data/docs/components/charts/Legend.json +510 -0
- package/data/docs/components/charts/LegendItem.json +128 -0
- package/data/docs/components/charts/Line.json +69 -0
- package/data/docs/components/charts/LineChart.json +753 -0
- package/data/docs/components/charts/LoadingBarChart.json +852 -0
- package/data/docs/components/charts/LoadingLineChart.json +753 -0
- package/data/docs/components/charts/LoadingPieChart.json +826 -0
- package/data/docs/components/charts/LoadingScatterPlot.json +802 -0
- package/data/docs/components/charts/PieChart.json +826 -0
- package/data/docs/components/charts/RenderedLineChart.json +753 -0
- package/data/docs/components/charts/RenderedLinearBarChart.json +823 -0
- package/data/docs/components/charts/RenderedOrdinalBarChart.json +852 -0
- package/data/docs/components/charts/RenderedPieChart.json +826 -0
- package/data/docs/components/charts/RenderedScatterPlot.json +802 -0
- package/data/docs/components/charts/ScatterPlot.json +802 -0
- package/data/docs/components/charts/getAxisType.json +9 -0
- package/data/docs/components/charts/getComponentPosition.json +9 -0
- package/data/docs/components/dashboard/ChartEmptyState.json +42 -0
- package/data/docs/components/dashboard/Dashboard.json +26 -0
- package/data/docs/components/dashboard/DataCard.json +300 -0
- package/data/docs/components/dashboard/DataCardBody.json +431 -0
- package/data/docs/components/dashboard/DataCardHeader.json +304 -0
- package/data/docs/components/dashboard/DataCardListbox.json +529 -0
- package/data/docs/components/dashboard/DataRow.json +539 -0
- package/data/docs/components/dashboard/DrilldownItem.json +342 -0
- package/data/docs/components/dashboard/FilterableBarChart.json +83 -0
- package/data/docs/components/dashboard/FilterableDataGrid.json +83 -0
- package/data/docs/components/dashboard/FilterablePieChart.json +83 -0
- package/data/docs/components/dashboard/FilterableScatterPlot.json +83 -0
- package/data/docs/components/dashboard/PdfDocument.json +58 -0
- package/data/docs/components/dashboard/PdfExportButton.json +458 -0
- package/data/docs/components/dashboard/TimeSeriesBarChart.json +172 -0
- package/data/docs/components/dashboard/WithFilters.json +83 -0
- package/data/docs/components/design-system/ActiveDescendantListbox.json +521 -0
- package/data/docs/components/design-system/Alert.json +349 -0
- package/data/docs/components/design-system/AppBar.json +64 -0
- package/data/docs/components/design-system/AppContainer.json +67 -0
- package/data/docs/components/design-system/AppContent.json +566 -0
- package/data/docs/components/design-system/AppSidePanel.json +87 -0
- package/data/docs/components/design-system/Badge.json +293 -0
- package/data/docs/components/design-system/BaseBreadcrumbs.json +298 -0
- package/data/docs/components/design-system/BaseGrid.json +543 -0
- package/data/docs/components/design-system/BaseSkeleton.json +338 -0
- package/data/docs/components/design-system/BreadcrumbItem.json +231 -0
- package/data/docs/components/design-system/Breadcrumbs.json +298 -0
- package/data/docs/components/design-system/Button.json +402 -0
- package/data/docs/components/design-system/ButtonGroup.json +415 -0
- package/data/docs/components/design-system/ButtonLink.json +568 -0
- package/data/docs/components/design-system/Card.json +328 -0
- package/data/docs/components/design-system/CardActions.json +431 -0
- package/data/docs/components/design-system/CardBody.json +431 -0
- package/data/docs/components/design-system/CardHeader.json +428 -0
- package/data/docs/components/design-system/Checkbox.json +426 -0
- package/data/docs/components/design-system/CheckboxGroup.json +382 -0
- package/data/docs/components/design-system/ConditionalWrapper.json +40 -0
- package/data/docs/components/design-system/DetailedCard.json +401 -0
- package/data/docs/components/design-system/DetailedCardCollapsibleSectionItems.json +29 -0
- package/data/docs/components/design-system/DetailedCardHeader.json +37 -0
- package/data/docs/components/design-system/DetailedCardSection.json +90 -0
- package/data/docs/components/design-system/DetailedCardSectionItem.json +109 -0
- package/data/docs/components/design-system/Flexbox.json +523 -0
- package/data/docs/components/design-system/FocusWithinGroup.json +9 -0
- package/data/docs/components/design-system/Grid.json +543 -0
- package/data/docs/components/design-system/GridItem.json +388 -0
- package/data/docs/components/design-system/Heading.json +390 -0
- package/data/docs/components/design-system/Icon.json +325 -0
- package/data/docs/components/design-system/IconButton.json +371 -0
- package/data/docs/components/design-system/IconButtonLink.json +588 -0
- package/data/docs/components/design-system/Item.json +554 -0
- package/data/docs/components/design-system/Link.json +552 -0
- package/data/docs/components/design-system/LinkButton.json +397 -0
- package/data/docs/components/design-system/Listbox.json +529 -0
- package/data/docs/components/design-system/Number.json +773 -0
- package/data/docs/components/design-system/NumberField.json +594 -0
- package/data/docs/components/design-system/Pill.json +378 -0
- package/data/docs/components/design-system/ProgressBar.json +121 -0
- package/data/docs/components/design-system/RadarSvgLinearGradient.json +9 -0
- package/data/docs/components/design-system/Radio.json +415 -0
- package/data/docs/components/design-system/RadioGroup.json +382 -0
- package/data/docs/components/design-system/RenderedListboxItem.json +18 -0
- package/data/docs/components/design-system/RovingTabindexListbox.json +521 -0
- package/data/docs/components/design-system/Shield.json +360 -0
- package/data/docs/components/design-system/SideNavigationMenu.json +144 -0
- package/data/docs/components/design-system/SideNavigationMenuBar.json +89 -0
- package/data/docs/components/design-system/SideNavigationMenuItem.json +319 -0
- package/data/docs/components/design-system/Skeleton.json +338 -0
- package/data/docs/components/design-system/SkeletonCircle.json +338 -0
- package/data/docs/components/design-system/SkeletonText.json +371 -0
- package/data/docs/components/design-system/Spinner.json +291 -0
- package/data/docs/components/design-system/Switch.json +415 -0
- package/data/docs/components/design-system/SwitchGroup.json +382 -0
- package/data/docs/components/design-system/Text.json +418 -0
- package/data/docs/components/design-system/TextArea.json +501 -0
- package/data/docs/components/design-system/TextField.json +539 -0
- package/data/docs/components/design-system/sizeToDimension.json +9 -0
- package/data/docs/components/pickers/BaseCombobox.json +320 -0
- package/data/docs/components/pickers/BaseComboboxContent.json +453 -0
- package/data/docs/components/pickers/BaseMenuButton.json +240 -0
- package/data/docs/components/pickers/BaseMenuButtonContent.json +442 -0
- package/data/docs/components/pickers/BaseSelect.json +258 -0
- package/data/docs/components/pickers/Combobox.json +320 -0
- package/data/docs/components/pickers/ComboboxContent.json +453 -0
- package/data/docs/components/pickers/ComboboxContentFooter.json +431 -0
- package/data/docs/components/pickers/ComboboxContentHeader.json +431 -0
- package/data/docs/components/pickers/ComboboxContentListbox.json +541 -0
- package/data/docs/components/pickers/ComboboxTrigger.json +336 -0
- package/data/docs/components/pickers/Item.json +554 -0
- package/data/docs/components/pickers/MenuButton.json +240 -0
- package/data/docs/components/pickers/MenuButtonContent.json +442 -0
- package/data/docs/components/pickers/MenuButtonContentFooter.json +431 -0
- package/data/docs/components/pickers/MenuButtonContentHeader.json +431 -0
- package/data/docs/components/pickers/MenuButtonContentMenu.json +523 -0
- package/data/docs/components/pickers/MenuButtonTrigger.json +287 -0
- package/data/docs/components/pickers/Select.json +258 -0
- package/data/docs/components/pickers/SelectContent.json +442 -0
- package/data/docs/components/pickers/SelectTrigger.json +298 -0
- package/data/docs/components/popovers/BaseDialog.json +114 -0
- package/data/docs/components/popovers/BaseDialogContent.json +21 -0
- package/data/docs/components/popovers/BasePopover.json +171 -0
- package/data/docs/components/popovers/BaseToggletip.json +184 -0
- package/data/docs/components/popovers/BaseTooltip.json +121 -0
- package/data/docs/components/popovers/Button.json +402 -0
- package/data/docs/components/popovers/ButtonLink.json +568 -0
- package/data/docs/components/popovers/Dialog.json +114 -0
- package/data/docs/components/popovers/DialogContent.json +21 -0
- package/data/docs/components/popovers/DialogContentActions.json +442 -0
- package/data/docs/components/popovers/DialogContentBody.json +442 -0
- package/data/docs/components/popovers/DialogContentHeader.json +76 -0
- package/data/docs/components/popovers/DialogTrigger.json +276 -0
- package/data/docs/components/popovers/IconButton.json +371 -0
- package/data/docs/components/popovers/IconButtonLink.json +588 -0
- package/data/docs/components/popovers/Link.json +552 -0
- package/data/docs/components/popovers/LinkButton.json +397 -0
- package/data/docs/components/popovers/Popover.json +171 -0
- package/data/docs/components/popovers/PopoverContent.json +442 -0
- package/data/docs/components/popovers/PopoverTrigger.json +276 -0
- package/data/docs/components/popovers/Toast.json +145 -0
- package/data/docs/components/popovers/ToastContainer.json +122 -0
- package/data/docs/components/popovers/Toggletip.json +184 -0
- package/data/docs/components/popovers/ToggletipContent.json +402 -0
- package/data/docs/components/popovers/ToggletipTrigger.json +276 -0
- package/data/docs/components/popovers/Tooltip.json +121 -0
- package/data/docs/components/popovers/TooltipContent.json +402 -0
- package/data/docs/components/popovers/TooltipTrigger.json +276 -0
- package/data/docs/components/products/Dialog.json +106 -0
- package/data/docs/components/products/MenuButton.json +232 -0
- package/data/docs/components/products/PulsedRadarImage.json +9 -0
- package/data/docs/components/products/RadarButton.json +402 -0
- package/data/docs/components/products/RadarItem.json +554 -0
- package/data/docs/components/table/ControlledPagination.json +9 -0
- package/data/docs/components/table/DataGrid.json +93 -0
- package/data/docs/components/table/GridToolbarFilterSemanticField.json +69 -0
- package/data/docs/components/table/ServerSideControlledPagination.json +9 -0
- package/data/docs/components/table/StatefulDataGrid.json +117 -0
- package/data/docs/components/table/TextCell.json +118 -0
- package/data/docs/components/table/Toolbar.json +145 -0
- package/data/docs/components/table/ToolbarWrapper.json +9 -0
- package/data/docs/components-index.json +1206 -0
- package/data/docs/components.json +55694 -0
- package/data/docs/llms-full.txt +8012 -0
- package/data/docs/llms.txt +234 -0
- package/data/docs/patterns-catalog.md +359 -0
- package/data/docs/patterns.json +712 -0
- package/data/metadata.json +4 -0
- package/data/patterns/crossfiltered-datagrid-page.mdx +386 -0
- package/data/patterns/datagrid-page.mdx +214 -0
- package/data/patterns/drilldown-datagrid-page.mdx +291 -0
- package/data/patterns/server-datagrid-page.mdx +301 -0
- package/data/tokens/properties/components/dark-components.json +1108 -0
- package/data/tokens/properties/components/light-components.json +1108 -0
- package/data/tokens/properties/core/border-radius.json +3 -0
- package/data/tokens/properties/core/color.json +280 -0
- package/data/tokens/properties/core/layout.json +14 -0
- package/data/tokens/properties/core/typography.json +199 -0
- package/data/tokens/redsift-design-tokens.css +1391 -0
- package/dist/data-store.d.ts +47 -0
- package/dist/data-store.d.ts.map +1 -0
- package/dist/data-store.js +152 -0
- package/dist/data-store.js.map +1 -0
- package/dist/index.d.ts +16 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +50 -0
- package/dist/index.js.map +1 -0
- package/dist/init.d.ts +14 -0
- package/dist/init.d.ts.map +1 -0
- package/dist/init.js +137 -0
- package/dist/init.js.map +1 -0
- package/dist/paths.d.ts +30 -0
- package/dist/paths.d.ts.map +1 -0
- package/dist/paths.js +53 -0
- package/dist/paths.js.map +1 -0
- package/dist/pattern-store.d.ts +41 -0
- package/dist/pattern-store.d.ts.map +1 -0
- package/dist/pattern-store.js +177 -0
- package/dist/pattern-store.js.map +1 -0
- package/dist/prompts.d.ts +14 -0
- package/dist/prompts.d.ts.map +1 -0
- package/dist/prompts.js +762 -0
- package/dist/prompts.js.map +1 -0
- package/dist/resources.d.ts +14 -0
- package/dist/resources.d.ts.map +1 -0
- package/dist/resources.js +482 -0
- package/dist/resources.js.map +1 -0
- package/dist/scaffold.d.ts +31 -0
- package/dist/scaffold.d.ts.map +1 -0
- package/dist/scaffold.js +239 -0
- package/dist/scaffold.js.map +1 -0
- package/dist/token-store.d.ts +70 -0
- package/dist/token-store.d.ts.map +1 -0
- package/dist/token-store.js +196 -0
- package/dist/token-store.js.map +1 -0
- package/dist/tools.d.ts +15 -0
- package/dist/tools.d.ts.map +1 -0
- package/dist/tools.js +491 -0
- package/dist/tools.js.map +1 -0
- package/dist/types.d.ts +108 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +17 -0
- package/dist/types.js.map +1 -0
- package/package.json +39 -0
|
@@ -0,0 +1,712 @@
|
|
|
1
|
+
[
|
|
2
|
+
{
|
|
3
|
+
"name": "Datagrid Page",
|
|
4
|
+
"slug": "datagrid-page",
|
|
5
|
+
"description": "Full-page MUI DataGrid with built-in Toolbar (columns, filters, density, export, quick search). Uses GridColDef[] with custom column types (rsString, rsNumber, rsSingleSelect), renderCell with TextCell and Pill, pagination, and checkboxSelection. All filtering, sorting, and pagination happen client-side — all rows are loaded into the DataGrid at once. Optionally includes bulk selection actions (rowSelectionModel + onRowSelectionModelChange). For server-side data handling, see the Server Datagrid Page pattern. Matches the table pattern used across OnDMARC, Certificates, and Brand Trust.",
|
|
6
|
+
"components": [
|
|
7
|
+
"DataGrid",
|
|
8
|
+
"TextCell",
|
|
9
|
+
"StatefulDataGrid",
|
|
10
|
+
"Pill",
|
|
11
|
+
"Button",
|
|
12
|
+
"Flexbox",
|
|
13
|
+
"Text",
|
|
14
|
+
"Badge",
|
|
15
|
+
"Icon",
|
|
16
|
+
"IconButton",
|
|
17
|
+
"IconButtonLink"
|
|
18
|
+
],
|
|
19
|
+
"packages": ["@redsift/table", "@redsift/design-system", "@mui/x-data-grid-pro"],
|
|
20
|
+
"layout": "DataGrid with autoHeight, pagination, pageSize, built-in Toolbar via componentsProps.toolbar.showQuickFilter. Optional bulk actions bar when selectionModel.length > 0.",
|
|
21
|
+
"tags": [
|
|
22
|
+
"table",
|
|
23
|
+
"datagrid",
|
|
24
|
+
"list",
|
|
25
|
+
"pagination",
|
|
26
|
+
"filter",
|
|
27
|
+
"toolbar",
|
|
28
|
+
"bulk-actions",
|
|
29
|
+
"GridColDef",
|
|
30
|
+
"filterModel",
|
|
31
|
+
"checkboxSelection",
|
|
32
|
+
"client-side"
|
|
33
|
+
],
|
|
34
|
+
"demoPath": "patterns/datagrid-page/example",
|
|
35
|
+
"whenToUse": [
|
|
36
|
+
"You need a filterable, sortable, paginated table of records",
|
|
37
|
+
"The full dataset can be loaded upfront (typically under ~1,000 rows)",
|
|
38
|
+
"All filtering, sorting, and pagination can happen client-side in the browser",
|
|
39
|
+
"You want built-in column visibility, density, export, and quick search with zero backend work",
|
|
40
|
+
"You need optional bulk selection with contextual action buttons"
|
|
41
|
+
],
|
|
42
|
+
"whenNotToUse": [
|
|
43
|
+
"The dataset has thousands or millions of rows — use Server Datagrid Page instead",
|
|
44
|
+
"Sorting or filtering logic must live on the backend (e.g. ElasticSearch, SQL) — use Server Datagrid Page instead"
|
|
45
|
+
],
|
|
46
|
+
"anatomy": [
|
|
47
|
+
"Toolbar — Flexbox wrapping GridToolbarContainer with filter, columns, density, export, quick search controls",
|
|
48
|
+
"DataGrid — the table itself, configured with autoHeight, pagination, checkboxSelection, and GridColDef[] columns",
|
|
49
|
+
"Bulk Action Bar — Flexbox row shown when selectionModel.length > 0, with Pill (count) and action Buttons"
|
|
50
|
+
],
|
|
51
|
+
"features": [
|
|
52
|
+
{
|
|
53
|
+
"name": "Column definitions",
|
|
54
|
+
"required": true,
|
|
55
|
+
"description": "GridColDef[] with custom types: rsString, rsNumber, rsSingleSelect, rsMultipleSelect, boolean, date"
|
|
56
|
+
},
|
|
57
|
+
{
|
|
58
|
+
"name": "Toolbar",
|
|
59
|
+
"required": true,
|
|
60
|
+
"description": "Built-in toolbar with filter, columns, density, export, and quick search controls"
|
|
61
|
+
},
|
|
62
|
+
{
|
|
63
|
+
"name": "Pagination",
|
|
64
|
+
"required": true,
|
|
65
|
+
"description": "Client-side pagination with configurable page size (rowsPerPageOptions)"
|
|
66
|
+
},
|
|
67
|
+
{ "name": "Sorting", "required": true, "description": "Client-side column sorting (built into DataGrid)" },
|
|
68
|
+
{ "name": "Filtering", "required": true, "description": "Client-side column filtering (built into DataGrid)" },
|
|
69
|
+
{
|
|
70
|
+
"name": "Custom cell renderers",
|
|
71
|
+
"required": true,
|
|
72
|
+
"description": "renderCell returning TextCell, Pill, Icon, IconButtonLink"
|
|
73
|
+
},
|
|
74
|
+
{
|
|
75
|
+
"name": "Checkbox selection",
|
|
76
|
+
"required": false,
|
|
77
|
+
"description": "checkboxSelection + rowSelectionModel + onRowSelectionModelChange"
|
|
78
|
+
},
|
|
79
|
+
{
|
|
80
|
+
"name": "Bulk action bar",
|
|
81
|
+
"required": false,
|
|
82
|
+
"description": "Contextual buttons shown when rows are selected"
|
|
83
|
+
},
|
|
84
|
+
{
|
|
85
|
+
"name": "Actions column",
|
|
86
|
+
"required": false,
|
|
87
|
+
"description": "Column with IconButtonLink for row-level navigation"
|
|
88
|
+
},
|
|
89
|
+
{
|
|
90
|
+
"name": "Quick search",
|
|
91
|
+
"required": false,
|
|
92
|
+
"description": "GridToolbarQuickFilter for text search across all columns"
|
|
93
|
+
}
|
|
94
|
+
],
|
|
95
|
+
"stateHooks": [
|
|
96
|
+
{
|
|
97
|
+
"name": "selectionModel",
|
|
98
|
+
"type": "GridSelectionModel",
|
|
99
|
+
"initial": "[]",
|
|
100
|
+
"description": "Tracks which rows are checked"
|
|
101
|
+
}
|
|
102
|
+
],
|
|
103
|
+
"dataContract": "type Row = {\n id: string;\n label: string;\n active: boolean;\n status: 'active' | 'warning' | 'critical' | 'expired';\n category: string;\n score: number;\n expiry: string;\n tags: string[];\n};",
|
|
104
|
+
"implementationSteps": [
|
|
105
|
+
"Define your row type — Create a TypeScript type Row. Every row must have a unique id field.",
|
|
106
|
+
"Define column definitions — Create a GridColDef[] array with RS custom column types (rsString, rsNumber, rsSingleSelect, rsMultipleSelect). Add renderCell for rich content.",
|
|
107
|
+
"Create the toolbar — Build a CustomToolbar using GridToolbarContainer with filter, columns, density, export, and quick search controls.",
|
|
108
|
+
"Set up state — Add useState<GridSelectionModel>([]) for checkbox selection (if needed).",
|
|
109
|
+
"Render the DataGrid — Pass rows, columns, autoHeight, pagination, pageSize, rowsPerPageOptions, checkboxSelection, components={{ Toolbar: CustomToolbar }}.",
|
|
110
|
+
"Add bulk action bar — Conditionally render when selectionModel.length > 0.",
|
|
111
|
+
"Handle edge cases — Add loading state (loading prop), empty state (custom NoRowsOverlay), and error state (conditional render with retry).",
|
|
112
|
+
"Verify — Test pagination breakpoints, filter operators, column visibility toggle, density switching, and export."
|
|
113
|
+
],
|
|
114
|
+
"variants": [
|
|
115
|
+
{
|
|
116
|
+
"name": "Loading State",
|
|
117
|
+
"slug": "with-loading",
|
|
118
|
+
"description": "DataGrid with loading={true} showing the built-in loading overlay"
|
|
119
|
+
},
|
|
120
|
+
{
|
|
121
|
+
"name": "Empty State",
|
|
122
|
+
"slug": "with-empty-state",
|
|
123
|
+
"description": "DataGrid with rows={[]} and a custom NoRowsOverlay"
|
|
124
|
+
},
|
|
125
|
+
{
|
|
126
|
+
"name": "Error State",
|
|
127
|
+
"slug": "with-error",
|
|
128
|
+
"description": "Error banner with retry button above the DataGrid"
|
|
129
|
+
}
|
|
130
|
+
],
|
|
131
|
+
"accessibility": [
|
|
132
|
+
"Arrow keys navigate between cells",
|
|
133
|
+
"Page Up / Page Down move between pages",
|
|
134
|
+
"Space toggles checkbox selection on the focused row",
|
|
135
|
+
"Tab moves focus between the toolbar and the grid",
|
|
136
|
+
"Every IconButtonLink in actions column needs aria-label",
|
|
137
|
+
"Custom NoRowsOverlay content must be announced to screen readers"
|
|
138
|
+
],
|
|
139
|
+
"relatedPatterns": [
|
|
140
|
+
{
|
|
141
|
+
"slug": "server-datagrid-page",
|
|
142
|
+
"relationship": "Use when the dataset is too large to load entirely, or when filtering/sorting must happen server-side"
|
|
143
|
+
},
|
|
144
|
+
{
|
|
145
|
+
"slug": "drilldown-datagrid-page",
|
|
146
|
+
"relationship": "Use when you want summary DataCards above the grid with one-way filter push"
|
|
147
|
+
},
|
|
148
|
+
{
|
|
149
|
+
"slug": "crossfiltered-datagrid-page",
|
|
150
|
+
"relationship": "Use when DataCard counts should recalculate as filters change (two-way sync)"
|
|
151
|
+
}
|
|
152
|
+
]
|
|
153
|
+
},
|
|
154
|
+
{
|
|
155
|
+
"name": "Server Datagrid Page",
|
|
156
|
+
"slug": "server-datagrid-page",
|
|
157
|
+
"description": "Full-page MUI DataGrid where filtering, sorting, and pagination are all handled server-side. Uses paginationMode='server', sortingMode='server', filterMode='server' with controlled rowCount and loading props. The same column types and toolbar as the client-side Datagrid Page pattern, but only the current page of data is fetched per request. Filter changes are debounced to avoid excessive requests. Ideal for datasets too large to load entirely in the browser.",
|
|
158
|
+
"components": [
|
|
159
|
+
"DataGrid",
|
|
160
|
+
"TextCell",
|
|
161
|
+
"Pill",
|
|
162
|
+
"Button",
|
|
163
|
+
"Flexbox",
|
|
164
|
+
"Text",
|
|
165
|
+
"Badge",
|
|
166
|
+
"Icon",
|
|
167
|
+
"IconButton",
|
|
168
|
+
"IconButtonLink"
|
|
169
|
+
],
|
|
170
|
+
"packages": ["@redsift/table", "@redsift/design-system", "@mui/x-data-grid-pro"],
|
|
171
|
+
"layout": "DataGrid with autoHeight, paginationMode='server', sortingMode='server', filterMode='server', rowCount, loading, built-in Toolbar. Optional bulk actions bar when selectionModel.length > 0.",
|
|
172
|
+
"tags": [
|
|
173
|
+
"table",
|
|
174
|
+
"datagrid",
|
|
175
|
+
"server-side",
|
|
176
|
+
"pagination",
|
|
177
|
+
"paginationMode",
|
|
178
|
+
"filterMode",
|
|
179
|
+
"sortingMode",
|
|
180
|
+
"loading",
|
|
181
|
+
"rowCount",
|
|
182
|
+
"filter",
|
|
183
|
+
"toolbar",
|
|
184
|
+
"bulk-actions",
|
|
185
|
+
"GridColDef",
|
|
186
|
+
"filterModel",
|
|
187
|
+
"sortModel",
|
|
188
|
+
"debounce"
|
|
189
|
+
],
|
|
190
|
+
"demoPath": "patterns/server-datagrid-page/example",
|
|
191
|
+
"whenToUse": [
|
|
192
|
+
"The dataset has thousands or millions of records that cannot be loaded into the browser",
|
|
193
|
+
"Filtering, sorting, or pagination logic must live on the backend (ElasticSearch, SQL, API)",
|
|
194
|
+
"You need the server to return the total matching count alongside the current page of results",
|
|
195
|
+
"Filter changes should be debounced to avoid excessive requests during rapid typing"
|
|
196
|
+
],
|
|
197
|
+
"whenNotToUse": [
|
|
198
|
+
"The dataset is small enough to load entirely (under ~1,000 rows) — use Datagrid Page instead",
|
|
199
|
+
"All data is available upfront and filtering can happen in the browser — use Datagrid Page instead"
|
|
200
|
+
],
|
|
201
|
+
"anatomy": [
|
|
202
|
+
"Toolbar — Flexbox wrapping GridToolbarContainer with filter, columns, density, export, quick search controls",
|
|
203
|
+
"DataGrid — the table configured with paginationMode='server', sortingMode='server', filterMode='server', loading, and rowCount",
|
|
204
|
+
"Bulk Action Bar — Flexbox row shown when selectionModel.length > 0, with Pill (count) and action Buttons"
|
|
205
|
+
],
|
|
206
|
+
"features": [
|
|
207
|
+
{
|
|
208
|
+
"name": "Server-side pagination",
|
|
209
|
+
"required": true,
|
|
210
|
+
"description": "paginationMode='server' with controlled page, pageSize, rowCount"
|
|
211
|
+
},
|
|
212
|
+
{
|
|
213
|
+
"name": "Server-side sorting",
|
|
214
|
+
"required": true,
|
|
215
|
+
"description": "sortingMode='server' with controlled sortModel + onSortModelChange"
|
|
216
|
+
},
|
|
217
|
+
{
|
|
218
|
+
"name": "Server-side filtering",
|
|
219
|
+
"required": true,
|
|
220
|
+
"description": "filterMode='server' with controlled filterModel + onFilterModelChange"
|
|
221
|
+
},
|
|
222
|
+
{ "name": "Loading overlay", "required": true, "description": "loading prop set to true during fetches" },
|
|
223
|
+
{
|
|
224
|
+
"name": "Row count",
|
|
225
|
+
"required": true,
|
|
226
|
+
"description": "rowCount prop set to total matching records from server response"
|
|
227
|
+
},
|
|
228
|
+
{
|
|
229
|
+
"name": "Debounced filter changes",
|
|
230
|
+
"required": true,
|
|
231
|
+
"description": "300ms debounce on onFilterModelChange to avoid excessive requests"
|
|
232
|
+
},
|
|
233
|
+
{
|
|
234
|
+
"name": "Column definitions",
|
|
235
|
+
"required": true,
|
|
236
|
+
"description": "GridColDef[] with custom types: rsString, rsNumber, rsSingleSelect, rsMultipleSelect"
|
|
237
|
+
},
|
|
238
|
+
{
|
|
239
|
+
"name": "Toolbar",
|
|
240
|
+
"required": true,
|
|
241
|
+
"description": "Built-in toolbar with filter, columns, density, export, and quick search"
|
|
242
|
+
},
|
|
243
|
+
{
|
|
244
|
+
"name": "Custom cell renderers",
|
|
245
|
+
"required": true,
|
|
246
|
+
"description": "renderCell returning TextCell, Pill, Icon, IconButtonLink"
|
|
247
|
+
},
|
|
248
|
+
{ "name": "Checkbox selection", "required": false, "description": "checkboxSelection + rowSelectionModel" },
|
|
249
|
+
{
|
|
250
|
+
"name": "Bulk action bar",
|
|
251
|
+
"required": false,
|
|
252
|
+
"description": "Contextual buttons shown when rows are selected"
|
|
253
|
+
},
|
|
254
|
+
{
|
|
255
|
+
"name": "Quick search",
|
|
256
|
+
"required": false,
|
|
257
|
+
"description": "GridToolbarQuickFilter with server-side text search"
|
|
258
|
+
}
|
|
259
|
+
],
|
|
260
|
+
"stateHooks": [
|
|
261
|
+
{
|
|
262
|
+
"name": "rows",
|
|
263
|
+
"type": "Row[]",
|
|
264
|
+
"initial": "[]",
|
|
265
|
+
"description": "Rows returned from the server for the current page"
|
|
266
|
+
},
|
|
267
|
+
{
|
|
268
|
+
"name": "totalRows",
|
|
269
|
+
"type": "number",
|
|
270
|
+
"initial": "0",
|
|
271
|
+
"description": "Total matching records (for pagination)"
|
|
272
|
+
},
|
|
273
|
+
{ "name": "loading", "type": "boolean", "initial": "true", "description": "Whether a fetch is in progress" },
|
|
274
|
+
{ "name": "page", "type": "number", "initial": "0", "description": "0-based current page index" },
|
|
275
|
+
{ "name": "pageSize", "type": "number", "initial": "10", "description": "Number of rows per page" },
|
|
276
|
+
{ "name": "sortModel", "type": "GridSortModel", "initial": "[]", "description": "Current sort configuration" },
|
|
277
|
+
{
|
|
278
|
+
"name": "filterModel",
|
|
279
|
+
"type": "GridFilterModel",
|
|
280
|
+
"initial": "{ items: [] }",
|
|
281
|
+
"description": "Current filter configuration"
|
|
282
|
+
},
|
|
283
|
+
{
|
|
284
|
+
"name": "selectionModel",
|
|
285
|
+
"type": "GridSelectionModel",
|
|
286
|
+
"initial": "[]",
|
|
287
|
+
"description": "Tracks which rows are checked"
|
|
288
|
+
},
|
|
289
|
+
{
|
|
290
|
+
"name": "quickFilterText",
|
|
291
|
+
"type": "string",
|
|
292
|
+
"initial": "''",
|
|
293
|
+
"description": "Text for quick search across columns"
|
|
294
|
+
},
|
|
295
|
+
{
|
|
296
|
+
"name": "debounceRef",
|
|
297
|
+
"type": "useRef<ReturnType<typeof setTimeout>>",
|
|
298
|
+
"initial": "undefined",
|
|
299
|
+
"description": "Ref for debouncing filter changes"
|
|
300
|
+
}
|
|
301
|
+
],
|
|
302
|
+
"dataContract": "type Row = {\n id: string;\n label: string;\n active: boolean;\n status: 'active' | 'warning' | 'critical' | 'expired';\n category: string;\n score: number;\n expiry: string;\n tags: string[];\n};\n\ntype FetchParams = {\n page: number;\n pageSize: number;\n sortModel: GridSortModel;\n filterModel: GridFilterModel;\n quickFilterText: string;\n};\n\ntype FetchResult = {\n rows: Row[];\n totalRows: number;\n};",
|
|
303
|
+
"implementationSteps": [
|
|
304
|
+
"Define your row type — Create a TypeScript type Row. Every row must have a unique id field.",
|
|
305
|
+
"Create your fetch function — Implement an async function matching the FetchParams → FetchResult contract. If using React Query, wrap it in a useQuery hook.",
|
|
306
|
+
"Define column definitions — Create a GridColDef[] array with RS custom column types. Add renderCell for rich content.",
|
|
307
|
+
"Create the toolbar — Build a CustomToolbar using GridToolbarContainer with filter, columns, density, export, and quick search controls.",
|
|
308
|
+
"Set up state — Add all hooks: rows, totalRows, loading, page, pageSize, sortModel, filterModel, selectionModel, quickFilterText, debounce ref.",
|
|
309
|
+
"Wire the fetch effect — Use useEffect to call your fetch function whenever page, pageSize, sortModel, filterModel, or quickFilterText changes.",
|
|
310
|
+
"Configure the DataGrid — Pass paginationMode='server', sortingMode='server', filterMode='server', loading, rowCount={totalRows}, and all controlled state handlers.",
|
|
311
|
+
"Debounce filter changes — Use a 300ms setTimeout in onFilterModelChange. Reset to page 0 on filter change.",
|
|
312
|
+
"Add bulk action bar — Conditionally render when selectionModel.length > 0.",
|
|
313
|
+
"Handle edge cases — Add loading state, empty state (custom NoRowsOverlay), and error state (conditional render with retry).",
|
|
314
|
+
"Verify — Test page navigation, sort toggling, filter operators, debounced quick search, loading overlay, empty results, and error recovery."
|
|
315
|
+
],
|
|
316
|
+
"variants": [
|
|
317
|
+
{
|
|
318
|
+
"name": "Loading State",
|
|
319
|
+
"slug": "with-loading",
|
|
320
|
+
"description": "Initial loading state before first fetch completes"
|
|
321
|
+
},
|
|
322
|
+
{
|
|
323
|
+
"name": "Empty State",
|
|
324
|
+
"slug": "with-empty-state",
|
|
325
|
+
"description": "Server returns zero results after filtering — shows custom NoRowsOverlay with clear filters button"
|
|
326
|
+
},
|
|
327
|
+
{
|
|
328
|
+
"name": "Error State",
|
|
329
|
+
"slug": "with-error",
|
|
330
|
+
"description": "Fetch rejects with error — shows error banner with retry button"
|
|
331
|
+
}
|
|
332
|
+
],
|
|
333
|
+
"accessibility": [
|
|
334
|
+
"Arrow keys navigate between cells",
|
|
335
|
+
"Page Up / Page Down move between pages",
|
|
336
|
+
"Space toggles checkbox selection on the focused row",
|
|
337
|
+
"Tab moves focus between the toolbar and the grid",
|
|
338
|
+
"Every IconButtonLink in actions column needs aria-label",
|
|
339
|
+
"Loading state should set aria-busy='true' on the container",
|
|
340
|
+
"Error messages should use aria-live='polite' for screen reader announcement",
|
|
341
|
+
"Custom NoRowsOverlay content must be announced to screen readers"
|
|
342
|
+
],
|
|
343
|
+
"relatedPatterns": [
|
|
344
|
+
{
|
|
345
|
+
"slug": "datagrid-page",
|
|
346
|
+
"relationship": "Use when all data can be loaded upfront and filtering/sorting can happen client-side"
|
|
347
|
+
},
|
|
348
|
+
{
|
|
349
|
+
"slug": "drilldown-datagrid-page",
|
|
350
|
+
"relationship": "Use when you want summary DataCards above the grid with one-way filter push"
|
|
351
|
+
},
|
|
352
|
+
{
|
|
353
|
+
"slug": "crossfiltered-datagrid-page",
|
|
354
|
+
"relationship": "Use when DataCard counts should recalculate as filters change (two-way sync)"
|
|
355
|
+
}
|
|
356
|
+
]
|
|
357
|
+
},
|
|
358
|
+
{
|
|
359
|
+
"name": "Drilldown Datagrid Page",
|
|
360
|
+
"slug": "drilldown-datagrid-page",
|
|
361
|
+
"description": "Extends the Datagrid Page with summary DataCards placed above the grid. Each DataCard contains DrilldownItems showing aggregate counts for a field (status, category, active). Clicking a DrilldownItem adds an isAnyOf filter to the DataGrid — a one-click shortcut. This is a one-way interaction: DataCard counts always reflect the full (unfiltered) dataset. When the user sets an is or isNot filter via the filter panel, the DataCard selection clears and clicking a DrilldownItem overwrites with isAnyOf.",
|
|
362
|
+
"components": [
|
|
363
|
+
"DataGrid",
|
|
364
|
+
"TextCell",
|
|
365
|
+
"DataCard",
|
|
366
|
+
"DataCard.Header",
|
|
367
|
+
"DataCard.Body",
|
|
368
|
+
"DataCard.Listbox",
|
|
369
|
+
"DrilldownItem",
|
|
370
|
+
"Pill",
|
|
371
|
+
"Button",
|
|
372
|
+
"Flexbox",
|
|
373
|
+
"Text",
|
|
374
|
+
"Icon",
|
|
375
|
+
"IconButtonLink"
|
|
376
|
+
],
|
|
377
|
+
"packages": ["@redsift/table", "@redsift/design-system", "@redsift/dashboard", "@mui/x-data-grid-pro"],
|
|
378
|
+
"layout": "Flexbox column: DataCard row (Flexbox gap=12px flexWrap=wrap with 1-N DataCards), then DataGrid with autoHeight, pagination, controlled filterModel + onFilterModelChange. Optional bulk actions bar when selectionModel.length > 0.",
|
|
379
|
+
"tags": [
|
|
380
|
+
"table",
|
|
381
|
+
"datagrid",
|
|
382
|
+
"datacard",
|
|
383
|
+
"drilldown",
|
|
384
|
+
"drilldown-item",
|
|
385
|
+
"filter",
|
|
386
|
+
"isAnyOf",
|
|
387
|
+
"summary-cards",
|
|
388
|
+
"kpi",
|
|
389
|
+
"one-way",
|
|
390
|
+
"filterModel",
|
|
391
|
+
"client-side"
|
|
392
|
+
],
|
|
393
|
+
"demoPath": "patterns/drilldown-datagrid-page/example",
|
|
394
|
+
"whenToUse": [
|
|
395
|
+
"You want summary KPI cards above a filterable table",
|
|
396
|
+
"Clicking a card value should add a filter to the datagrid as a convenience shortcut",
|
|
397
|
+
"DataCard counts should always show totals from the full dataset, regardless of active filters",
|
|
398
|
+
"The dataset is small enough to load entirely (under ~1,000 rows)"
|
|
399
|
+
],
|
|
400
|
+
"whenNotToUse": [
|
|
401
|
+
"DataCard counts should recalculate when filters change — use Cross-filtered Datagrid Page instead",
|
|
402
|
+
"No summary cards are needed — use Datagrid Page instead",
|
|
403
|
+
"The dataset is too large to load entirely — combine with Server Datagrid Page patterns"
|
|
404
|
+
],
|
|
405
|
+
"anatomy": [
|
|
406
|
+
"DataCard Row — Flexbox with 1-N DataCards, each containing DataCard.Header and DataCard.Listbox or DataCard.Body with DrilldownItem children",
|
|
407
|
+
"Toolbar — Flexbox wrapping GridToolbarContainer with filter, columns, density, export, quick search controls",
|
|
408
|
+
"DataGrid — the table with controlled filterModel + onFilterModelChange",
|
|
409
|
+
"Bulk Action Bar — Flexbox row shown when selectionModel.length > 0, with Pill (count) and action Buttons"
|
|
410
|
+
],
|
|
411
|
+
"features": [
|
|
412
|
+
{
|
|
413
|
+
"name": "DataCard aggregation",
|
|
414
|
+
"required": true,
|
|
415
|
+
"description": "DataCard components showing aggregate counts per field from the full dataset"
|
|
416
|
+
},
|
|
417
|
+
{
|
|
418
|
+
"name": "DrilldownItem filter push",
|
|
419
|
+
"required": true,
|
|
420
|
+
"description": "Clicking a DrilldownItem adds an isAnyOf filter to the DataGrid filterModel"
|
|
421
|
+
},
|
|
422
|
+
{
|
|
423
|
+
"name": "Listbox multi-select",
|
|
424
|
+
"required": true,
|
|
425
|
+
"description": "DataCard.Listbox with selectionMode=multiple and controlled values for multi-value fields"
|
|
426
|
+
},
|
|
427
|
+
{
|
|
428
|
+
"name": "is/isNot clearing",
|
|
429
|
+
"required": true,
|
|
430
|
+
"description": "When filter panel has is/isNot for a card's field, the DataCard selection clears"
|
|
431
|
+
},
|
|
432
|
+
{
|
|
433
|
+
"name": "Column definitions",
|
|
434
|
+
"required": true,
|
|
435
|
+
"description": "GridColDef[] with custom types: rsString, rsNumber, rsSingleSelect, rsMultipleSelect"
|
|
436
|
+
},
|
|
437
|
+
{
|
|
438
|
+
"name": "Toolbar",
|
|
439
|
+
"required": true,
|
|
440
|
+
"description": "Built-in toolbar with filter, columns, density, export, and quick search controls"
|
|
441
|
+
},
|
|
442
|
+
{
|
|
443
|
+
"name": "Custom cell renderers",
|
|
444
|
+
"required": true,
|
|
445
|
+
"description": "renderCell returning TextCell, Pill, Icon, IconButtonLink"
|
|
446
|
+
},
|
|
447
|
+
{
|
|
448
|
+
"name": "Boolean toggle",
|
|
449
|
+
"required": false,
|
|
450
|
+
"description": "DataCard.Body with DrilldownItem onClick for boolean fields (active/inactive)"
|
|
451
|
+
},
|
|
452
|
+
{
|
|
453
|
+
"name": "Checkbox selection",
|
|
454
|
+
"required": false,
|
|
455
|
+
"description": "checkboxSelection + rowSelectionModel"
|
|
456
|
+
},
|
|
457
|
+
{
|
|
458
|
+
"name": "Bulk action bar",
|
|
459
|
+
"required": false,
|
|
460
|
+
"description": "Contextual buttons shown when rows are selected"
|
|
461
|
+
}
|
|
462
|
+
],
|
|
463
|
+
"stateHooks": [
|
|
464
|
+
{
|
|
465
|
+
"name": "filterModel",
|
|
466
|
+
"type": "GridFilterModel",
|
|
467
|
+
"initial": "{ items: [] }",
|
|
468
|
+
"description": "Controlled filter state shared between DataCards and DataGrid"
|
|
469
|
+
},
|
|
470
|
+
{
|
|
471
|
+
"name": "selectionModel",
|
|
472
|
+
"type": "GridSelectionModel",
|
|
473
|
+
"initial": "[]",
|
|
474
|
+
"description": "Tracks which rows are checked"
|
|
475
|
+
}
|
|
476
|
+
],
|
|
477
|
+
"dataContract": "type Row = {\n id: string;\n label: string;\n active: boolean;\n status: 'active' | 'warning' | 'critical' | 'expired' | 'revoked';\n category: 'primary' | 'secondary' | 'tertiary';\n score: number;\n expiry: string;\n tags: string[];\n};\n\ntype AggregateCounts = {\n status: Record<string, number>;\n category: Record<string, number>;\n activeCount: number;\n inactiveCount: number;\n};",
|
|
478
|
+
"implementationSteps": [
|
|
479
|
+
"Define your row type — Create a TypeScript type Row. Every row must have a unique id field.",
|
|
480
|
+
"Compute aggregate counts — Write a useAggregateCounts(allRows) hook that counts occurrences per field value from the full dataset.",
|
|
481
|
+
"Build DataCards — Create a DataCard for each summarized field with DataCard.Header and DataCard.Listbox or DataCard.Body containing DrilldownItem children.",
|
|
482
|
+
"Write filter helpers — Implement getSelectedFromFilterModel (reads isAnyOf values, returns [] for is/isNot) and updateFilterModel (always writes isAnyOf).",
|
|
483
|
+
"Wire DataCard handlers — Connect DataCard.Listbox onChange to updateFilterModel. For boolean cards, connect DrilldownItem onClick to updateBooleanFilter.",
|
|
484
|
+
"Render the DataGrid — Pass filterModel and onFilterModelChange so the filter panel stays synced with DataCard selections.",
|
|
485
|
+
"Handle edge cases — Add loading, empty, and error states for both DataCards and DataGrid."
|
|
486
|
+
],
|
|
487
|
+
"variants": [
|
|
488
|
+
{
|
|
489
|
+
"name": "Loading State",
|
|
490
|
+
"slug": "with-loading",
|
|
491
|
+
"description": "DataCards with isLoading={true} and DataGrid with loading={true}"
|
|
492
|
+
},
|
|
493
|
+
{
|
|
494
|
+
"name": "Empty State",
|
|
495
|
+
"slug": "with-empty-state",
|
|
496
|
+
"description": "DataCards with zero counts and DataGrid with custom NoRowsOverlay"
|
|
497
|
+
},
|
|
498
|
+
{
|
|
499
|
+
"name": "Error State",
|
|
500
|
+
"slug": "with-error",
|
|
501
|
+
"description": "Error banner above DataCards and DataGrid with retry button"
|
|
502
|
+
}
|
|
503
|
+
],
|
|
504
|
+
"accessibility": [
|
|
505
|
+
"DrilldownItem renders as a button — focusable via Tab, activates with Enter or Space",
|
|
506
|
+
"DataCard.Listbox supports Arrow Up/Down to navigate and Space to toggle selection",
|
|
507
|
+
"Selected DrilldownItems receive aria-selected=true from the Listbox",
|
|
508
|
+
"DataGrid keyboard navigation works unchanged (arrows, Page Up/Down, Space for checkboxes)",
|
|
509
|
+
"Error banners use role=alert and aria-live=polite for screen reader announcement"
|
|
510
|
+
],
|
|
511
|
+
"relatedPatterns": [
|
|
512
|
+
{
|
|
513
|
+
"slug": "crossfiltered-datagrid-page",
|
|
514
|
+
"relationship": "Use when DataCard counts should recalculate as filters change (two-way sync)"
|
|
515
|
+
},
|
|
516
|
+
{
|
|
517
|
+
"slug": "datagrid-page",
|
|
518
|
+
"relationship": "Use when no summary cards are needed"
|
|
519
|
+
},
|
|
520
|
+
{
|
|
521
|
+
"slug": "server-datagrid-page",
|
|
522
|
+
"relationship": "Use when the dataset is too large to load entirely"
|
|
523
|
+
}
|
|
524
|
+
]
|
|
525
|
+
},
|
|
526
|
+
{
|
|
527
|
+
"name": "Cross-filtered Datagrid Page",
|
|
528
|
+
"slug": "crossfiltered-datagrid-page",
|
|
529
|
+
"description": "Extends the Drilldown Datagrid Page with two-way synchronization between DataCards and the DataGrid filter panel. DrilldownItem clicks add isAnyOf filters. Filter panel changes update DataCard selection state. DataCard counts recalculate against the cross-filtered dataset — each card computes counts by applying all filters except its own field, preventing a card from zeroing out its non-selected values. When the user sets is/isNot via the filter panel, the DataCard clears. Clicking a DrilldownItem overwrites with isAnyOf.",
|
|
530
|
+
"components": [
|
|
531
|
+
"DataGrid",
|
|
532
|
+
"TextCell",
|
|
533
|
+
"DataCard",
|
|
534
|
+
"DataCard.Header",
|
|
535
|
+
"DataCard.Body",
|
|
536
|
+
"DataCard.Listbox",
|
|
537
|
+
"DrilldownItem",
|
|
538
|
+
"Pill",
|
|
539
|
+
"Button",
|
|
540
|
+
"Flexbox",
|
|
541
|
+
"Text",
|
|
542
|
+
"Icon",
|
|
543
|
+
"IconButtonLink"
|
|
544
|
+
],
|
|
545
|
+
"packages": ["@redsift/table", "@redsift/design-system", "@redsift/dashboard", "@mui/x-data-grid-pro"],
|
|
546
|
+
"layout": "Flexbox column: DataCard row (cross-filtered counts), then DataGrid with autoHeight, pagination, controlled filterModel + onFilterModelChange. Rows are pre-filtered client-side via applyFilters. Optional bulk actions bar.",
|
|
547
|
+
"tags": [
|
|
548
|
+
"table",
|
|
549
|
+
"datagrid",
|
|
550
|
+
"datacard",
|
|
551
|
+
"drilldown",
|
|
552
|
+
"drilldown-item",
|
|
553
|
+
"cross-filter",
|
|
554
|
+
"crossfilter",
|
|
555
|
+
"two-way",
|
|
556
|
+
"bidirectional",
|
|
557
|
+
"filter",
|
|
558
|
+
"isAnyOf",
|
|
559
|
+
"summary-cards",
|
|
560
|
+
"kpi",
|
|
561
|
+
"dashboard",
|
|
562
|
+
"filterModel",
|
|
563
|
+
"client-side"
|
|
564
|
+
],
|
|
565
|
+
"demoPath": "patterns/crossfiltered-datagrid-page/example",
|
|
566
|
+
"whenToUse": [
|
|
567
|
+
"You want dashboard-style KPI cards that stay in sync with the table below",
|
|
568
|
+
"DataCard counts should recalculate as filters change — reflecting the current filter context",
|
|
569
|
+
"Clicking a card value should add a filter to the datagrid",
|
|
570
|
+
"Changing the filter panel should update the card selection (bidirectional)",
|
|
571
|
+
"The dataset is small enough to load entirely (under ~1,000 rows)"
|
|
572
|
+
],
|
|
573
|
+
"whenNotToUse": [
|
|
574
|
+
"DataCard counts should always show full-dataset totals — use Drilldown Datagrid Page instead",
|
|
575
|
+
"No summary cards are needed — use Datagrid Page instead",
|
|
576
|
+
"The dataset is too large to load entirely — combine with Server Datagrid Page patterns"
|
|
577
|
+
],
|
|
578
|
+
"anatomy": [
|
|
579
|
+
"DataCard Row — Flexbox with 1-N DataCards. Counts are cross-filtered: each card excludes its own field from the filter calculation",
|
|
580
|
+
"Toolbar — Flexbox wrapping GridToolbarContainer with filter, columns, density, export, quick search controls",
|
|
581
|
+
"DataGrid — the table with controlled filterModel + onFilterModelChange. Rows are pre-filtered client-side",
|
|
582
|
+
"Bulk Action Bar — Flexbox row shown when selectionModel.length > 0, with Pill (count) and action Buttons"
|
|
583
|
+
],
|
|
584
|
+
"features": [
|
|
585
|
+
{
|
|
586
|
+
"name": "Cross-filtered aggregation",
|
|
587
|
+
"required": true,
|
|
588
|
+
"description": "DataCard counts recompute from rows filtered by all fields except the card's own field"
|
|
589
|
+
},
|
|
590
|
+
{
|
|
591
|
+
"name": "Two-way filter sync",
|
|
592
|
+
"required": true,
|
|
593
|
+
"description": "DataCard selections derive from filterModel; DataCard clicks update filterModel"
|
|
594
|
+
},
|
|
595
|
+
{
|
|
596
|
+
"name": "DrilldownItem filter push",
|
|
597
|
+
"required": true,
|
|
598
|
+
"description": "Clicking a DrilldownItem adds an isAnyOf filter to the DataGrid filterModel"
|
|
599
|
+
},
|
|
600
|
+
{
|
|
601
|
+
"name": "Listbox multi-select",
|
|
602
|
+
"required": true,
|
|
603
|
+
"description": "DataCard.Listbox with selectionMode=multiple and controlled values for multi-value fields"
|
|
604
|
+
},
|
|
605
|
+
{
|
|
606
|
+
"name": "is/isNot clearing",
|
|
607
|
+
"required": true,
|
|
608
|
+
"description": "When filter panel has is/isNot for a card's field, the DataCard selection clears"
|
|
609
|
+
},
|
|
610
|
+
{
|
|
611
|
+
"name": "Client-side row filtering",
|
|
612
|
+
"required": true,
|
|
613
|
+
"description": "applyFilters function filters the full row set by the current filterModel"
|
|
614
|
+
},
|
|
615
|
+
{
|
|
616
|
+
"name": "Column definitions",
|
|
617
|
+
"required": true,
|
|
618
|
+
"description": "GridColDef[] with custom types: rsString, rsNumber, rsSingleSelect, rsMultipleSelect"
|
|
619
|
+
},
|
|
620
|
+
{
|
|
621
|
+
"name": "Toolbar",
|
|
622
|
+
"required": true,
|
|
623
|
+
"description": "Built-in toolbar with filter, columns, density, export, and quick search controls"
|
|
624
|
+
},
|
|
625
|
+
{
|
|
626
|
+
"name": "Custom cell renderers",
|
|
627
|
+
"required": true,
|
|
628
|
+
"description": "renderCell returning TextCell, Pill, Icon, IconButtonLink"
|
|
629
|
+
},
|
|
630
|
+
{
|
|
631
|
+
"name": "Boolean toggle",
|
|
632
|
+
"required": false,
|
|
633
|
+
"description": "DataCard.Body with DrilldownItem onClick for boolean fields (active/inactive)"
|
|
634
|
+
},
|
|
635
|
+
{
|
|
636
|
+
"name": "Checkbox selection",
|
|
637
|
+
"required": false,
|
|
638
|
+
"description": "checkboxSelection + rowSelectionModel"
|
|
639
|
+
},
|
|
640
|
+
{
|
|
641
|
+
"name": "Bulk action bar",
|
|
642
|
+
"required": false,
|
|
643
|
+
"description": "Contextual buttons shown when rows are selected"
|
|
644
|
+
}
|
|
645
|
+
],
|
|
646
|
+
"stateHooks": [
|
|
647
|
+
{
|
|
648
|
+
"name": "filterModel",
|
|
649
|
+
"type": "GridFilterModel",
|
|
650
|
+
"initial": "{ items: [] }",
|
|
651
|
+
"description": "Controlled filter state — single source of truth shared between DataCards and DataGrid"
|
|
652
|
+
},
|
|
653
|
+
{
|
|
654
|
+
"name": "selectionModel",
|
|
655
|
+
"type": "GridSelectionModel",
|
|
656
|
+
"initial": "[]",
|
|
657
|
+
"description": "Tracks which rows are checked"
|
|
658
|
+
}
|
|
659
|
+
],
|
|
660
|
+
"dataContract": "type Row = {\n id: string;\n label: string;\n active: boolean;\n status: 'active' | 'warning' | 'critical' | 'expired' | 'revoked';\n category: 'primary' | 'secondary' | 'tertiary';\n score: number;\n expiry: string;\n tags: string[];\n};\n\ntype AggregateCounts = {\n status: Record<string, number>;\n category: Record<string, number>;\n activeCount: number;\n inactiveCount: number;\n};",
|
|
661
|
+
"implementationSteps": [
|
|
662
|
+
"Define your row type — Create a TypeScript type Row. Every row must have a unique id field.",
|
|
663
|
+
"Write the applyFilters function — Accepts (rows, filterModel, excludeField?). Supports isAnyOf, is, isNot operators. When excludeField is provided, skips filters for that field.",
|
|
664
|
+
"Write computeCounts — Accepts a row array and returns aggregate counts per field value.",
|
|
665
|
+
"Write filter helpers — Implement getSelectedFromFilterModel (reads isAnyOf values, returns [] for is/isNot) and updateFilterModel (always writes isAnyOf).",
|
|
666
|
+
"Compute cross-filtered counts — For each DataCard, call computeCounts(applyFilters(allRows, filterModel, cardField)).",
|
|
667
|
+
"Compute filtered rows for DataGrid — Call applyFilters(allRows, filterModel) without excluding any field.",
|
|
668
|
+
"Build DataCards — Create a DataCard for each field with DataCard.Listbox (multi-select with controlled values) or DataCard.Body (boolean toggle). Wire onChange/onClick to updateFilterModel/updateBooleanFilter.",
|
|
669
|
+
"Render the DataGrid — Pass rows={filteredRows}, filterModel, and onFilterModelChange={setFilterModel}.",
|
|
670
|
+
"Handle edge cases — Add loading, empty, and error states for both DataCards and DataGrid."
|
|
671
|
+
],
|
|
672
|
+
"variants": [
|
|
673
|
+
{
|
|
674
|
+
"name": "Loading State",
|
|
675
|
+
"slug": "with-loading",
|
|
676
|
+
"description": "DataCards with isLoading={true} and DataGrid with loading={true}"
|
|
677
|
+
},
|
|
678
|
+
{
|
|
679
|
+
"name": "Empty State",
|
|
680
|
+
"slug": "with-empty-state",
|
|
681
|
+
"description": "DataCards with zero counts and DataGrid with custom NoRowsOverlay"
|
|
682
|
+
},
|
|
683
|
+
{
|
|
684
|
+
"name": "Error State",
|
|
685
|
+
"slug": "with-error",
|
|
686
|
+
"description": "Error banner above DataCards and DataGrid with retry button"
|
|
687
|
+
}
|
|
688
|
+
],
|
|
689
|
+
"accessibility": [
|
|
690
|
+
"DrilldownItem renders as a button — focusable via Tab, activates with Enter or Space",
|
|
691
|
+
"DataCard.Listbox supports Arrow Up/Down to navigate and Space to toggle selection",
|
|
692
|
+
"Selected DrilldownItems receive aria-selected=true from the Listbox",
|
|
693
|
+
"DataGrid keyboard navigation works unchanged (arrows, Page Up/Down, Space for checkboxes)",
|
|
694
|
+
"Error banners use role=alert and aria-live=polite for screen reader announcement",
|
|
695
|
+
"As counts update in real-time, screen readers can query the updated values"
|
|
696
|
+
],
|
|
697
|
+
"relatedPatterns": [
|
|
698
|
+
{
|
|
699
|
+
"slug": "drilldown-datagrid-page",
|
|
700
|
+
"relationship": "Use when DataCard counts should always show full-dataset totals (one-way)"
|
|
701
|
+
},
|
|
702
|
+
{
|
|
703
|
+
"slug": "datagrid-page",
|
|
704
|
+
"relationship": "Use when no summary cards are needed"
|
|
705
|
+
},
|
|
706
|
+
{
|
|
707
|
+
"slug": "server-datagrid-page",
|
|
708
|
+
"relationship": "Use when the dataset is too large to load entirely"
|
|
709
|
+
}
|
|
710
|
+
]
|
|
711
|
+
}
|
|
712
|
+
]
|