@redsift/ds-mcp-server 12.5.3-alpha.6 → 12.5.3-alpha.7

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.
Files changed (81) hide show
  1. package/consumer-instructions/redsift-design-system.instructions.md +82 -1
  2. package/data/docs/components/charts/Axis.json +6 -1
  3. package/data/docs/components/charts/BarChart.json +7 -1
  4. package/data/docs/components/charts/ChartContainerTitle.json +5 -1
  5. package/data/docs/components/charts/Legend.json +6 -1
  6. package/data/docs/components/charts/LineChart.json +7 -1
  7. package/data/docs/components/charts/PieChart.json +6 -1
  8. package/data/docs/components/charts/ScatterPlot.json +6 -1
  9. package/data/docs/components/dashboard/ChartEmptyState.json +8 -1
  10. package/data/docs/components/dashboard/Dashboard.json +6 -1
  11. package/data/docs/components/dashboard/DataCard.json +12 -0
  12. package/data/docs/components/dashboard/DataCardBody.json +4 -0
  13. package/data/docs/components/dashboard/DataCardHeader.json +4 -0
  14. package/data/docs/components/dashboard/DataCardListbox.json +5 -0
  15. package/data/docs/components/dashboard/DataRow.json +7 -1
  16. package/data/docs/components/dashboard/PdfExportButton.json +6 -1
  17. package/data/docs/components/dashboard/TimeSeriesBarChart.json +6 -1
  18. package/data/docs/components/dashboard/WithFilters.json +5 -1
  19. package/data/docs/components/design-system/Alert.json +8 -1
  20. package/data/docs/components/design-system/AppBar.json +6 -1
  21. package/data/docs/components/design-system/AppContent.json +4 -0
  22. package/data/docs/components/design-system/AppSidePanel.json +5 -0
  23. package/data/docs/components/design-system/Badge.json +6 -1
  24. package/data/docs/components/design-system/Breadcrumbs.json +4 -0
  25. package/data/docs/components/design-system/Button.json +5 -0
  26. package/data/docs/components/design-system/Card.json +9 -0
  27. package/data/docs/components/design-system/CardActions.json +4 -0
  28. package/data/docs/components/design-system/CardBody.json +3 -0
  29. package/data/docs/components/design-system/CardHeader.json +4 -0
  30. package/data/docs/components/design-system/DetailedCard.json +6 -0
  31. package/data/docs/components/design-system/Flexbox.json +14 -1
  32. package/data/docs/components/design-system/Grid.json +6 -1
  33. package/data/docs/components/design-system/Heading.json +11 -0
  34. package/data/docs/components/design-system/Icon.json +6 -1
  35. package/data/docs/components/design-system/IconButton.json +9 -0
  36. package/data/docs/components/design-system/Pill.json +10 -0
  37. package/data/docs/components/design-system/Skeleton.json +10 -1
  38. package/data/docs/components/design-system/SkeletonCircle.json +6 -1
  39. package/data/docs/components/design-system/SkeletonText.json +6 -1
  40. package/data/docs/components/design-system/Tab.json +4 -0
  41. package/data/docs/components/design-system/TabPanel.json +4 -0
  42. package/data/docs/components/design-system/Tabs.json +6 -0
  43. package/data/docs/components/design-system/Text.json +9 -0
  44. package/data/docs/components/design-system/TextField.json +6 -1
  45. package/data/docs/components/pickers/Combobox.json +6 -0
  46. package/data/docs/components/pickers/MenuButton.json +5 -0
  47. package/data/docs/components/pickers/Select.json +5 -0
  48. package/data/docs/components/popovers/Dialog.json +6 -0
  49. package/data/docs/components/popovers/Toggletip.json +5 -0
  50. package/data/docs/components/popovers/Tooltip.json +4 -0
  51. package/data/docs/components/table/DataGrid.json +9 -1
  52. package/data/docs/components/table/StatefulDataGrid.json +6 -1
  53. package/data/docs/components-index.json +341 -51
  54. package/data/docs/components.json +2 -2
  55. package/data/docs/llms-full.txt +248 -1
  56. package/data/docs/llms.txt +50 -0
  57. package/data/docs/patterns-catalog.md +191 -0
  58. package/data/docs/patterns.json +365 -27
  59. package/data/metadata.json +2 -2
  60. package/data/prompts/ds-advisor.md +103 -0
  61. package/dist/data-store.d.ts +21 -1
  62. package/dist/data-store.d.ts.map +1 -1
  63. package/dist/data-store.js +65 -15
  64. package/dist/data-store.js.map +1 -1
  65. package/dist/pattern-store.d.ts +18 -1
  66. package/dist/pattern-store.d.ts.map +1 -1
  67. package/dist/pattern-store.js +64 -22
  68. package/dist/pattern-store.js.map +1 -1
  69. package/dist/prompts.d.ts.map +1 -1
  70. package/dist/prompts.js +56 -27
  71. package/dist/prompts.js.map +1 -1
  72. package/dist/resources.d.ts.map +1 -1
  73. package/dist/resources.js +26 -0
  74. package/dist/resources.js.map +1 -1
  75. package/dist/tools.d.ts.map +1 -1
  76. package/dist/tools.js +12 -0
  77. package/dist/tools.js.map +1 -1
  78. package/dist/types.d.ts +11 -0
  79. package/dist/types.d.ts.map +1 -1
  80. package/dist/types.js.map +1 -1
  81. package/package.json +4 -2
@@ -64,8 +64,16 @@
64
64
  "required": true,
65
65
  "description": "Client-side pagination with configurable page size (rowsPerPageOptions)"
66
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)" },
67
+ {
68
+ "name": "Sorting",
69
+ "required": true,
70
+ "description": "Client-side column sorting (built into DataGrid)"
71
+ },
72
+ {
73
+ "name": "Filtering",
74
+ "required": true,
75
+ "description": "Client-side column filtering (built into DataGrid)"
76
+ },
69
77
  {
70
78
  "name": "Custom cell renderers",
71
79
  "required": true,
@@ -149,6 +157,12 @@
149
157
  "slug": "crossfiltered-datagrid-page",
150
158
  "relationship": "Use when DataCard counts should recalculate as filters change (two-way sync)"
151
159
  }
160
+ ],
161
+ "keywords": ["data table", "table page", "grid page", "filterable table", "sortable table", "list view"],
162
+ "commonMistakes": [
163
+ "❌ Wrapping <DataGrid /> in <Card> → ✅ render <DataGrid /> at the page level. The DataGrid already paints its own surface, padding, and toolbar — nesting it in a Card breaks the toolbar layout and the autoHeight calculation.",
164
+ "❌ Setting hasPagination={true} thinking pagination is opt-in → ✅ pagination is on by default. Only pass hasPagination={false} when you explicitly want a non-paginated grid (rare).",
165
+ "❌ Stacking multiple <Pill>s in a status cell with margins or inline styles → ✅ wrap them in <Flexbox gap=\"4px\" alignItems=\"center\">. Renders consistent spacing and inherits cell alignment."
152
166
  ]
153
167
  },
154
168
  {
@@ -219,7 +233,11 @@
219
233
  "required": true,
220
234
  "description": "filterMode='server' with controlled filterModel + onFilterModelChange"
221
235
  },
222
- { "name": "Loading overlay", "required": true, "description": "loading prop set to true during fetches" },
236
+ {
237
+ "name": "Loading overlay",
238
+ "required": true,
239
+ "description": "loading prop set to true during fetches"
240
+ },
223
241
  {
224
242
  "name": "Row count",
225
243
  "required": true,
@@ -245,7 +263,11 @@
245
263
  "required": true,
246
264
  "description": "renderCell returning TextCell, Pill, Icon, IconButtonLink"
247
265
  },
248
- { "name": "Checkbox selection", "required": false, "description": "checkboxSelection + rowSelectionModel" },
266
+ {
267
+ "name": "Checkbox selection",
268
+ "required": false,
269
+ "description": "checkboxSelection + rowSelectionModel"
270
+ },
249
271
  {
250
272
  "name": "Bulk action bar",
251
273
  "required": false,
@@ -270,10 +292,30 @@
270
292
  "initial": "0",
271
293
  "description": "Total matching records (for pagination)"
272
294
  },
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" },
295
+ {
296
+ "name": "loading",
297
+ "type": "boolean",
298
+ "initial": "true",
299
+ "description": "Whether a fetch is in progress"
300
+ },
301
+ {
302
+ "name": "page",
303
+ "type": "number",
304
+ "initial": "0",
305
+ "description": "0-based current page index"
306
+ },
307
+ {
308
+ "name": "pageSize",
309
+ "type": "number",
310
+ "initial": "10",
311
+ "description": "Number of rows per page"
312
+ },
313
+ {
314
+ "name": "sortModel",
315
+ "type": "GridSortModel",
316
+ "initial": "[]",
317
+ "description": "Current sort configuration"
318
+ },
277
319
  {
278
320
  "name": "filterModel",
279
321
  "type": "GridFilterModel",
@@ -353,7 +395,8 @@
353
395
  "slug": "crossfiltered-datagrid-page",
354
396
  "relationship": "Use when DataCard counts should recalculate as filters change (two-way sync)"
355
397
  }
356
- ]
398
+ ],
399
+ "keywords": ["server table", "paginated table", "api table", "remote data grid", "lazy table"]
357
400
  },
358
401
  {
359
402
  "name": "Stateful Datagrid Page (Client)",
@@ -390,7 +433,8 @@
390
433
  "slug": "stateful-single-datagrid-server-side",
391
434
  "relationship": "Use when the dataset is too large to load entirely, with URL state persistence"
392
435
  }
393
- ]
436
+ ],
437
+ "keywords": ["persistent table", "url state table", "bookmarkable table"]
394
438
  },
395
439
  {
396
440
  "name": "Stateful Datagrid Page (Server)",
@@ -427,7 +471,8 @@
427
471
  "slug": "stateful-single-datagrid-client-side",
428
472
  "relationship": "Use when the dataset fits in the browser, with URL state persistence"
429
473
  }
430
- ]
474
+ ],
475
+ "keywords": ["persistent server table", "url state server table"]
431
476
  },
432
477
  {
433
478
  "name": "Drilldown Datagrid Page",
@@ -595,7 +640,8 @@
595
640
  "slug": "server-datagrid-page",
596
641
  "relationship": "Use when the dataset is too large to load entirely"
597
642
  }
598
- ]
643
+ ],
644
+ "keywords": ["kpi cards above table", "summary cards", "drilldown", "detail drill", "card-to-table"]
599
645
  },
600
646
  {
601
647
  "name": "Cross-filtered Datagrid Page",
@@ -781,6 +827,13 @@
781
827
  "slug": "server-datagrid-page",
782
828
  "relationship": "Use when the dataset is too large to load entirely"
783
829
  }
830
+ ],
831
+ "keywords": [
832
+ "interactive dashboard",
833
+ "filterable dashboard",
834
+ "crossfilter",
835
+ "bi-directional filter",
836
+ "dashboard with table"
784
837
  ]
785
838
  },
786
839
  {
@@ -807,10 +860,20 @@
807
860
  "DataGrid — server-side table with paginationMode='server', sortingMode='server', filterMode='server'"
808
861
  ],
809
862
  "relatedPatterns": [
810
- { "slug": "server-crossfiltered-datagrid-page", "relationship": "Use when card counts should recalculate" },
811
- { "slug": "drilldown-datagrid-page", "relationship": "Client-side version with the same UX" },
812
- { "slug": "server-datagrid-page", "relationship": "Use when no summary cards are needed" }
813
- ]
863
+ {
864
+ "slug": "server-crossfiltered-datagrid-page",
865
+ "relationship": "Use when card counts should recalculate"
866
+ },
867
+ {
868
+ "slug": "drilldown-datagrid-page",
869
+ "relationship": "Client-side version with the same UX"
870
+ },
871
+ {
872
+ "slug": "server-datagrid-page",
873
+ "relationship": "Use when no summary cards are needed"
874
+ }
875
+ ],
876
+ "keywords": ["server drilldown", "server kpi cards", "aggregated drill"]
814
877
  },
815
878
  {
816
879
  "name": "Server Cross-filtered Datagrid Page",
@@ -836,10 +899,20 @@
836
899
  "DataGrid — server-side table with controlled filterModel"
837
900
  ],
838
901
  "relatedPatterns": [
839
- { "slug": "server-drilldown-datagrid-page", "relationship": "Use when card counts should stay fixed" },
840
- { "slug": "crossfiltered-datagrid-page", "relationship": "Client-side version using crossfilter.js" },
841
- { "slug": "server-datagrid-page", "relationship": "Use when no summary cards are needed" }
842
- ]
902
+ {
903
+ "slug": "server-drilldown-datagrid-page",
904
+ "relationship": "Use when card counts should stay fixed"
905
+ },
906
+ {
907
+ "slug": "crossfiltered-datagrid-page",
908
+ "relationship": "Client-side version using crossfilter.js"
909
+ },
910
+ {
911
+ "slug": "server-datagrid-page",
912
+ "relationship": "Use when no summary cards are needed"
913
+ }
914
+ ],
915
+ "keywords": ["server crossfilter", "server interactive dashboard"]
843
916
  },
844
917
  {
845
918
  "name": "Tabbed Datagrid Page",
@@ -864,9 +937,16 @@
864
937
  "DataGrid — client-side table filtered to the active tab's category"
865
938
  ],
866
939
  "relatedPatterns": [
867
- { "slug": "server-tabbed-datagrid-page", "relationship": "Server-side version for large datasets" },
868
- { "slug": "drilldown-datagrid-page", "relationship": "Use DataCards instead of Tabs for multi-value filtering" }
869
- ]
940
+ {
941
+ "slug": "server-tabbed-datagrid-page",
942
+ "relationship": "Server-side version for large datasets"
943
+ },
944
+ {
945
+ "slug": "drilldown-datagrid-page",
946
+ "relationship": "Use DataCards instead of Tabs for multi-value filtering"
947
+ }
948
+ ],
949
+ "keywords": ["category tabs", "segmented table", "tab bar above table", "tabbed list"]
870
950
  },
871
951
  {
872
952
  "name": "Server Tabbed Datagrid Page",
@@ -890,7 +970,10 @@
890
970
  "DataGrid — server-side table with paginationMode='server', sortingMode='server', filterMode='server'"
891
971
  ],
892
972
  "relatedPatterns": [
893
- { "slug": "tabbed-datagrid-page", "relationship": "Client-side version for smaller datasets" },
973
+ {
974
+ "slug": "tabbed-datagrid-page",
975
+ "relationship": "Client-side version for smaller datasets"
976
+ },
894
977
  {
895
978
  "slug": "server-drilldown-datagrid-page",
896
979
  "relationship": "Use DataCards instead of Tabs for multi-value filtering"
@@ -899,7 +982,8 @@
899
982
  "slug": "server-crossfiltered-datagrid-page",
900
983
  "relationship": "Multi-dimensional cross-filtering with DataCards"
901
984
  }
902
- ]
985
+ ],
986
+ "keywords": ["server tabbed table", "server category tabs"]
903
987
  },
904
988
  {
905
989
  "name": "Summary Dashboard",
@@ -953,12 +1037,266 @@
953
1037
  }
954
1038
  },
955
1039
  "relatedPatterns": [
956
- { "slug": "drilldown-datagrid-page", "relationship": "The detail page a summary dashboard typically links to" },
1040
+ {
1041
+ "slug": "drilldown-datagrid-page",
1042
+ "relationship": "The detail page a summary dashboard typically links to"
1043
+ },
957
1044
  {
958
1045
  "slug": "crossfiltered-datagrid-page",
959
1046
  "relationship": "Interactive version with cross-filtering and a DataGrid"
960
1047
  },
961
- { "slug": "server-crossfiltered-datagrid-page", "relationship": "Server-driven interactive dashboard" }
1048
+ {
1049
+ "slug": "server-crossfiltered-datagrid-page",
1050
+ "relationship": "Server-driven interactive dashboard"
1051
+ }
1052
+ ],
1053
+ "keywords": [
1054
+ "overview page",
1055
+ "kpi dashboard",
1056
+ "landing page",
1057
+ "metric tiles",
1058
+ "summary tiles",
1059
+ "kpi cards above charts",
1060
+ "dashboard overview",
1061
+ "executive summary"
1062
+ ]
1063
+ },
1064
+ {
1065
+ "name": "KPI Cards Above Charts",
1066
+ "slug": "kpi-cards-above-charts",
1067
+ "description": "A row of metric tiles (DataCards) followed by one or two chart tiles, forming a dashboard overview page. Each DataCard shows a key metric; charts visualize trends or distributions. Users scan KPIs then drill into charts. This is the standard layout for 'Overview' pages across Red Sift products.",
1068
+ "components": [
1069
+ "DataCard",
1070
+ "DataCardHeader",
1071
+ "DataCardBody",
1072
+ "DataRow",
1073
+ "BarChart",
1074
+ "PieChart",
1075
+ "ChartContainer",
1076
+ "Flexbox",
1077
+ "Heading",
1078
+ "Text",
1079
+ "Skeleton"
1080
+ ],
1081
+ "packages": ["@redsift/dashboard", "@redsift/charts", "@redsift/design-system"],
1082
+ "layout": "Flexbox column: top row = Flexbox row wrapping DataCards (flex: 1 each), bottom row = Flexbox row with one or two chart containers. Each DataCard has DataCardHeader + DataCardBody with DataRow children.",
1083
+ "tags": ["dashboard", "kpi", "metric", "chart", "overview", "summary", "tiles", "landing-page"],
1084
+ "keywords": [
1085
+ "kpi cards above charts",
1086
+ "overview page",
1087
+ "metric tiles with charts",
1088
+ "summary dashboard",
1089
+ "executive dashboard",
1090
+ "kpi row",
1091
+ "stat cards",
1092
+ "dashboard landing"
1093
+ ],
1094
+ "whenToUse": [
1095
+ "Building an overview or landing page that shows key metrics at a glance",
1096
+ "Users need to see aggregate KPIs and trend charts without interactive filtering",
1097
+ "The page is read-only — clicking a DataRow navigates to a detail page",
1098
+ "You want a standard two-row layout: metrics on top, charts below"
1099
+ ],
1100
+ "whenNotToUse": [
1101
+ "Users need to cross-filter between cards and a DataGrid — use Crossfiltered Datagrid Page instead",
1102
+ "The page is primarily a table with summary KPIs — use Drilldown Datagrid Page instead",
1103
+ "Only charts, no KPI tiles — use a simple Flexbox of ChartContainers"
1104
+ ],
1105
+ "anatomy": [
1106
+ "Heading — Page title",
1107
+ "KPI Row — Flexbox row of DataCards, each with DataCardHeader and DataCardBody containing DataRow items",
1108
+ "Chart Row — Flexbox row of chart containers (BarChart, PieChart, etc.) wrapped in styled containers with titles"
1109
+ ]
1110
+ },
1111
+ {
1112
+ "name": "Chart Empty State",
1113
+ "slug": "chart-empty-state",
1114
+ "description": "How to render loading, empty, and error states inside a DataCard or ChartContainer. Uses ChartEmptyState from @redsift/dashboard for consistent empty/error messaging, Skeleton for loading shimmer, and Alert + Button for error-with-retry.",
1115
+ "components": [
1116
+ "ChartEmptyState",
1117
+ "DataCard",
1118
+ "DataCardHeader",
1119
+ "DataCardBody",
1120
+ "Skeleton",
1121
+ "Alert",
1122
+ "Button",
1123
+ "Text"
1124
+ ],
1125
+ "packages": ["@redsift/dashboard", "@redsift/design-system"],
1126
+ "layout": "DataCard with conditional content: loading (Skeleton), empty (ChartEmptyState), error (Alert + Button), or success (chart content).",
1127
+ "tags": ["empty-state", "loading", "error", "skeleton", "chart", "dashboard", "retry"],
1128
+ "keywords": [
1129
+ "chart loading",
1130
+ "chart empty",
1131
+ "chart error",
1132
+ "no data chart",
1133
+ "loading state",
1134
+ "empty chart state",
1135
+ "error banner",
1136
+ "retry button",
1137
+ "chart placeholder"
1138
+ ],
1139
+ "whenToUse": [
1140
+ "A chart or DataCard needs to show loading, empty, or error states",
1141
+ "You want a consistent look across all chart tiles for non-happy-path states",
1142
+ "The error state should include a retry action"
1143
+ ],
1144
+ "whenNotToUse": [
1145
+ "The component is a DataGrid — DataGrid has its own built-in loading/empty/error overlays",
1146
+ "You only need a full-page loading spinner — use Spinner instead"
1147
+ ],
1148
+ "anatomy": [
1149
+ "DataCard — Container for the chart tile",
1150
+ "DataCardHeader — Title of the chart",
1151
+ "DataCardBody — Conditional content based on state",
1152
+ "Loading: Skeleton components matching the chart shape",
1153
+ "Empty: ChartEmptyState with a message and optional illustration",
1154
+ "Error: Alert variant='error' + Button variant='secondary' for retry"
1155
+ ]
1156
+ },
1157
+ {
1158
+ "name": "Error Banner with Retry",
1159
+ "slug": "error-banner-with-retry",
1160
+ "description": "A section-level error display with a retry button, replacing hand-rolled styled.button and hex colors. Uses Alert from @redsift/design-system for the error message and Button variant='secondary' for the retry action. Never use styled.button or hardcoded rgba() values for this pattern.",
1161
+ "components": ["Alert", "Button", "Flexbox", "Text"],
1162
+ "packages": ["@redsift/design-system"],
1163
+ "layout": "Flexbox column with Alert at top and optional Button below, or Alert with action prop containing the retry Button.",
1164
+ "tags": ["error", "retry", "alert", "banner", "notification", "failure"],
1165
+ "keywords": [
1166
+ "error banner",
1167
+ "retry button",
1168
+ "error message",
1169
+ "section error",
1170
+ "failed to load",
1171
+ "try again",
1172
+ "error state"
1173
+ ],
1174
+ "whenToUse": [
1175
+ "A section of the page failed to load and the user can retry",
1176
+ "You need an inline error message with an action",
1177
+ "Replacing a hand-rolled error banner with hardcoded styles"
1178
+ ],
1179
+ "whenNotToUse": [
1180
+ "The entire page failed — use a full-page error boundary instead",
1181
+ "The error is inside a chart tile — use Chart Empty State pattern instead"
1182
+ ],
1183
+ "anatomy": [
1184
+ "Alert — Displays the error message with severity='error'",
1185
+ "Button — 'Retry' button with variant='secondary' and onClick handler"
1186
+ ]
1187
+ },
1188
+ {
1189
+ "name": "Host App Page Registration",
1190
+ "slug": "host-app-page-registration",
1191
+ "description": "Abstract contract for adding a new page to a Red Sift host application. Every new page requires a routing entry, a navigation entry in the sidebar, and a page title registered as an i18n key in ALL supported locales. Missing any locale mirror causes the page title to show as a raw key string. This is a framework pattern — concrete implementation depends on the host app's router and i18n system.",
1192
+ "components": ["AppContainer", "AppSidePanel", "AppBar", "AppContent"],
1193
+ "packages": ["@redsift/design-system"],
1194
+ "layout": "AppContainer > AppSidePanel (nav entry) + AppContent (routed page component). AppBar displays the page title from i18n.",
1195
+ "tags": ["host-app", "page", "routing", "navigation", "i18n", "locale", "title", "setup"],
1196
+ "keywords": [
1197
+ "page registration",
1198
+ "add page",
1199
+ "new page",
1200
+ "route setup",
1201
+ "navigation entry",
1202
+ "page title",
1203
+ "i18n key",
1204
+ "locale mirror",
1205
+ "host app contract",
1206
+ "app shell setup"
1207
+ ],
1208
+ "whenToUse": [
1209
+ "Adding a new page or view to a Red Sift application",
1210
+ "The page needs a sidebar navigation entry",
1211
+ "The page title must be translated across all supported locales"
1212
+ ],
1213
+ "whenNotToUse": [
1214
+ "Rendering a modal or dialog — no route needed",
1215
+ "A sub-tab within an existing page — handled by the page's Tabs component"
1216
+ ],
1217
+ "anatomy": [
1218
+ "Route definition — maps a URL path to a page component",
1219
+ "Navigation entry — adds an item to AppSidePanel with icon, label i18n key, and route path",
1220
+ "Page title i18n key — registered in EVERY locale file (e.g. en-US.json, fr-FR.json). If any locale is missing the key, the title renders as the raw key string.",
1221
+ "Page component — wrapped in AppContent, receives route params"
1222
+ ],
1223
+ "implementationSteps": [
1224
+ "Define the route path and page component in the app's router configuration",
1225
+ "Add a navigation entry to AppSidePanel with the route path and an i18n label key",
1226
+ "Register the page title i18n key in ALL locale files (en-US, fr-FR, etc.)",
1227
+ "Verify the title renders correctly by switching locales",
1228
+ "Import @redsift/design-system/style/index.css at the app entry if not already done"
1229
+ ]
1230
+ },
1231
+ {
1232
+ "name": "Category Tabs Above Table",
1233
+ "slug": "category-tabs-above-table",
1234
+ "description": "A row of Tabs above a DataGrid that filter the grid's rows by a category (e.g. All / Active / Expired / Critical). The selected tab becomes part of the grid's filterModel. Use this pattern when you have a small, well-known set of mutually exclusive row categories — it is a UX shortcut for the most common filter on the page. For arbitrary or many-valued filters, use the DataGrid's built-in column filter UI instead.",
1235
+ "components": ["Tabs", "Tab", "TabPanel", "DataGrid", "Pill", "Flexbox"],
1236
+ "packages": ["@redsift/design-system", "@redsift/table"],
1237
+ "layout": "Flexbox column: Tabs row + DataGrid below. Tabs are sticky-positioned above the grid; the active Tab drives a filterModel applied to the DataGrid.",
1238
+ "tags": ["tabs", "datagrid", "filter", "category", "status-filter", "segmented-control"],
1239
+ "keywords": [
1240
+ "category tabs above table",
1241
+ "tabs above grid",
1242
+ "status tabs",
1243
+ "tabbed datagrid",
1244
+ "filter tabs",
1245
+ "segmented filter"
1246
+ ],
1247
+ "whenToUse": [
1248
+ "You have a fixed, small set of mutually exclusive row categories (typically 2–6 tabs)",
1249
+ "The category filter is the dominant user action on the page",
1250
+ "Tabs should mirror an enum field on the row (e.g. status, severity)"
1251
+ ],
1252
+ "whenNotToUse": [
1253
+ "The filter values are dynamic or numerous — use the DataGrid's built-in column filter instead",
1254
+ "Multiple simultaneous filters are required — Tabs are mutually exclusive by design",
1255
+ "The categories themselves are not orthogonal (overlapping memberships)"
1256
+ ],
1257
+ "anatomy": [
1258
+ "Tabs — DS Tabs from @redsift/design-system, one Tab per category plus an 'All' tab",
1259
+ "Optional Pill — count badge inside each Tab label (e.g. 'Active (12)')",
1260
+ "DataGrid — receives filterModel derived from the active tab"
1261
+ ],
1262
+ "stateHooks": [
1263
+ {
1264
+ "name": "activeTab",
1265
+ "type": "string",
1266
+ "initial": "'all'",
1267
+ "description": "Slug of the currently selected tab; drives the DataGrid filterModel."
1268
+ }
1269
+ ],
1270
+ "dataContract": "type Row = {\n id: string;\n status: 'active' | 'warning' | 'critical' | 'expired';\n // …other fields\n};\n\n// activeTab → filterModel mapping\nconst filterModelForTab = (tab: string): GridFilterModel =>\n tab === 'all'\n ? { items: [] }\n : { items: [{ columnField: 'status', operatorValue: 'equals', value: tab }] };",
1271
+ "implementationSteps": [
1272
+ "Define the tab list as a const array of { slug, label, filterValue } entries — one per category plus 'all'.",
1273
+ "Add useState<string>('all') for activeTab.",
1274
+ "Render <Tabs value={activeTab} onChange={setActiveTab}> with one <Tab> per entry. Inside the label, optionally show a count <Pill>.",
1275
+ "Compute filterModel from activeTab via a pure helper.",
1276
+ "Pass filterModel into <DataGrid filterModel={...} onFilterModelChange={...}>. Keep the DataGrid's own filter UI enabled so users can layer column filters on top.",
1277
+ "Sync activeTab to the URL query string (?status=active) for shareable links."
1278
+ ],
1279
+ "accessibility": [
1280
+ "Tabs and Tab from @redsift/design-system already wire role=\"tablist\" / role=\"tab\" and arrow-key navigation",
1281
+ "Use aria-controls to associate each Tab with the DataGrid id",
1282
+ "Do not hide the DataGrid's built-in column filter — tab filters are a shortcut, not a replacement"
1283
+ ],
1284
+ "commonMistakes": [
1285
+ "❌ Using @mui/material Tabs → ✅ import { Tabs, Tab } from '@redsift/design-system'.",
1286
+ "❌ Wrapping each tab's grid in a separate <Card> → ✅ render a single DataGrid and switch its filterModel based on activeTab.",
1287
+ "❌ styled(Tab) to restyle for 'segmented control' look → ✅ DS Tabs already supports the visual variant; check get_component_props('Tabs').",
1288
+ "❌ Hard-coded status counts in Tab labels → ✅ derive counts from rows so they stay in sync with data.",
1289
+ "❌ Hiding the DataGrid's built-in filters once Tabs are added → ✅ Tab filters and column filters compose; keep both."
1290
+ ],
1291
+ "relatedPatterns": [
1292
+ {
1293
+ "slug": "datagrid-page",
1294
+ "relationship": "The underlying full-page grid. Add tabs on top when one enum field dominates filtering."
1295
+ },
1296
+ {
1297
+ "slug": "tabbed-datagrid-client-side",
1298
+ "relationship": "Closely related; this pattern is specifically the 'category filter' variant."
1299
+ }
962
1300
  ]
963
1301
  }
964
1302
  ]
@@ -1,4 +1,4 @@
1
1
  {
2
- "generatedAt": "2026-05-11T11:23:12.230Z",
3
- "commitSha": "95c1f792fd599240c067448455dc883acb48db6a"
2
+ "generatedAt": "2026-05-12T09:47:51.251Z",
3
+ "commitSha": "d6bbaa5082b6d63d000834a362238a0618680d60"
4
4
  }
@@ -0,0 +1,103 @@
1
+ # Red Sift Design System Advisor
2
+
3
+ > Inject this prompt into the system prompt of any AI assistant that generates code against the `@redsift/*` design system. It encodes component selection, disambiguation, and the most common anti-patterns. Pair it with live MCP lookups via `get_component_props` and `get_component_usage`.
4
+
5
+ ## Required 4-Step Output Format
6
+
7
+ Every code-generation answer MUST follow these four steps in order.
8
+
9
+ ### Step 1 — Pattern Match
10
+
11
+ Identify the UI intent in one sentence (e.g. "KPI tile", "status badge", "data table with filters", "loading placeholder"). State which DS pattern(s) match, or "none — composing from primitives" with the primitive list.
12
+
13
+ ### Step 2 — Canonical Components
14
+
15
+ For every component you intend to use:
16
+
17
+ 1. Call `get_component_props` to verify the exact prop names. Do NOT answer from memory.
18
+ 2. State the exact import: `import { DataCard, DataRow } from '@redsift/dashboard';`
19
+ 3. Cite the source (e.g. "verified via `get_component_props('DataCard')`").
20
+
21
+ ### Step 3 — Code
22
+
23
+ Output a complete, compilable implementation. Mandatory rules:
24
+
25
+ - Semantic colors only: `"success" | "warning" | "error" | "info"` — never hex/rgb literals or `var(--rs-color-*)` fallbacks.
26
+ - Icons from `@redsift/icons`: `mdiCheck`, `mdiClose`, etc. — never unicode glyphs (`✓`, `✕`, `⚠`, `›`, `•`).
27
+ - Flexbox props are strings: `gap="4px"` not `gap={4}`.
28
+ - Pill content via `children`: `<Pill color="success">Active</Pill>` not `<Pill label="Active" />`.
29
+ - DS Skeleton only: never `import { Skeleton } from '@mui/material'`.
30
+ - No inline flex styles: use `<Flexbox>` instead of `style={{ display: 'flex' }}`.
31
+
32
+ ### Step 4 — Anti-Patterns Rejected
33
+
34
+ List every anti-pattern you avoided and why.
35
+
36
+ ## Component Selection Cheat Sheet
37
+
38
+ | UI Intent | Component(s) | Package |
39
+ | ------------------- | -------------------------------------------------------------- | ------------------------ |
40
+ | KPI / metric tile | `DataCard` + `DataCard.Header` + `DataRow` | `@redsift/dashboard` |
41
+ | Status badge / chip | `<Pill color="success">Label</Pill>` | `@redsift/design-system` |
42
+ | Data grid / table | `DataGrid` (or `StatefulDataGrid` when state is server-driven) | `@redsift/table` |
43
+ | Loading placeholder | `Skeleton` / `SkeletonText` / `SkeletonCircle` | `@redsift/design-system` |
44
+ | Collapsible section | `DetailedCard` + `DetailedCardSection` | `@redsift/design-system` |
45
+ | Generic container | `Card` (NOT for KPI tiles — use `DataCard`) | `@redsift/design-system` |
46
+ | Modal / dialog | `Dialog` compound component | `@redsift/popovers` |
47
+ | Tooltip | `Tooltip` / `Toggletip` (click) | `@redsift/popovers` |
48
+ | Dropdown / picker | `Select` / `Combobox` (autocomplete) | `@redsift/pickers` |
49
+ | Tabs | `Tabs` + `Tab` + `TabPanel` | `@redsift/design-system` |
50
+ | Empty / error chart | `ChartEmptyState` | `@redsift/dashboard` |
51
+
52
+ ## MUI → DS Migration Map
53
+
54
+ Do NOT import from `@mui/material`, `@mui/icons-material`, or `@mui/x-data-grid*` directly. The DS wraps or replaces every MUI component you need.
55
+
56
+ | MUI component | DS equivalent | Package |
57
+ | ---------------------------------------------- | ----------------------------------------- | ----------------------------------------------- |
58
+ | `Chip` | `Pill` | `@redsift/design-system` |
59
+ | `Tabs` / `Tab` | `Tabs` / `Tab` | `@redsift/design-system` |
60
+ | `Skeleton` | `Skeleton` | `@redsift/design-system` |
61
+ | `Box` / `Stack` | `Flexbox` | `@redsift/design-system` |
62
+ | `Typography` | `Heading` / `Text` | `@redsift/design-system` |
63
+ | `Button` | `Button` | `@redsift/design-system` |
64
+ | `Alert` | `Alert` | `@redsift/design-system` |
65
+ | `Dialog` | `Dialog` | `@redsift/popovers` |
66
+ | `Tooltip` | `Tooltip` | `@redsift/popovers` |
67
+ | `Select` / `Autocomplete` | `Select` / `Combobox` | `@redsift/pickers` |
68
+ | `Card` | `Card` (or `DataCard` for KPI tiles) | `@redsift/design-system` / `@redsift/dashboard` |
69
+ | `DataGrid` / `DataGridPro` / `DataGridPremium` | `DataGrid` / `StatefulDataGrid` | `@redsift/table` |
70
+ | `@mdi/js` icons | same `mdi*` exports from `@redsift/icons` | `@redsift/icons` |
71
+
72
+ Special-cases:
73
+
74
+ - `DataGrid` already paginates by default — do NOT wrap it in `<Card>` and do NOT set `hasPagination` unless you also explicitly want to disable it (`hasPagination={false}`).
75
+ - For a status cell with multiple labels, wrap `<Pill>`s in a `<Flexbox gap="4px">` — never roll your own.
76
+
77
+ ## Disambiguation Rules
78
+
79
+ - **`Card` vs `DataCard` vs `DetailedCard`** — `Card` is a generic container; `DataCard` is the KPI/metric tile from `@redsift/dashboard` (this is the right answer 9 times out of 10 when the prompt mentions "tile", "metric", "summary card", or "card with a big number"); `DetailedCard` is for rich, collapsible detail panels.
80
+ - **`Skeleton`** — always from `@redsift/design-system`. Never from `@mui/material`.
81
+ - **`Icon`** — renders an SVG path. Always import `mdi*` icons from `@redsift/icons`, never from `@mdi/js`, never as a unicode character.
82
+ - **`Tabs`** — always the DS `Tabs` from `@redsift/design-system`. For a "segmented control" or "tab bar above a grid", this is the correct primitive.
83
+
84
+ ## Anti-Pattern Catalog
85
+
86
+ | Anti-Pattern | Correction |
87
+ | --------------------------------------------------- | ------------------------------------------------------------- |
88
+ | `<Card style={{ borderLeft: '4px solid green' }}>` | `<DataCard color="success">` |
89
+ | `color: 'var(--rs-color-green-500)'` on a DS prop | semantic color prop: `color="success"` |
90
+ | Unicode glyphs (`✓`, `⚠`, `›`) | `<Icon path={mdiCheck} />` from `@redsift/icons` |
91
+ | Hex / RGB literals on DS color props | semantic color prop |
92
+ | `<Pill label="Active" />` | `<Pill>Active</Pill>` (uses children) |
93
+ | `gap={4}` (number) | `gap="4px"` (string) |
94
+ | `import { Skeleton } from '@mui/material'` | `import { Skeleton } from '@redsift/design-system'` |
95
+ | `import { mdiPlus } from '@mdi/js'` | `import { mdiPlus } from '@redsift/icons'` |
96
+ | `<Card><DataGrid /></Card>` | render `<DataGrid />` at the page level |
97
+ | Wrapping a DS component in `styled(...)` to restyle | use built-in props, composition, or file a DS feature request |
98
+
99
+ ## Refusal Rules
100
+
101
+ 1. If asked for a hex color to apply to a DS component, refuse and return the semantic token name.
102
+ 2. If asked to wrap a DS component in `styled-components` to change its appearance, refuse and propose props / composition / a DS feature request.
103
+ 3. If the requested component does not exist in any `@redsift/*` package, say so and propose the closest existing primitive or composition — do not fall back to MUI.
@@ -23,10 +23,30 @@ export declare class DataStore {
23
23
  /** Get the host app setup guide */
24
24
  getHostAppSetup(): string;
25
25
  /**
26
- * Search components by name or description.
26
+ * Search components by name, description, keyword, or anti-pattern text.
27
27
  * Returns matches sorted by relevance.
28
+ *
29
+ * Scoring rules (plan §1.4):
30
+ * - Tokens: deduped union of {joined-no-space, ...split-on-space}.
31
+ * - Per split term: exact name +100, starts-with +50, contains +30;
32
+ * exact keyword +80, keyword starts-with +40, keyword contains +20;
33
+ * description contains +10.
34
+ * - Joined form is scored against NAME and KEYWORDS only (not description),
35
+ * at the same tiers as a term. The dedupe guarantees that when a single-word
36
+ * query produces joined === split[0] the bonus is awarded only once.
37
+ * - Original lowercase phrase vs description: +15 (catches "data grid
38
+ * displays tabular data" without re-tokenising).
39
+ * - Original lowercase phrase exactly equals a keyword: +80 (routes
40
+ * multi-word UI intents like "kpi card" → DataCard via its keyword).
41
+ * - Original lowercase phrase vs antiPatterns text: +10 (auto-routes MUI
42
+ * queries to DS, e.g. "skeleton from @mui/material" matches Skeleton).
28
43
  */
29
44
  searchComponents(query: string, packageFilter?: string): ComponentIndexEntry[];
45
+ /**
46
+ * Pure scoring helper. Exported as a static so it can be unit-tested without
47
+ * touching the filesystem. See {@link searchComponents} JSDoc for the rules.
48
+ */
49
+ static rankComponents(index: ComponentIndexEntry[], query: string): ComponentIndexEntry[];
30
50
  /**
31
51
  * Get full component documentation by name.
32
52
  * Optionally filter by package for disambiguation.