@exxatdesignux/ui 0.2.19 → 0.3.0
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/CHANGELOG.md +60 -7
- package/bin/sync-extras.mjs +116 -29
- package/consumer-extras/README.md +42 -7
- package/consumer-extras/cursor-rules/exxat-accessibility.mdc +39 -0
- package/consumer-extras/cursor-rules/exxat-board-cards.mdc +26 -0
- package/consumer-extras/cursor-rules/exxat-breadcrumbs-no-back.mdc +21 -0
- package/consumer-extras/cursor-rules/exxat-card-vs-list-rows.mdc +21 -0
- package/consumer-extras/cursor-rules/exxat-centralized-list-dataset.mdc +44 -0
- package/consumer-extras/cursor-rules/exxat-collaboration-access.mdc +32 -0
- package/consumer-extras/cursor-rules/exxat-command-menu.mdc +22 -0
- package/consumer-extras/cursor-rules/exxat-dashboard-view-charts.mdc +53 -0
- package/consumer-extras/cursor-rules/exxat-data-tables.mdc +41 -0
- package/consumer-extras/cursor-rules/exxat-dedicated-search-surfaces.mdc +25 -0
- package/consumer-extras/cursor-rules/exxat-drawer-vs-dialog.mdc +22 -0
- package/consumer-extras/cursor-rules/exxat-ds-agents.mdc +56 -0
- package/consumer-extras/cursor-rules/exxat-fontawesome-icons.mdc +31 -0
- package/consumer-extras/cursor-rules/exxat-kbd-shortcuts.mdc +100 -0
- package/consumer-extras/cursor-rules/exxat-kpi-flat-band.mdc +28 -0
- package/consumer-extras/cursor-rules/exxat-kpi-max-four.mdc +21 -0
- package/consumer-extras/cursor-rules/exxat-kpi-trends.mdc +31 -0
- package/consumer-extras/cursor-rules/exxat-list-page-connected-views.mdc +24 -0
- package/consumer-extras/cursor-rules/exxat-list-page-view-shells.mdc +31 -0
- package/consumer-extras/cursor-rules/exxat-mono-ids.mdc +30 -0
- package/consumer-extras/cursor-rules/exxat-no-slds-leakage.mdc +78 -0
- package/consumer-extras/cursor-rules/exxat-no-toast.mdc +25 -0
- package/consumer-extras/cursor-rules/exxat-page-vs-drawer.mdc +23 -0
- package/consumer-extras/cursor-rules/exxat-person-identity-display.mdc +47 -0
- package/consumer-extras/cursor-rules/exxat-primary-nav-secondary-panel.mdc +52 -0
- package/consumer-extras/cursor-rules/exxat-question-bank-hub-header.mdc +28 -0
- package/consumer-extras/cursor-rules/exxat-reuse-before-custom.mdc +34 -0
- package/consumer-extras/cursor-rules/exxat-table-properties-drawer.mdc +77 -0
- package/consumer-extras/cursor-rules/exxat-token-discipline.mdc +103 -0
- package/consumer-extras/cursor-skills/exxat-accessibility/SKILL.md +1 -1
- package/consumer-extras/cursor-skills/exxat-board-cards/SKILL.md +2 -2
- package/consumer-extras/cursor-skills/exxat-centralized-list-dataset/SKILL.md +4 -15
- package/consumer-extras/cursor-skills/exxat-ds-skill/SKILL.md +13 -28
- package/consumer-extras/cursor-skills/exxat-ds-skill/references/data-table-pattern.md +1 -1
- package/consumer-extras/cursor-skills/exxat-primary-nav-secondary-panel/SKILL.md +2 -4
- package/consumer-extras/handbook/HANDBOOK.md +185 -0
- package/consumer-extras/handbook/glossary.md +57 -0
- package/consumer-extras/handbook/reference-implementations.md +126 -0
- package/consumer-extras/handbook/voice-and-tone.md +262 -0
- package/consumer-extras/patterns/command-menu-pattern.md +1 -1
- package/consumer-extras/patterns/consumer-upgrade-checklist.md +0 -20
- package/consumer-extras/patterns/data-views-pattern.md +17 -54
- package/consumer-extras/patterns/shell-surface-elevation-pattern.md +3 -5
- package/dist/components/data-table/filter-date-calendar.d.ts +10 -0
- package/dist/components/data-table/filter-date-calendar.js +280 -0
- package/dist/components/data-table/filter-date-calendar.js.map +1 -0
- package/dist/components/data-table/filter-text-value-input.d.ts +15 -0
- package/dist/components/data-table/filter-text-value-input.js +561 -0
- package/dist/components/data-table/filter-text-value-input.js.map +1 -0
- package/dist/components/data-table/index.d.ts +45 -0
- package/dist/components/data-table/index.js +3085 -0
- package/dist/components/data-table/index.js.map +1 -0
- package/dist/components/data-table/pagination.d.ts +28 -0
- package/dist/components/data-table/pagination.js +3264 -0
- package/dist/components/data-table/pagination.js.map +1 -0
- package/dist/components/data-table/types.d.ts +84 -0
- package/dist/components/data-table/types.js +3 -0
- package/dist/components/data-table/types.js.map +1 -0
- package/dist/components/data-table/use-table-state.d.ts +116 -0
- package/dist/components/data-table/use-table-state.js +670 -0
- package/dist/components/data-table/use-table-state.js.map +1 -0
- package/dist/components/data-views/board-card-primitives.d.ts +22 -0
- package/dist/components/data-views/board-card-primitives.js +84 -0
- package/dist/components/data-views/board-card-primitives.js.map +1 -0
- package/dist/components/data-views/data-row-list.d.ts +33 -0
- package/dist/components/data-views/data-row-list.js +106 -0
- package/dist/components/data-views/data-row-list.js.map +1 -0
- package/dist/components/data-views/finder-panel-view.d.ts +54 -0
- package/dist/components/data-views/finder-panel-view.js +388 -0
- package/dist/components/data-views/finder-panel-view.js.map +1 -0
- package/dist/components/data-views/folder-grid-view.d.ts +22 -0
- package/dist/components/data-views/folder-grid-view.js +58 -0
- package/dist/components/data-views/folder-grid-view.js.map +1 -0
- package/dist/components/data-views/hub-table.d.ts +167 -0
- package/dist/components/data-views/hub-table.js +5561 -0
- package/dist/components/data-views/hub-table.js.map +1 -0
- package/dist/components/data-views/index.d.ts +27 -0
- package/dist/components/data-views/index.js +6575 -0
- package/dist/components/data-views/index.js.map +1 -0
- package/dist/components/data-views/list-page-board-card.d.ts +72 -0
- package/dist/components/data-views/list-page-board-card.js +264 -0
- package/dist/components/data-views/list-page-board-card.js.map +1 -0
- package/dist/components/data-views/list-page-board-template.d.ts +24 -0
- package/dist/components/data-views/list-page-board-template.js +137 -0
- package/dist/components/data-views/list-page-board-template.js.map +1 -0
- package/dist/components/data-views/list-page-connected-view-body.d.ts +19 -0
- package/dist/components/data-views/list-page-connected-view-body.js +116 -0
- package/dist/components/data-views/list-page-connected-view-body.js.map +1 -0
- package/dist/components/data-views/list-page-split-details-placeholder.d.ts +14 -0
- package/dist/components/data-views/list-page-split-details-placeholder.js +38 -0
- package/dist/components/data-views/list-page-split-details-placeholder.js.map +1 -0
- package/dist/components/data-views/list-page-split-hub-chrome.d.ts +17 -0
- package/dist/components/data-views/list-page-split-hub-chrome.js +54 -0
- package/dist/components/data-views/list-page-split-hub-chrome.js.map +1 -0
- package/dist/components/data-views/list-page-split-hub-tokens.d.ts +12 -0
- package/dist/components/data-views/list-page-split-hub-tokens.js +8 -0
- package/dist/components/data-views/list-page-split-hub-tokens.js.map +1 -0
- package/dist/components/data-views/list-page-tree-column-header.d.ts +15 -0
- package/dist/components/data-views/list-page-tree-column-header.js +22 -0
- package/dist/components/data-views/list-page-tree-column-header.js.map +1 -0
- package/dist/components/data-views/list-page-tree-panel-shell.d.ts +25 -0
- package/dist/components/data-views/list-page-tree-panel-shell.js +146 -0
- package/dist/components/data-views/list-page-tree-panel-shell.js.map +1 -0
- package/dist/components/data-views/os-folder-glyph.d.ts +35 -0
- package/dist/components/data-views/os-folder-glyph.js +104 -0
- package/dist/components/data-views/os-folder-glyph.js.map +1 -0
- package/dist/components/data-views/outline-tree-menu.d.ts +36 -0
- package/dist/components/data-views/outline-tree-menu.js +131 -0
- package/dist/components/data-views/outline-tree-menu.js.map +1 -0
- package/dist/components/table-properties/column-row.d.ts +22 -0
- package/dist/components/table-properties/column-row.js +153 -0
- package/dist/components/table-properties/column-row.js.map +1 -0
- package/dist/components/table-properties/draggable-list.d.ts +24 -0
- package/dist/components/table-properties/draggable-list.js +53 -0
- package/dist/components/table-properties/draggable-list.js.map +1 -0
- package/dist/components/table-properties/drawer-button.d.ts +110 -0
- package/dist/components/table-properties/drawer-button.js +2748 -0
- package/dist/components/table-properties/drawer-button.js.map +1 -0
- package/dist/components/table-properties/drawer.d.ts +100 -0
- package/dist/components/table-properties/drawer.js +2595 -0
- package/dist/components/table-properties/drawer.js.map +1 -0
- package/dist/components/table-properties/filter-card.d.ts +24 -0
- package/dist/components/table-properties/filter-card.js +854 -0
- package/dist/components/table-properties/filter-card.js.map +1 -0
- package/dist/components/table-properties/index.d.ts +14 -0
- package/dist/components/table-properties/index.js +2768 -0
- package/dist/components/table-properties/index.js.map +1 -0
- package/dist/components/table-properties/sort-card.d.ts +20 -0
- package/dist/components/table-properties/sort-card.js +102 -0
- package/dist/components/table-properties/sort-card.js.map +1 -0
- package/dist/components/templates/dedicated-search-landing-template.d.ts +21 -0
- package/dist/components/templates/dedicated-search-landing-template.js +254 -0
- package/dist/components/templates/dedicated-search-landing-template.js.map +1 -0
- package/dist/components/templates/dedicated-search-results-template.d.ts +15 -0
- package/dist/components/templates/dedicated-search-results-template.js +16 -0
- package/dist/components/templates/dedicated-search-results-template.js.map +1 -0
- package/dist/components/templates/index.d.ts +9 -0
- package/dist/components/templates/index.js +2720 -0
- package/dist/components/templates/index.js.map +1 -0
- package/dist/components/templates/list-page.d.ts +83 -0
- package/dist/components/templates/list-page.js +2433 -0
- package/dist/components/templates/list-page.js.map +1 -0
- package/dist/components/templates/nested-secondary-panel-shell.d.ts +20 -0
- package/dist/components/templates/nested-secondary-panel-shell.js +54 -0
- package/dist/components/templates/nested-secondary-panel-shell.js.map +1 -0
- package/dist/components/ui/accordion.d.ts +10 -0
- package/dist/components/ui/accordion.js +74 -0
- package/dist/components/ui/accordion.js.map +1 -0
- package/dist/components/ui/alert-dialog.d.ts +37 -0
- package/dist/components/ui/alert-dialog.js +201 -0
- package/dist/components/ui/alert-dialog.js.map +1 -0
- package/dist/components/ui/avatar.d.ts +84 -0
- package/dist/components/ui/avatar.js +328 -0
- package/dist/components/ui/avatar.js.map +1 -0
- package/dist/components/ui/badge.d.ts +13 -0
- package/dist/components/ui/badge.js +49 -0
- package/dist/components/ui/badge.js.map +1 -0
- package/dist/components/ui/banner.d.ts +62 -0
- package/dist/components/ui/banner.js +364 -0
- package/dist/components/ui/banner.js.map +1 -0
- package/dist/components/ui/breadcrumb.d.ts +14 -0
- package/dist/components/ui/breadcrumb.js +114 -0
- package/dist/components/ui/breadcrumb.js.map +1 -0
- package/dist/components/ui/button.d.ts +16 -0
- package/dist/components/ui/button.js +59 -0
- package/dist/components/ui/button.js.map +1 -0
- package/dist/components/ui/calendar.d.ts +13 -0
- package/dist/components/ui/calendar.js +238 -0
- package/dist/components/ui/calendar.js.map +1 -0
- package/dist/components/ui/card.d.ts +14 -0
- package/dist/components/ui/card.js +102 -0
- package/dist/components/ui/card.js.map +1 -0
- package/dist/components/ui/chart.d.ts +58 -0
- package/dist/components/ui/chart.js +292 -0
- package/dist/components/ui/chart.js.map +1 -0
- package/dist/components/ui/checkbox.d.ts +23 -0
- package/dist/components/ui/checkbox.js +155 -0
- package/dist/components/ui/checkbox.js.map +1 -0
- package/dist/components/ui/coach-mark.d.ts +27 -0
- package/dist/components/ui/coach-mark.js +306 -0
- package/dist/components/ui/coach-mark.js.map +1 -0
- package/dist/components/ui/collapsible.d.ts +8 -0
- package/dist/components/ui/collapsible.js +35 -0
- package/dist/components/ui/collapsible.js.map +1 -0
- package/dist/components/ui/command.d.ts +36 -0
- package/dist/components/ui/command.js +274 -0
- package/dist/components/ui/command.js.map +1 -0
- package/dist/components/ui/context-menu.d.ts +32 -0
- package/dist/components/ui/context-menu.js +245 -0
- package/dist/components/ui/context-menu.js.map +1 -0
- package/dist/components/ui/date-picker-field.d.ts +38 -0
- package/dist/components/ui/date-picker-field.js +550 -0
- package/dist/components/ui/date-picker-field.js.map +1 -0
- package/dist/components/ui/dialog.d.ts +22 -0
- package/dist/components/ui/dialog.js +200 -0
- package/dist/components/ui/dialog.js.map +1 -0
- package/dist/components/ui/dot-pattern.d.ts +21 -0
- package/dist/components/ui/dot-pattern.js +139 -0
- package/dist/components/ui/dot-pattern.js.map +1 -0
- package/dist/components/ui/drag-handle-grip.d.ts +10 -0
- package/dist/components/ui/drag-handle-grip.js +15 -0
- package/dist/components/ui/drag-handle-grip.js.map +1 -0
- package/dist/components/ui/drawer.d.ts +16 -0
- package/dist/components/ui/drawer.js +125 -0
- package/dist/components/ui/drawer.js.map +1 -0
- package/dist/components/ui/dropdown-menu.d.ts +45 -0
- package/dist/components/ui/dropdown-menu.js +353 -0
- package/dist/components/ui/dropdown-menu.js.map +1 -0
- package/dist/components/ui/export-drawer.d.ts +11 -0
- package/dist/components/ui/export-drawer.js +1658 -0
- package/dist/components/ui/export-drawer.js.map +1 -0
- package/dist/components/ui/field.d.ts +30 -0
- package/dist/components/ui/field.js +249 -0
- package/dist/components/ui/field.js.map +1 -0
- package/dist/components/ui/form.d.ts +28 -0
- package/dist/components/ui/form.js +110 -0
- package/dist/components/ui/form.js.map +1 -0
- package/dist/components/ui/hover-card.d.ts +9 -0
- package/dist/components/ui/hover-card.js +43 -0
- package/dist/components/ui/hover-card.js.map +1 -0
- package/dist/components/ui/input-group.d.ts +20 -0
- package/dist/components/ui/input-group.js +219 -0
- package/dist/components/ui/input-group.js.map +1 -0
- package/dist/components/ui/input-mask.d.ts +39 -0
- package/dist/components/ui/input-mask.js +118 -0
- package/dist/components/ui/input-mask.js.map +1 -0
- package/dist/components/ui/input.d.ts +5 -0
- package/dist/components/ui/input.js +30 -0
- package/dist/components/ui/input.js.map +1 -0
- package/dist/components/ui/kbd.d.ts +20 -0
- package/dist/components/ui/kbd.js +45 -0
- package/dist/components/ui/kbd.js.map +1 -0
- package/dist/components/ui/key-metrics-context.d.ts +19 -0
- package/dist/components/ui/key-metrics-context.js +26 -0
- package/dist/components/ui/key-metrics-context.js.map +1 -0
- package/dist/components/ui/key-metrics.d.ts +131 -0
- package/dist/components/ui/key-metrics.js +1015 -0
- package/dist/components/ui/key-metrics.js.map +1 -0
- package/dist/components/ui/label.d.ts +6 -0
- package/dist/components/ui/label.js +28 -0
- package/dist/components/ui/label.js.map +1 -0
- package/dist/components/ui/list-page-view-frame.d.ts +22 -0
- package/dist/components/ui/list-page-view-frame.js +24 -0
- package/dist/components/ui/list-page-view-frame.js.map +1 -0
- package/dist/components/ui/page-header.d.ts +51 -0
- package/dist/components/ui/page-header.js +372 -0
- package/dist/components/ui/page-header.js.map +1 -0
- package/dist/components/ui/payment-card-fields.d.ts +10 -0
- package/dist/components/ui/payment-card-fields.js +80 -0
- package/dist/components/ui/payment-card-fields.js.map +1 -0
- package/dist/components/ui/popover.d.ts +10 -0
- package/dist/components/ui/popover.js +47 -0
- package/dist/components/ui/popover.js.map +1 -0
- package/dist/components/ui/radio-group.d.ts +29 -0
- package/dist/components/ui/radio-group.js +190 -0
- package/dist/components/ui/radio-group.js.map +1 -0
- package/dist/components/ui/resizable.d.ts +16 -0
- package/dist/components/ui/resizable.js +51 -0
- package/dist/components/ui/resizable.js.map +1 -0
- package/dist/components/ui/scroll-area.d.ts +8 -0
- package/dist/components/ui/scroll-area.js +66 -0
- package/dist/components/ui/scroll-area.js.map +1 -0
- package/dist/components/ui/select.d.ts +18 -0
- package/dist/components/ui/select.js +186 -0
- package/dist/components/ui/select.js.map +1 -0
- package/dist/components/ui/selection-tile-grid.d.ts +52 -0
- package/dist/components/ui/selection-tile-grid.js +347 -0
- package/dist/components/ui/selection-tile-grid.js.map +1 -0
- package/dist/components/ui/separator.d.ts +7 -0
- package/dist/components/ui/separator.js +33 -0
- package/dist/components/ui/separator.js.map +1 -0
- package/dist/components/ui/sheet.d.ts +18 -0
- package/dist/components/ui/sheet.js +181 -0
- package/dist/components/ui/sheet.js.map +1 -0
- package/dist/components/ui/sidebar.d.ts +94 -0
- package/dist/components/ui/sidebar.js +805 -0
- package/dist/components/ui/sidebar.js.map +1 -0
- package/dist/components/ui/skeleton.d.ts +5 -0
- package/dist/components/ui/skeleton.js +22 -0
- package/dist/components/ui/skeleton.js.map +1 -0
- package/dist/components/ui/slider.d.ts +7 -0
- package/dist/components/ui/slider.js +66 -0
- package/dist/components/ui/slider.js.map +1 -0
- package/dist/components/ui/sonner.d.ts +6 -0
- package/dist/components/ui/sonner.js +38 -0
- package/dist/components/ui/sonner.js.map +1 -0
- package/dist/components/ui/status-badge.d.ts +38 -0
- package/dist/components/ui/status-badge.js +77 -0
- package/dist/components/ui/status-badge.js.map +1 -0
- package/dist/components/ui/table.d.ts +13 -0
- package/dist/components/ui/table.js +115 -0
- package/dist/components/ui/table.js.map +1 -0
- package/dist/components/ui/tabs.d.ts +15 -0
- package/dist/components/ui/tabs.js +93 -0
- package/dist/components/ui/tabs.js.map +1 -0
- package/dist/components/ui/textarea.d.ts +6 -0
- package/dist/components/ui/textarea.js +25 -0
- package/dist/components/ui/textarea.js.map +1 -0
- package/dist/components/ui/tip.d.ts +12 -0
- package/dist/components/ui/tip.js +61 -0
- package/dist/components/ui/tip.js.map +1 -0
- package/dist/components/ui/toggle-group.d.ts +14 -0
- package/dist/components/ui/toggle-group.js +104 -0
- package/dist/components/ui/toggle-group.js.map +1 -0
- package/dist/components/ui/toggle-switch.d.ts +10 -0
- package/dist/components/ui/toggle-switch.js +33 -0
- package/dist/components/ui/toggle-switch.js.map +1 -0
- package/dist/components/ui/toggle.d.ts +13 -0
- package/dist/components/ui/toggle.js +51 -0
- package/dist/components/ui/toggle.js.map +1 -0
- package/dist/components/ui/tooltip.d.ts +10 -0
- package/dist/components/ui/tooltip.js +68 -0
- package/dist/components/ui/tooltip.js.map +1 -0
- package/dist/components/ui/view-segmented-control.d.ts +31 -0
- package/dist/components/ui/view-segmented-control.js +167 -0
- package/dist/components/ui/view-segmented-control.js.map +1 -0
- package/dist/data-list-view-registry-CyBoBML4.d.ts +73 -0
- package/dist/hooks/use-app-theme.d.ts +24 -0
- package/dist/hooks/use-app-theme.js +286 -0
- package/dist/hooks/use-app-theme.js.map +1 -0
- package/dist/hooks/use-coach-mark.d.ts +86 -0
- package/dist/hooks/use-coach-mark.js +218 -0
- package/dist/hooks/use-coach-mark.js.map +1 -0
- package/dist/hooks/use-mobile.d.ts +3 -0
- package/dist/hooks/use-mobile.js +29 -0
- package/dist/hooks/use-mobile.js.map +1 -0
- package/dist/hooks/use-mod-key-label.d.ts +6 -0
- package/dist/hooks/use-mod-key-label.js +25 -0
- package/dist/hooks/use-mod-key-label.js.map +1 -0
- package/dist/index.d.ts +120 -0
- package/dist/index.js +13324 -0
- package/dist/index.js.map +1 -0
- package/dist/lib/compose-refs.d.ts +6 -0
- package/dist/lib/compose-refs.js +17 -0
- package/dist/lib/compose-refs.js.map +1 -0
- package/dist/lib/conditional-rule-match.d.ts +30 -0
- package/dist/lib/conditional-rule-match.js +66 -0
- package/dist/lib/conditional-rule-match.js.map +1 -0
- package/dist/lib/data-list-display-options.d.ts +26 -0
- package/dist/lib/data-list-display-options.js +14 -0
- package/dist/lib/data-list-display-options.js.map +1 -0
- package/dist/lib/data-list-view-registry.d.ts +2 -0
- package/dist/lib/data-list-view-registry.js +102 -0
- package/dist/lib/data-list-view-registry.js.map +1 -0
- package/dist/lib/data-list-view-surface.d.ts +2 -0
- package/dist/lib/data-list-view-surface.js +80 -0
- package/dist/lib/data-list-view-surface.js.map +1 -0
- package/dist/lib/data-list-view.d.ts +21 -0
- package/dist/lib/data-list-view.js +25 -0
- package/dist/lib/data-list-view.js.map +1 -0
- package/dist/lib/date-filter.d.ts +22 -0
- package/dist/lib/date-filter.js +61 -0
- package/dist/lib/date-filter.js.map +1 -0
- package/dist/lib/dev-log.d.ts +8 -0
- package/dist/lib/dev-log.js +10 -0
- package/dist/lib/dev-log.js.map +1 -0
- package/dist/lib/dropdown-menu-surface.d.ts +14 -0
- package/dist/lib/dropdown-menu-surface.js +6 -0
- package/dist/lib/dropdown-menu-surface.js.map +1 -0
- package/dist/lib/editable-target.d.ts +12 -0
- package/dist/lib/editable-target.js +12 -0
- package/dist/lib/editable-target.js.map +1 -0
- package/dist/lib/list-page-table-properties.d.ts +35 -0
- package/dist/lib/list-page-table-properties.js +81 -0
- package/dist/lib/list-page-table-properties.js.map +1 -0
- package/dist/lib/raf-throttle.d.ts +23 -0
- package/dist/lib/raf-throttle.js +27 -0
- package/dist/lib/raf-throttle.js.map +1 -0
- package/dist/lib/row-height.d.ts +16 -0
- package/dist/lib/row-height.js +10 -0
- package/dist/lib/row-height.js.map +1 -0
- package/dist/lib/table-properties-types.d.ts +83 -0
- package/dist/lib/table-properties-types.js +19 -0
- package/dist/lib/table-properties-types.js.map +1 -0
- package/dist/lib/utils.d.ts +5 -0
- package/dist/lib/utils.js +11 -0
- package/dist/lib/utils.js.map +1 -0
- package/package.json +83 -19
- package/src/components/data-table/filter-date-calendar.tsx +38 -0
- package/src/components/data-table/filter-text-value-input.tsx +77 -0
- package/src/components/data-table/index.tsx +1678 -0
- package/src/components/data-table/pagination.tsx +255 -0
- package/src/components/data-table/types.ts +96 -0
- package/src/components/data-table/use-table-state.ts +767 -0
- package/src/components/data-views/board-card-primitives.tsx +93 -0
- package/src/components/data-views/data-row-list.tsx +183 -0
- package/src/components/data-views/finder-panel-view.tsx +405 -0
- package/src/components/data-views/folder-grid-view.tsx +86 -0
- package/src/components/data-views/hub-table.tsx +498 -0
- package/src/components/data-views/index.ts +28 -0
- package/src/components/data-views/list-page-board-card.tsx +192 -0
- package/src/components/data-views/list-page-board-template.tsx +122 -0
- package/src/components/data-views/list-page-connected-view-body.tsx +66 -0
- package/src/components/data-views/list-page-split-details-placeholder.tsx +39 -0
- package/src/components/data-views/list-page-split-hub-chrome.tsx +60 -0
- package/src/components/data-views/list-page-split-hub-tokens.ts +16 -0
- package/src/components/data-views/list-page-tree-column-header.tsx +31 -0
- package/src/components/data-views/list-page-tree-panel-shell.tsx +91 -0
- package/src/components/data-views/os-folder-glyph.tsx +141 -0
- package/src/components/data-views/outline-tree-menu.tsx +157 -0
- package/src/components/table-properties/column-row.tsx +90 -0
- package/src/components/table-properties/draggable-list.ts +54 -0
- package/src/components/table-properties/drawer-button.tsx +300 -0
- package/src/components/table-properties/drawer.tsx +1148 -0
- package/src/components/table-properties/filter-card.tsx +251 -0
- package/src/components/table-properties/index.ts +36 -0
- package/src/components/table-properties/sort-card.tsx +63 -0
- package/src/components/templates/dedicated-search-landing-template.tsx +124 -0
- package/src/components/templates/dedicated-search-results-template.tsx +19 -0
- package/src/components/templates/index.ts +33 -0
- package/src/components/templates/list-page.tsx +602 -0
- package/src/components/templates/nested-secondary-panel-shell.tsx +70 -0
- package/src/components/ui/accordion.tsx +92 -0
- package/src/components/ui/alert-dialog.tsx +221 -0
- package/src/components/ui/avatar.tsx +13 -2
- package/src/components/ui/banner.tsx +2 -2
- package/src/components/ui/button.tsx +4 -4
- package/src/components/ui/calendar.tsx +1 -1
- package/src/components/ui/coach-mark.tsx +1 -1
- package/src/components/ui/context-menu.tsx +291 -0
- package/src/components/ui/date-picker-field.tsx +2 -2
- package/src/components/ui/dot-pattern.tsx +183 -0
- package/src/components/ui/export-drawer.tsx +375 -0
- package/src/components/ui/hover-card.tsx +66 -0
- package/src/components/ui/key-metrics-context.tsx +78 -0
- package/src/components/ui/key-metrics.tsx +1133 -0
- package/src/components/ui/list-page-view-frame.tsx +64 -0
- package/src/components/ui/page-header.tsx +244 -0
- package/src/components/ui/payment-card-fields.tsx +2 -2
- package/src/components/ui/resizable.tsx +68 -0
- package/src/components/ui/scroll-area.tsx +72 -0
- package/src/components/ui/selection-tile-grid.tsx +9 -2
- package/src/components/ui/sidebar.tsx +84 -12
- package/src/components/ui/slider.tsx +83 -0
- package/src/globals.css +2201 -7
- package/src/globals.d.ts +20 -0
- package/src/index.ts +68 -1
- package/src/lib/conditional-rule-match.ts +119 -0
- package/src/lib/data-list-display-options.ts +35 -0
- package/src/lib/data-list-view-registry.ts +104 -0
- package/src/lib/data-list-view-surface.ts +83 -0
- package/src/lib/data-list-view.ts +47 -0
- package/src/lib/dev-log.ts +10 -0
- package/src/lib/editable-target.ts +20 -0
- package/src/lib/list-page-table-properties.ts +48 -0
- package/src/lib/raf-throttle.ts +45 -0
- package/src/lib/row-height.ts +19 -0
- package/src/lib/table-properties-types.ts +98 -0
- package/template/.cursor/rules/exxat-command-menu.mdc +1 -1
- package/template/.cursor/rules/exxat-dashboard-view-charts.mdc +3 -3
- package/template/.cursor/rules/exxat-data-tables.mdc +1 -1
- package/template/.cursor/rules/exxat-ds-agents.mdc +2 -2
- package/template/.cursor/rules/exxat-kbd-shortcuts.mdc +2 -2
- package/template/.cursor/rules/exxat-table-properties-drawer.mdc +1 -1
- package/template/AGENTS.md +104 -78
- package/template/app/(app)/dashboard/loading.tsx +15 -3
- package/template/app/(app)/dashboard/page.tsx +14 -2
- package/template/app/(app)/examples/page.tsx +0 -2
- package/template/app/(app)/layout.tsx +17 -4
- package/template/app/(app)/loading.tsx +18 -1
- package/template/app/(app)/question-bank/find/page.tsx +1 -2
- package/template/app/(app)/question-bank/layout.tsx +1 -1
- package/template/app/(app)/question-bank/library/page.tsx +1 -2
- package/template/app/(app)/question-bank/list/page.tsx +1 -2
- package/template/app/(app)/question-bank/new/page.tsx +15 -20
- package/template/app/(app)/question-bank/page.tsx +1 -2
- package/template/app/(app)/settings/page.tsx +5 -4
- package/template/app/globals.css +14 -16
- package/template/components/ask-leo-sidebar.tsx +5 -1
- package/template/components/brand-color-picker.tsx +2 -2
- package/template/components/charts-overview.tsx +1 -1
- package/template/components/compliance-board-view.tsx +142 -0
- package/template/components/compliance-client.tsx +92 -0
- package/template/components/compliance-page-header.tsx +89 -0
- package/template/components/compliance-table.tsx +468 -0
- package/template/components/dashboard-report-charts.tsx +1 -1
- package/template/components/dashboard-tabs.tsx +1 -1
- package/template/components/data-table/filter-date-calendar.tsx +1 -38
- package/template/components/data-table/filter-text-value-input.tsx +1 -77
- package/template/components/data-table/index.tsx +1 -1634
- package/template/components/data-table/pagination.tsx +1 -255
- package/template/components/data-table/types.ts +1 -94
- package/template/components/data-table/use-table-state.test.ts +420 -0
- package/template/components/data-table/use-table-state.ts +1 -758
- package/template/components/data-view-dashboard-charts-compliance.tsx +963 -0
- package/template/components/data-view-dashboard-charts-team.tsx +971 -0
- package/template/components/data-view-dashboard-charts.tsx +1503 -0
- package/template/components/data-views/board-card-primitives.tsx +1 -93
- package/template/components/data-views/data-row-list.tsx +1 -183
- package/template/components/data-views/finder-panel-view.tsx +1 -405
- package/template/components/data-views/folder-grid-view.tsx +1 -86
- package/template/components/data-views/hub-table.tsx +1 -0
- package/template/components/data-views/index.ts +50 -37
- package/template/components/data-views/list-page-board-card.tsx +1 -192
- package/template/components/data-views/list-page-board-template.tsx +1 -122
- package/template/components/data-views/list-page-connected-view-body.tsx +1 -66
- package/template/components/data-views/list-page-split-details-placeholder.tsx +1 -39
- package/template/components/data-views/list-page-split-hub-chrome.tsx +1 -68
- package/template/components/data-views/list-page-split-hub-tokens.ts +1 -16
- package/template/components/data-views/list-page-tree-column-header.tsx +1 -31
- package/template/components/data-views/list-page-tree-panel-shell.tsx +1 -91
- package/template/components/data-views/list-page-view-frame.tsx +5 -53
- package/template/components/data-views/os-folder-glyph.tsx +1 -129
- package/template/components/data-views/outline-tree-menu.tsx +1 -157
- package/template/components/export-drawer.test.tsx +71 -0
- package/template/components/export-drawer.tsx +1 -375
- package/template/components/exxat-product-logo.tsx +5 -5
- package/template/components/hub-tree-panel-view.tsx +2 -2
- package/template/components/invite-collaborators-drawer.tsx +3 -3
- package/template/components/key-metrics-ask-leo-bridge.tsx +40 -0
- package/template/components/key-metrics.tsx +1 -1063
- package/template/components/leo-insight-indicator.tsx +2 -2
- package/template/components/new-placement-back-btn.tsx +28 -0
- package/template/components/new-placement-form.tsx +942 -0
- package/template/components/new-question-composer.tsx +456 -408
- package/template/components/onboarding/index.ts +9 -0
- package/template/components/onboarding/onboarding-01.tsx +1 -1
- package/template/components/onboarding/onboarding-02.tsx +1 -1
- package/template/components/onboarding/onboarding-03.tsx +1 -1
- package/template/components/onboarding/onboarding-04.tsx +1 -1
- package/template/components/page-header.tsx +8 -226
- package/template/components/placement-board-card.tsx +250 -0
- package/template/components/placement-detail.tsx +438 -0
- package/template/components/placements-board-view.tsx +397 -0
- package/template/components/placements-client.tsx +220 -0
- package/template/components/placements-list-view.tsx +124 -0
- package/template/components/placements-page-header.tsx +166 -0
- package/template/components/placements-table-cells.test.tsx +22 -0
- package/template/components/placements-table-cells.tsx +173 -0
- package/template/components/placements-table-columns.tsx +210 -0
- package/template/components/placements-table.tsx +934 -0
- package/template/components/product-switcher.tsx +3 -4
- package/template/components/product-wordmark.tsx +2 -1
- package/template/components/question-bank-client.tsx +5 -5
- package/template/components/question-bank-hub-client.tsx +1 -1
- package/template/components/question-bank-new-folder-sheet.tsx +2 -2
- package/template/components/question-bank-secondary-nav.tsx +3 -3
- package/template/components/question-bank-table.tsx +541 -431
- package/template/components/rotations-empty-state.tsx +50 -0
- package/template/components/rotations-panel-activator.tsx +8 -0
- package/template/components/settings-appearance-card.tsx +3 -4
- package/template/components/settings-client.tsx +15 -59
- package/template/components/settings-form-row.tsx +4 -9
- package/template/components/{app-sidebar-dynamic.tsx → sidebar/app-sidebar-dynamic.tsx} +1 -1
- package/template/components/{app-sidebar.tsx → sidebar/app-sidebar.tsx} +59 -74
- package/template/components/sidebar/index.ts +16 -0
- package/template/components/{secondary-nav.tsx → sidebar/secondary-nav.tsx} +2 -2
- package/template/components/{secondary-panel.tsx → sidebar/secondary-panel.tsx} +50 -7
- package/template/components/{sidebar-auto-collapse.tsx → sidebar/sidebar-auto-collapse.tsx} +6 -2
- package/template/components/{sidebar-shell.tsx → sidebar/sidebar-shell.tsx} +1 -1
- package/template/components/site-header.tsx +1 -1
- package/template/components/sites-board-view.tsx +67 -0
- package/template/components/sites-client.tsx +154 -0
- package/template/components/sites-table.tsx +249 -0
- package/template/components/table-properties/column-row.tsx +1 -90
- package/template/components/table-properties/draggable-list.ts +1 -49
- package/template/components/table-properties/drawer-button.tsx +1 -262
- package/template/components/table-properties/drawer.tsx +1 -1166
- package/template/components/table-properties/filter-card.tsx +1 -251
- package/template/components/table-properties/sort-card.tsx +1 -59
- package/template/components/table-properties/types.ts +28 -71
- package/template/components/team-board-view.tsx +122 -0
- package/template/components/team-client.tsx +100 -0
- package/template/components/team-page-header.tsx +92 -0
- package/template/components/team-table.tsx +553 -0
- package/template/components/templates/dedicated-search-landing-template.tsx +1 -124
- package/template/components/templates/dedicated-search-results-template.tsx +1 -19
- package/template/components/templates/list-page.tsx +1 -608
- package/template/components/templates/nested-secondary-panel-shell.tsx +1 -63
- package/template/components/templates/new-focus-template.tsx +659 -0
- package/template/components/templates/secondary-panel-hub-template.tsx +1 -1
- package/template/components/ui/accordion.tsx +1 -0
- package/template/components/ui/alert-dialog.tsx +1 -0
- package/template/components/ui/context-menu.tsx +1 -0
- package/template/components/ui/dot-pattern.tsx +1 -183
- package/template/components/ui/hover-card.tsx +1 -0
- package/template/components/ui/resizable.tsx +1 -68
- package/template/components/ui/scroll-area.tsx +1 -0
- package/template/components/ui/slider.tsx +1 -0
- package/template/docs/blueprints/README.md +86 -0
- package/template/docs/blueprints/_template.md +91 -0
- package/template/docs/blueprints/board-card.md +123 -0
- package/template/docs/blueprints/data-table.md +139 -0
- package/template/docs/blueprints/key-metrics.md +128 -0
- package/template/docs/blueprints/list-page-template.md +123 -0
- package/template/docs/blueprints/page-header.md +130 -0
- package/template/docs/command-menu-pattern.md +1 -1
- package/template/docs/component-selection-guide.md +224 -0
- package/template/docs/components-audit-2026-05.md +158 -0
- package/template/docs/data-views-pattern.md +17 -54
- package/template/docs/drawer-vs-dialog-pattern.md +1 -3
- package/template/docs/migrations/0001-brand-deep-alias-stabilization.md +95 -0
- package/template/docs/migrations/0002-exxat-token-namespace.md +154 -0
- package/template/docs/migrations/0003-globals-css-canonical.md +110 -0
- package/template/docs/migrations/README.md +100 -0
- package/template/docs/migrations/_template.md +64 -0
- package/template/docs/shell-surface-elevation-pattern.md +3 -5
- package/template/docs/token-taxonomy.md +416 -0
- package/template/eslint.config.mjs +27 -0
- package/template/hooks/use-secondary-panel-hub-nav.ts +1 -1
- package/template/lib/command-menu-config.ts +0 -1
- package/template/lib/command-menu-search-data.ts +27 -11
- package/template/lib/compliance-supported-views.ts +10 -0
- package/template/lib/conditional-rule-match.ts +6 -97
- package/template/lib/data-list-display-options.ts +1 -49
- package/template/lib/data-list-view-registry.ts +1 -104
- package/template/lib/data-list-view-surface.ts +1 -83
- package/template/lib/data-list-view.ts +1 -47
- package/template/lib/data-view-dashboard-placements-layout.ts +215 -0
- package/template/lib/data-view-dashboard-storage.ts +35 -38
- package/template/lib/dev-log.ts +1 -8
- package/template/lib/editable-target.ts +1 -10
- package/template/lib/list-page-table-properties.ts +1 -48
- package/template/lib/list-status-badges.ts +97 -4
- package/template/lib/mock/compliance-kpi.ts +61 -0
- package/template/lib/mock/compliance.ts +146 -0
- package/template/lib/mock/navigation.tsx +0 -9
- package/template/lib/mock/placements-kpi.ts +134 -0
- package/template/lib/mock/placements.ts +176 -0
- package/template/lib/mock/sites-directory.ts +16 -0
- package/template/lib/mock/sites-kpi.ts +25 -0
- package/template/lib/mock/team-kpi.ts +60 -0
- package/template/lib/mock/team.ts +118 -0
- package/template/lib/placement-board-card-layout.ts +79 -0
- package/template/lib/placements-supported-views.ts +12 -0
- package/template/lib/question-bank-supported-views.ts +0 -1
- package/template/lib/raf-throttle.ts +1 -45
- package/template/lib/row-height.ts +4 -10
- package/template/lib/sidebar-state-cookie.ts +11 -2
- package/template/lib/sites-supported-views.ts +10 -0
- package/template/lib/table-state-lifecycle.ts +2 -2
- package/template/lib/team-supported-views.ts +10 -0
- package/template/package.json +1 -0
- package/template/tests/setup.ts +25 -0
- package/consumer-extras/AGENTS.md +0 -76
- package/consumer-extras/cursor-skills/exxat-consumer-app/SKILL.md +0 -37
- package/consumer-extras/cursor-skills/exxat-focused-workflow-page/SKILL.md +0 -57
- package/consumer-extras/patterns/consumer-app-pattern.md +0 -39
- package/consumer-extras/patterns/focused-workflow-page-pattern.md +0 -84
- package/src/components/ui/button-group.tsx +0 -81
- package/src/theme.css +0 -16
- package/src/tokens/README.md +0 -15
- package/src/tokens/base.css +0 -337
- package/src/tokens/high-contrast.css +0 -1195
- package/src/tokens/layers.css +0 -224
- package/src/tokens/tailwind-bridge.css +0 -118
- package/src/tokens/themes.css +0 -201
- package/template/app/(app)/data-list/layout.tsx +0 -43
- package/template/app/(app)/data-list/page.tsx +0 -10
- package/template/app/(app)/examples/focused-workflow/page.tsx +0 -5
- package/template/components/app-route-loading.tsx +0 -14
- package/template/components/dashboard-onboarding-gallery.tsx +0 -13
- package/template/components/dashboard-onboarding.tsx +0 -21
- package/template/components/data-views/list-page-calendar-view.tsx +0 -593
- package/template/components/data-views/list-page-folder-columns-panel.tsx +0 -345
- package/template/components/examples/focused-workflow-showcase.tsx +0 -183
- package/template/components/list-hub-board-view.tsx +0 -68
- package/template/components/list-hub-client.tsx +0 -186
- package/template/components/list-hub-list-view.tsx +0 -36
- package/template/components/list-hub-panel-activator.tsx +0 -8
- package/template/components/list-hub-secondary-nav.tsx +0 -121
- package/template/components/list-hub-table.tsx +0 -336
- package/template/components/question-bank-folder-columns-panel.tsx +0 -104
- package/template/components/question-bank-list-view.tsx +0 -53
- package/template/components/secondary-panel/nav-link-rows.tsx +0 -83
- package/template/components/secondary-panels/list-hub-panel.tsx +0 -39
- package/template/components/secondary-panels/question-bank-panel.tsx +0 -39
- package/template/components/secondary-panels/registry.tsx +0 -15
- package/template/components/section-cards.tsx +0 -106
- package/template/components/templates/focused-workflow-layouts.tsx +0 -448
- package/template/components/templates/focused-workflow-page-template.tsx +0 -69
- package/template/components/templates/page-loading-shell.tsx +0 -262
- package/template/components/ui/button-group.tsx +0 -1
- package/template/docs/consumer-app-pattern.md +0 -39
- package/template/docs/focused-workflow-page-pattern.md +0 -84
- package/template/lib/list-hub-nav.ts +0 -121
- package/template/lib/mock/list-hub-directory.ts +0 -27
- package/template/lib/mock/list-hub-kpi.ts +0 -27
- package/template/lib/page-loading-variant.ts +0 -40
- /package/template/components/{getting-started.tsx → onboarding/getting-started.tsx} +0 -0
- /package/template/components/{nav-documents.tsx → sidebar/nav-documents.tsx} +0 -0
- /package/template/components/{nav-main.tsx → sidebar/nav-main.tsx} +0 -0
- /package/template/components/{nav-secondary.tsx → sidebar/nav-secondary.tsx} +0 -0
- /package/template/components/{nav-user.tsx → sidebar/nav-user.tsx} +0 -0
- /package/template/components/{sidebar-auto-open.tsx → sidebar/sidebar-auto-open.tsx} +0 -0
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
---
|
|
2
|
+
description: Data view dashboard — centralized charts, storage, keyboard parity with gallery, edit layout, coach marks
|
|
3
|
+
alwaysApply: true
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Exxat DS — Data view dashboard (list hubs)
|
|
7
|
+
|
|
8
|
+
**Authoritative detail:** **`apps/web/AGENTS.md` §4.3** and **`exxat-dashboard-view-charts`** (this rule).
|
|
9
|
+
|
|
10
|
+
## Two dashboard surfaces (do not fork chart engines)
|
|
11
|
+
|
|
12
|
+
| Surface | Entry | Shared building blocks |
|
|
13
|
+
|--------|--------|-------------------------|
|
|
14
|
+
| **Full-page dashboard** | `app/(app)/dashboard/page.tsx` | `DashboardTabs`, `ChartsOverview` / gallery demos in `charts-overview.tsx` |
|
|
15
|
+
| **Data tab** on Placements / Team / Compliance | `PlacementsTable`, `TeamTable`, `ComplianceTable` → `*DashboardChartsSection` | `ChartFigure`, `ChartCard`, `useChartVariant()`, `data-view-dashboard-charts*.tsx` |
|
|
16
|
+
|
|
17
|
+
**MUST NOT** duplicate “another” chart system for Data view — extend **`charts-overview`** patterns and **`lib/chart-keyboard-selection`**.
|
|
18
|
+
|
|
19
|
+
## MUST — accessibility & data
|
|
20
|
+
|
|
21
|
+
1. **`ChartFigure`** + **`ChartDataTable`** (`sr-only`) for every chart on the Data dashboard — same as **`charts-overview.tsx`**.
|
|
22
|
+
2. **`ChartCard`** wraps chart content; **`KeyMetrics`** **`variant="card"`** for the **`key-metrics`** tile; KPI count **1–4** persisted in layout.
|
|
23
|
+
|
|
24
|
+
## MUST — keyboard selection (parity with `/dashboard` gallery)
|
|
25
|
+
|
|
26
|
+
- Import **`CHART_KBD_ACTIVE_BAR`** and **`CHART_KBD_ACTIVE_PIE_SHAPE`** from **`@/lib/chart-keyboard-selection`**.
|
|
27
|
+
- **Bar** series: **`activeBar={CHART_KBD_ACTIVE_BAR}`** + **`activeIndex={activeIndex ?? undefined}`** (and **`Cell`** only for per-bar **fill**, not opacity-only selection).
|
|
28
|
+
- **Pie / donut:** **`activeShape={CHART_KBD_ACTIVE_PIE_SHAPE}`** + **`activeIndex`** + slice **`stroke`** / **`strokeWidth`** consistent with gallery donuts.
|
|
29
|
+
- **MUST NOT** use **`fillOpacity` dimming alone** on **`Cell`** as the sole “selected” state for keyboard exploration.
|
|
30
|
+
|
|
31
|
+
## MUST — customisation UX
|
|
32
|
+
|
|
33
|
+
- **Edit layout** control: **`aria-label="Edit dashboard layout"`** (toolbar pen-ruler). Coach marks may target **`[aria-label='Edit dashboard layout']`**.
|
|
34
|
+
- On-canvas: drag reorder, remove, width (half / full), chart type, add/remove cards, reset. **No** separate Sheet for layout.
|
|
35
|
+
- While **`layoutEditMode`**: hide **`DataTableToolbar`** (search / filters / Properties row); **Done** / **Cancel** on canvas.
|
|
36
|
+
|
|
37
|
+
## MUST — persistence (centralized)
|
|
38
|
+
|
|
39
|
+
- **One bundle:** **`lib/data-view-dashboard-storage.ts`** — key **`exxat-ds:data-view-dashboards:v1`**, scopes **`placements` | `team` | `compliance`**.
|
|
40
|
+
- Placements helpers: **`loadDashboardLayout`** / **`saveDashboardLayout`** in **`data-view-dashboard-charts.tsx`** (wrap storage API).
|
|
41
|
+
- **MUST NOT** introduce parallel **`localStorage`** keys for the same **`DashboardLayout`** shape without updating the storage module.
|
|
42
|
+
|
|
43
|
+
## SHOULD — coach marks
|
|
44
|
+
|
|
45
|
+
- Register **customize dashboard** flows in **`lib/coach-mark-registry.ts`**; shared copy in **`lib/dashboard-customize-coach-mark.ts`**.
|
|
46
|
+
- Use **`useCoachMark`** **`enabled`** / **`dependsOnDismissedFlowId`** when a tour only applies on **dashboard** view or after another flow (**`COACH_MARK_FLOW_COMPLETED_EVENT`**).
|
|
47
|
+
|
|
48
|
+
## Reference files
|
|
49
|
+
|
|
50
|
+
- `components/data-view-dashboard-charts.tsx` (Placements)
|
|
51
|
+
- `components/data-view-dashboard-charts-team.tsx`, `data-view-dashboard-charts-compliance.tsx`
|
|
52
|
+
- `components/placements-table.tsx` — dashboard tab body wires `PlacementsDashboardChartsSection` + layout-edit toolbar inline (no separate `DashboardShell` component)
|
|
53
|
+
- `lib/chart-keyboard-selection.ts`, `lib/data-view-dashboard-storage.ts`, `lib/dashboard-customize-coach-mark.ts`
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
---
|
|
2
|
+
description: Exxat DS — product data tables must use DataTable with search, filters, and table properties; no alternate table stacks.
|
|
3
|
+
alwaysApply: true
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Exxat DS — data tables (mandatory pattern)
|
|
7
|
+
|
|
8
|
+
## Use one stack for product data lists
|
|
9
|
+
|
|
10
|
+
For **any app screen that shows a browsable, filterable grid of records** (lists, directories, placements, tokens, columns showcase, etc.):
|
|
11
|
+
|
|
12
|
+
1. **Inside `ListPageTemplate` (every primary hub + every showcase page that mounts a hub-style grid) MUST use `HubTable`** from `@/components/data-views`. `HubTable` is the **canonical** wrapper that wires `useTableState`, the toolbar (**search + filter chips + filter dropdown + sort**), the **Table properties drawer**, view-type tiles, bulk-actions, and conditional rules in one place. Pages that drop down to raw `<DataTable>` silently lose filters and Properties — **MUST NOT** ship a hub or showcase that way.
|
|
13
|
+
2. **Outside `ListPageTemplate`** (rare — e.g. embedded mini-grids, modal sub-tables, drawer body lists), use `DataTable` from `@/components/data-table` directly. Even then, prefer composing a small `toolbarSlot` with `TablePropertiesDrawerButton` whenever the grid is more than a handful of rows.
|
|
14
|
+
3. **Pagination:** Wrap with `DataTablePaginated` when server-style paging is required (Placements is the reference).
|
|
15
|
+
4. **Search:** `HubTable` wires the toolbar search automatically; only consumers that pass `searchable={false}` to `displayOptionsInit` can opt out, and they MUST justify it in the call-site comment.
|
|
16
|
+
5. **Filters:** Configure per-column `filter:` blocks in `ColumnDef` (text / select / date / number) — `HubTable` turns those into chips automatically via `columnsToFilterFields`. **MUST NOT** ship one-off filter inputs above the table that duplicate this.
|
|
17
|
+
6. **Table properties:** Always reachable. `HubTable` mounts `TablePropertiesDrawerButton` in `toolbarSlot`; on **`ListPageTemplate`** pages with **table / list / board / dashboard** tabs it **MUST** also receive **`currentView`** and **`onViewChange`** (see **`apps/web/AGENTS.md` §4.2** and **`.cursor/rules/exxat-table-properties-drawer.mdc`**) so Properties matches the selected view.
|
|
18
|
+
7. **Dropdown menus:** `DropdownMenuContent` uses the shared **`@exxatdesignux/ui`** default (**intrinsic `w-max`**, **`min-w-52`**, capped **`max-w`**) for view settings, row ⋯, column menus, and filter pickers — **pure CSS**, no **`ResizeObserver`**. Override only for deliberate narrow/wide rails (e.g. pagination **`w-20`**, account trigger-width, school switcher **`!w-max min-w-72 …`**). See **`docs/data-views-pattern.md`** (“Dropdown menus”).
|
|
19
|
+
|
|
20
|
+
**Reference implementations:**
|
|
21
|
+
|
|
22
|
+
- `components/placements-table.tsx` — full hub: paged table, board, dashboard, list, conditional rules, dashboard customize, bulk actions.
|
|
23
|
+
- `components/sites-table.tsx` — table + finder/board.
|
|
24
|
+
- `components/team-table.tsx` — table + dashboard + list.
|
|
25
|
+
- `components/columns-showcase.tsx` — minimal hub (single `table` view); good reference for showcase pages.
|
|
26
|
+
- `components/tokens-themes-client.tsx` — minimal hub + secondary panel scope.
|
|
27
|
+
|
|
28
|
+
## Do not
|
|
29
|
+
|
|
30
|
+
- Do **not** build product list pages with `@/components/ui/table` alone, raw `<table>` markup, or third-party data grids.
|
|
31
|
+
- Do **not** mount raw `<DataTable>` inside `ListPageTemplate.renderContent` — use `HubTable`. Raw `<DataTable>` does not ship the Properties drawer or filter chips; users lose discoverability.
|
|
32
|
+
- Do **not** introduce a second “table component” pattern for the same product surfaces (splitting search/filters/properties across incompatible implementations).
|
|
33
|
+
|
|
34
|
+
## Exceptions
|
|
35
|
+
|
|
36
|
+
- **Tiny, read-only tables inside charts or analytics cards** (e.g. chart figure captions / summary matrices) may use minimal markup when they are not primary data-list experiences — still prefer tokens and accessibility, but the full hub stack is not required there.
|
|
37
|
+
- **Drawer body and dialog sub-grids** (small, secondary, scoped to a transient flow) — raw `<DataTable>` is acceptable; still expose search if rows > ~10.
|
|
38
|
+
|
|
39
|
+
## See also
|
|
40
|
+
|
|
41
|
+
- **`apps/web/AGENTS.md`** — full MUST/MUST NOT, list-page template, primary hubs, checklist.
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
# Exxat DS — dedicated search surfaces
|
|
2
|
+
|
|
3
|
+
**Authoritative detail:** **`apps/web/AGENTS.md` §4.8**, **`.cursor/skills/exxat-dedicated-search-surfaces/SKILL.md`**.
|
|
4
|
+
|
|
5
|
+
## Intent
|
|
6
|
+
|
|
7
|
+
Some hubs use **one route** (or sibling routes) with **empty vs non-empty** primary search query:
|
|
8
|
+
|
|
9
|
+
- **Landing** — centered hero, composer, optional recents; no results grid (or minimal chrome).
|
|
10
|
+
- **Results** — `ListPageTemplate` + table/list driven by the same filtered row bag as the rest of the hub.
|
|
11
|
+
|
|
12
|
+
Shared building blocks use **generic** `DedicatedSearch*` names under `components/`, `components/templates/`, and `lib/dedicated-search-*.ts`. Domain code passes **`patchSearchParams`**, **recents controller**, and copy.
|
|
13
|
+
|
|
14
|
+
## MUST
|
|
15
|
+
|
|
16
|
+
- Keep **first paint** of recents **storage-free** (no `localStorage` in `useState` initial state) — see skill.
|
|
17
|
+
- Prefer **`DedicatedSearchLandingTemplate`**, **`DedicatedSearchUrlComposer`**, **`DedicatedSearchRecents`**, **`DedicatedSearchResultsHeaderChrome`**, **`DEDICATED_SEARCH_RESULTS_OUTER_CONTENT_CLASSNAME`** before copying markup into a new hub.
|
|
18
|
+
|
|
19
|
+
## MUST NOT
|
|
20
|
+
|
|
21
|
+
- Introduce parallel `*QuestionBankSearchLanding*` (or similar) components for another entity — extend the generic layer and compose in the hub client.
|
|
22
|
+
|
|
23
|
+
## See also
|
|
24
|
+
|
|
25
|
+
- **`exxat-list-page-connected-views.mdc`**, **`exxat-centralized-list-dataset.mdc`** — results branch still uses one row bag + `ListPageTemplate`.
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
---
|
|
2
|
+
description: Exxat DS — drawer/sheet vs modal dialog vs route for flows and confirmations.
|
|
3
|
+
alwaysApply: true
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Exxat DS — drawer vs dialog
|
|
7
|
+
|
|
8
|
+
## MUST
|
|
9
|
+
|
|
10
|
+
1. **Drawer / sheet** — Hub-**adjacent** work where **parent context** (list, filters, selection) stays relevant: properties, export, invites, long option lists beside the grid.
|
|
11
|
+
2. **Dialog** — **Blocking**, **short** focus: destructive confirm, legal/acknowledgment, single-step choice, alert when the user must not interact with the page behind until resolved.
|
|
12
|
+
3. **Route** — **Primary**, **long**, or **bookmarkable** flows — **`AGENTS.md` §6.4**, **`.cursor/rules/exxat-page-vs-drawer.mdc`**.
|
|
13
|
+
|
|
14
|
+
## MUST NOT
|
|
15
|
+
|
|
16
|
+
- Put **irreversible delete** only in a dismissible toast — use **dialog** (or drawer with explicit confirm) per **`exxat-no-toast.mdc`**.
|
|
17
|
+
- Use a **centered dialog** for **wide tables of export columns** when a **drawer** matches mental model and space.
|
|
18
|
+
|
|
19
|
+
## See also
|
|
20
|
+
|
|
21
|
+
- **`docs/drawer-vs-dialog-pattern.md`** · **`.cursor/skills/exxat-drawer-vs-dialog/SKILL.md`**
|
|
22
|
+
- **`exxat-page-vs-drawer.mdc`** (drawer vs **route**)
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
---
|
|
2
|
+
description: Exxat DS — follow AGENTS.md; DataTable, ListPageTemplate, primary hubs, export, Kbd
|
|
3
|
+
alwaysApply: true
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Exxat DS — AI handbook (binding)
|
|
7
|
+
|
|
8
|
+
**App location:** `apps/web/` in this **pnpm monorepo**. The legacy single-folder layout (`exxat-ds/`) was migrated in 2026-05; the path no longer exists. Shared design system lives at `packages/ui/` (`@exxatdesignux/ui`).
|
|
9
|
+
|
|
10
|
+
**Read `AGENTS.md`:** `apps/web/AGENTS.md` from the monorepo root, or `./AGENTS.md` when the workspace is the `apps/web/` folder only (same file).
|
|
11
|
+
|
|
12
|
+
Before implementing or reviewing **list / table / board / dashboard / data-heavy** pages, read **AGENTS.md** (rule precedence, MUST/MUST NOT, file references, §4.1–§4.8, **§6.4** page vs drawer, **§6.5** no toast, §7.1 command palette, §13 checklist). **Before** adding **new shared UI** not covered by existing **`components/`** patterns, read **`exxat-reuse-before-custom.mdc`**.
|
|
13
|
+
|
|
14
|
+
## Non‑negotiables (if anything conflicts, open AGENTS.md §12–§13)
|
|
15
|
+
|
|
16
|
+
1. **Product data lists** → `DataTable` + search + shared filters + `TablePropertiesDrawer` — not raw `<table>` / ui `Table` alone / ad-hoc grids. With **`ListPageTemplate`** view tabs, pass **`currentView`** + **`onViewChange`** into **`TablePropertiesDrawer`** (**`AGENTS.md` §4.2**, **`.cursor/rules/exxat-table-properties-drawer.mdc`**).
|
|
17
|
+
2. **Main `DataTable` surface** → wrapped in **`ListPageTemplate`** (view tabs). All tab view types share **`useTableState`**; list/board/dashboard read **`tableState.rows`**. Reference: `PlacementsClient`, `TeamClient`, `TeamTable`, `ComplianceClient`.
|
|
18
|
+
3. **Do not double-indent** the toolbar/table — avoid extra `px`/`mx` wrappers around `DataTable` when it already applies horizontal inset.
|
|
19
|
+
4. **Primary hub + large/complex data** → same composition as Placements/Team: `ListPageTemplate` + metrics/export pattern as in `PlacementsClient` / `TeamClient`, not `PageHeader`-only. **Do not** ship empty or "replace later" placeholder pages for nav-linked hubs (**`AGENTS.md` §4.1**).
|
|
20
|
+
5. **Exportable pages** → filled primary CTA; **⋯** menu with Export → `ExportDrawer` pattern (see `PlacementsPageHeader`).
|
|
21
|
+
6. **Keyboard hints** → `.cursor/rules/exxat-kbd-shortcuts.mdc`; pair hints with behavior.
|
|
22
|
+
7. **Accessibility** → `.cursor/rules/exxat-accessibility.mdc` + **`apps/web/AGENTS.md` §8** + `.cursor/skills/exxat-accessibility/SKILL.md`.
|
|
23
|
+
8. **Data view dashboard charts** → **`apps/web/AGENTS.md` §4.3** + **`apps/web/.cursor/rules/exxat-dashboard-view-charts.mdc`** (centralized storage, `chart-keyboard-selection`, `ChartFigure`).
|
|
24
|
+
9. **Board (kanban) cards** → **`apps/web/AGENTS.md` §4.4** + **`exxat-board-cards.mdc`** + **`.cursor/skills/exxat-board-cards/SKILL.md`** (`ListPageBoardCard`, **`ListHubStatusBadge`** + **`lib/list-status-badges.ts`**, primitives).
|
|
25
|
+
10. **List-page view shells** (folder / panel / centered non-table bodies) → **`apps/web/AGENTS.md` §4.5** + **`exxat-list-page-view-shells.mdc`** + **`.cursor/skills/exxat-list-page-view-shells/SKILL.md`** (`ListPageViewFrame`, **`components/data-views/`**).
|
|
26
|
+
11. **Centralized hub dataset + presentation** — **`apps/web/AGENTS.md` §4.1** / **§4.5** + **`.cursor/rules/exxat-centralized-list-dataset.mdc`** + **`.cursor/skills/exxat-centralized-list-dataset/SKILL.md`** — one **`useTableState`** row bag for **all** views + **`TablePropertiesDrawer`**; **`ListPageViewFrame`** + **`data-views/`** for shared chrome; **no** parallel mock arrays per **`DataListViewType`**.
|
|
27
|
+
12. **Font Awesome (product icons)** — **`.cursor/rules/exxat-fontawesome-icons.mdc`** — Kit in **`app/layout.tsx`**, **`fa-light` / `fa-solid`**, subset audit, **`aria-hidden`** on decorative **`<i>`**; pair with **`exxat-accessibility.mdc`** for icon-only controls.
|
|
28
|
+
13. **Monospace system IDs** — **`apps/web/AGENTS.md` §1 (item 9)** + **`.cursor/rules/exxat-mono-ids.mdc`** + **`.cursor/skills/exxat-mono-ids/SKILL.md`** — **`font-mono tabular-nums`** on question/record keys; mono **only** the ID token in mixed lines.
|
|
29
|
+
14. **Primary nav → secondary panel** (Question bank) — **`apps/web/AGENTS.md` §4.6** + **`.cursor/rules/exxat-primary-nav-secondary-panel.mdc`** — **`secondaryPanel`** + **`PANELS`** + **`useAutoPanel`**; **`--secondary-panel-bg`** brand elevation (**`apps/web/docs/shell-surface-elevation-pattern.md`**); **folder URL scope** → **`exxat-question-bank-hub-header.mdc`** + **`apps/web/docs/question-bank-hub-header-pattern.md`**.
|
|
30
|
+
15. **Collaboration & access** (shared hubs) — **`apps/web/AGENTS.md` §4.7** + **`.cursor/rules/exxat-collaboration-access.mdc`** + **`.cursor/skills/exxat-collaboration-access/SKILL.md`** — face rail, **`InviteCollaboratorsDrawer`**, **`lib/collaborator-access.ts`**.
|
|
31
|
+
16. **Dedicated search** (landing vs results, `DedicatedSearch*`) — **`apps/web/AGENTS.md` §4.8** + **`.cursor/rules/exxat-dedicated-search-surfaces.mdc`** + **`.cursor/skills/exxat-dedicated-search-surfaces/SKILL.md`**.
|
|
32
|
+
17. **No toast** → **`apps/web/AGENTS.md` §6.5** + **`exxat-no-toast.mdc`** — do not use **`toast()`** / Sonner / snackbars for product messaging; use banners, inline status, or dialogs.
|
|
33
|
+
18. **KPI trend polarity** (`KeyMetrics`, `*-kpi.ts`, chart mini-metrics) — **`docs/kpi-trend-pattern.md`** + **`.cursor/rules/exxat-kpi-trends.mdc`** + **`.cursor/skills/exxat-kpi-trends/SKILL.md`** — **`trend`** follows the data; set **`trendPolarity`** when “up” is not good news (e.g. defect counts, **low PBI flags**).
|
|
34
|
+
19. **Drawer vs dialog** (same-route overlays) — **`docs/drawer-vs-dialog-pattern.md`** + **`.cursor/rules/exxat-drawer-vs-dialog.mdc`** + **`.cursor/skills/exxat-drawer-vs-dialog/SKILL.md`** — drawers preserve hub context; dialogs for **blocking** short confirms.
|
|
35
|
+
20. **Cards vs table rows** — **`docs/card-vs-rows-pattern.md`** + **`.cursor/rules/exxat-card-vs-list-rows.mdc`** + **`.cursor/skills/exxat-card-vs-list-rows/SKILL.md`** — **`DataTable`** for dense comparable hubs; cards for kanban / visual browse (**`ListPageBoardCard`**).
|
|
36
|
+
21. **KPI strip max four** — **`docs/kpi-strip-max-four-pattern.md`** + **`.cursor/rules/exxat-kpi-max-four.mdc`** + **`.cursor/skills/exxat-kpi-max-four/SKILL.md`** — **≤ 4** `MetricItem` per primary **`KeyMetrics`** strip / Data-tab key-metrics card (**`KEY_METRICS_KPI_COUNT_MAX`**).
|
|
37
|
+
22. **KPI flat band** — **`docs/kpi-flat-band-pattern.md`** + **`.cursor/rules/exxat-kpi-flat-band.mdc`** + **`.cursor/skills/exxat-kpi-flat-band/SKILL.md`** — **`variant="flat"`**: transparent cells, OKLCH brand glow only, border hairlines (no grey panel).
|
|
38
|
+
23. **Reuse before custom** — **`exxat-reuse-before-custom.mdc`** — compose from **`components/`** + **`AGENTS.md` §9**; **ask the user** before new shared primitives or bespoke widgets unless the task already approved greenfield.
|
|
39
|
+
24. **Token discipline** — **`docs/token-taxonomy.md`** + **`.cursor/rules/exxat-token-discipline.mdc`** + **`packages/ui/tokens/hooks-index.json`** (163 tokens · 36 namespaces) — no hex literals in app code; no deprecated tokens; **prefer Exxat L0** (`--exxat-color-*`, `--exxat-radius-*`, `--exxat-spacing-*`) for new code (taxonomy §2.0 · rollout `docs/migrations/0002-exxat-token-namespace.md`); legacy L1 shadcn names stay as aliases. ESLint enforces via `exxat-ds/no-hex-color` + `exxat-ds/no-deprecated-tokens` in **`@exxatdesignux/eslint-plugin`** (workspace: **`packages/eslint-plugin-exxat-ds/`**).
|
|
40
|
+
25. **No SLDS leakage** — **`.cursor/rules/exxat-no-slds-leakage.mdc`** — no `slds-*` classes, no `<lightning-*>` markup, no SLDS token names, no synthetic-shadow assumptions. ESLint catches via `exxat-ds/no-slds-classes` + `exxat-ds/no-lightning-elements` (from **`@exxatdesignux/eslint-plugin`**).
|
|
41
|
+
26. **Blueprints + selection guide** — **`apps/web/docs/blueprints/`** + **`apps/web/docs/component-selection-guide.md`** — framework-agnostic specs + decision tree across the whole DS. Start there before composing a new hub.
|
|
42
|
+
27. **Migrations** — **`apps/web/docs/migrations/`** — every deprecation gets a numbered entry (`NNNN-<slug>.md`). Token deprecations surface in `tokens/hooks-index.json` as `deprecated: true` and are lint-flagged.
|
|
43
|
+
|
|
44
|
+
## Also read
|
|
45
|
+
|
|
46
|
+
- **`apps/web/docs/data-views-pattern.md`** — architecture narrative for list hubs. Includes **Page vs drawer** (§6.4 in `AGENTS.md`), **board UI** (§4.4), and **KPI trend polarity** → **`apps/web/docs/kpi-trend-pattern.md`**.
|
|
47
|
+
- **`apps/web/docs/command-menu-pattern.md`** — global ⌘K palette (search + quick AI vs Ask Leo).
|
|
48
|
+
- **`apps/web/docs/token-taxonomy.md`** — naming + deprecation policy for every CSS custom property the DS ships (semantic shadcn + brand / chip / chart / interactive / sidebar / control / radius / shadow / transition families).
|
|
49
|
+
- **`apps/web/docs/component-selection-guide.md`** — top-of-funnel decision tree for picking the right composition.
|
|
50
|
+
- **`apps/web/docs/blueprints/`** — framework-agnostic specs (start: `page-header.md`, `data-table.md`).
|
|
51
|
+
- **`apps/web/docs/migrations/`** — token rename + removal history.
|
|
52
|
+
- **`packages/ui/tokens/hooks-index.json`** — machine-readable token index (regenerate via `pnpm --filter @exxatdesignux/ui tokens:index`).
|
|
53
|
+
- `.cursor/rules/exxat-data-tables.mdc`, `exxat-list-page-connected-views.mdc`, **`exxat-centralized-list-dataset.mdc`**, **`exxat-list-page-view-shells.mdc`**, **`exxat-fontawesome-icons.mdc`**, **`exxat-mono-ids.mdc`**, **`exxat-primary-nav-secondary-panel.mdc`**, **`exxat-question-bank-hub-header.mdc`**, **`exxat-collaboration-access.mdc`**, **`exxat-dedicated-search-surfaces.mdc`**, **`exxat-kpi-trends.mdc`**, **`exxat-kpi-flat-band.mdc`**, **`exxat-drawer-vs-dialog.mdc`**, **`exxat-card-vs-list-rows.mdc`**, **`exxat-kpi-max-four.mdc`**, **`exxat-reuse-before-custom.mdc`**, `exxat-table-properties-drawer.mdc`, **`exxat-board-cards.mdc`**, **`exxat-page-vs-drawer.mdc`**, **`exxat-no-toast.mdc`**, **`exxat-command-menu.mdc`**, `exxat-kbd-shortcuts.mdc`, `exxat-accessibility.mdc` at repo root; **`apps/web/.cursor/rules/exxat-dashboard-view-charts.mdc`** for Data tab charts.
|
|
54
|
+
- **`apps/web/docs/kpi-flat-band-pattern.md`**, **`apps/web/docs/shell-surface-elevation-pattern.md`** — flat KPI strip + sidebar/secondary/page OKLCH stack.
|
|
55
|
+
- **`apps/web/docs/question-bank-hub-header-pattern.md`** — folder-scoped question bank header **Customize folder**.
|
|
56
|
+
- **`apps/web/docs/collaboration-access-pattern.md`** — shared hub face rail + invite sheet.
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
---
|
|
2
|
+
description: Font Awesome Pro icons — kit, weights, markup, subset audit, accessibility pairing
|
|
3
|
+
globs: apps/web/**/*.tsx
|
|
4
|
+
alwaysApply: false
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
# Exxat DS — Font Awesome icons
|
|
8
|
+
|
|
9
|
+
Product UI uses **Font Awesome 6 Pro** via the **Kit script** in **`apps/web/app/layout.tsx`** (not per-page ad-hoc CDNs). **Authoritative accessibility pairing** for decorative vs informational vs icon-only controls: **`.cursor/rules/exxat-accessibility.mdc`** (Case A/B/C).
|
|
10
|
+
|
|
11
|
+
## MUST
|
|
12
|
+
|
|
13
|
+
1. **Markup** — Use **`<i className="…" />`** with **`fa-*`** weight + icon classes (e.g. **`fa-light fa-folder`**, **`fa-solid fa-check`**). Put **`aria-hidden="true"`** on the **`<i>`** when the **accessible name** lives on a parent (**`Button` `aria-label`**, adjacent text, **`Tip`** on interactive controls).
|
|
14
|
+
2. **Weights** — Default inactive/ambient icons to **`fa-light`**; use **`fa-solid`** for **selected / active / strong emphasis** when the pattern already exists (e.g. sidebar rows, view tabs). Stay consistent within a surface.
|
|
15
|
+
3. **Class strings** — Prefer **static** `className` strings so **`pnpm --filter web fa:subset-audit`** (see **`apps/web/scripts/fontawesome-subset-audit.mjs`**) can discover glyphs for **Kit subsetting** (`fontawesome-subset.manifest.json` → [fontawesome.com/kits](https://fontawesome.com/kits) Icon Selection).
|
|
16
|
+
4. **Props APIs** — When a component accepts an icon, document **suffix only** (`fa-folder`) or **full classes** consistently with nearby code (**`lib/data-list-view.ts`**, **`lib/list-status-badges.ts`**, **`os-folder-glyph.tsx`**).
|
|
17
|
+
|
|
18
|
+
## SHOULD
|
|
19
|
+
|
|
20
|
+
- After adding **new** Font Awesome glyph names, run **`fa:subset-audit`** and refresh the **Kit** subset so production does not 404 missing icons.
|
|
21
|
+
- Reuse **shared** maps (**`DATA_LIST_VIEW_TILES`**, **`lib/list-status-badges.ts`**) instead of one-off **`fa-*`** strings for the same semantic concept.
|
|
22
|
+
|
|
23
|
+
## MUST NOT
|
|
24
|
+
|
|
25
|
+
- Add **second** icon systems for **product chrome** (duplicate Lucide/Phosphor/Heroicons for the same nav, table toolbar, or hub cards) when Font Awesome is already the standard for that surface.
|
|
26
|
+
- Put **meaningful** accessible names **only** on **`<i>`** without **`role`** / parent labelling — follow **Case B/C** in **`exxat-accessibility.mdc`**.
|
|
27
|
+
|
|
28
|
+
## See also
|
|
29
|
+
|
|
30
|
+
- **`apps/web/AGENTS.md`** — handbook; **§8** accessibility.
|
|
31
|
+
- **`.cursor/rules/exxat-accessibility.mdc`** — tooltips + **`aria-label`** for icon-only buttons.
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
---
|
|
2
|
+
description: Exxat DS — show Kbd hints on primary/secondary actions, search, Ask Leo; avoid browser-reserved chords.
|
|
3
|
+
alwaysApply: true
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Exxat DS — keyboard shortcuts (`Kbd`)
|
|
7
|
+
|
|
8
|
+
## When to show `Kbd`
|
|
9
|
+
|
|
10
|
+
Use `@/components/ui/kbd` (`Kbd` + `KbdGroup`) anywhere users discover actions by hovering or reading tooltips:
|
|
11
|
+
|
|
12
|
+
- **Primary actions** — main page CTAs (e.g. “New …”, “Save”, “Submit”).
|
|
13
|
+
- **Secondary actions** — overflow menus, “More”, outline companions to a primary button.
|
|
14
|
+
- **Global affordances** — **Search** (table toolbar), **Ask Leo**, **Toggle sidebar**.
|
|
15
|
+
|
|
16
|
+
## Rules
|
|
17
|
+
|
|
18
|
+
0. **`Kbd` variant MUST match its host surface** (this is the #1 recurring mistake):
|
|
19
|
+
|
|
20
|
+
| Where the `Kbd` renders | Required variant |
|
|
21
|
+
|-------------------------|------------------|
|
|
22
|
+
| Inside a `Button` (primary, secondary, wizard Next/Back/Submit, full-width CTAs in popovers) | **`variant="bare"`** — no bg/border, inherits `currentColor` @ 70 % |
|
|
23
|
+
| Inside a `TooltipContent` | **default `tile`** (no prop) |
|
|
24
|
+
| Inside a `DropdownMenuItem` via `shortcut=` | menu handles it — pass the chord string |
|
|
25
|
+
| Standalone helper text on a surface | **default `tile`** |
|
|
26
|
+
|
|
27
|
+
Glue multi-key chords into **one** bare kbd (`<Kbd variant="bare">⌘⌥K</Kbd>`), not one tile per key. See `new-placement-form.tsx` (Next = `{mod}⏎`, Back = `{mod}{alt}←`) and the primary "Ask Leo" button inside chart insight popovers.
|
|
28
|
+
|
|
29
|
+
1. **Pair hint with behavior** — If `Kbd` shows a chord, implement the same shortcut. **Preferred:** the shared primitives from `@/components/ui/dropdown-menu`:
|
|
30
|
+
|
|
31
|
+
```tsx
|
|
32
|
+
import { DropdownMenuItem, Shortcut } from "@/components/ui/dropdown-menu"
|
|
33
|
+
|
|
34
|
+
// Visual hint in a menu item:
|
|
35
|
+
<DropdownMenuItem shortcut="⌘⇧E" onSelect={onExport}>Export</DropdownMenuItem>
|
|
36
|
+
|
|
37
|
+
// Global binding — render in a parent that stays mounted (menu items unmount on close):
|
|
38
|
+
<Shortcut keys="⌘⇧E" onInvoke={onExport} />
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
The hook skips input/textarea/contenteditable targets and any open dialog. Accepts symbols (`⌘⇧⌥⌃⌫⌦⏎↑↓`) and words (`Cmd+Shift+D`, `Alt+P`). Avoid ad-hoc `document.addEventListener("keydown", …)` + `isEditableTarget` — use `<Shortcut>` instead.
|
|
42
|
+
2. **Modifier labels** — Use `useModKeyLabel()` (**⌘** / **Ctrl**) and `useAltKeyLabel()` (**⌥** / **Alt**) from `@/hooks/use-mod-key-label` for tooltips.
|
|
43
|
+
3. **Avoid browser-reserved chords** — Do **not** use combinations that match common browser defaults, including:
|
|
44
|
+
- **⌘⇧N / Ctrl+Shift+N** — private/incognito window
|
|
45
|
+
- **⌘⇧T / Ctrl+Shift+T** — reopen closed tab
|
|
46
|
+
- **⌘⇧O / Ctrl+Shift+O** — bookmark manager (Chromium)
|
|
47
|
+
- **⌘⇧B / Ctrl+Shift+B** — bookmarks bar
|
|
48
|
+
- **⌘L / Ctrl+L** — focus address bar (avoid plain **L** with only mod unless scoped)
|
|
49
|
+
- **⌃⌥L / Ctrl+Alt+L** — screen lock on many Linux desktops (avoid for in-app actions)
|
|
50
|
+
4. **Preferred pattern for app shortcuts** — Use **⌘⌥** / **Ctrl+Alt** + letter (e.g. **⌘⌥N** for “New”, **⌘⌥M** for “More”, **⌘⌥K** for Ask Leo). Table search stays **⌘K** / **Ctrl+K** **without** Alt so **⌘⌥K** does not collide.
|
|
51
|
+
5. **Tooltips** — `Tip` supports `label` as `React.ReactNode` so you can compose text + `KbdGroup`.
|
|
52
|
+
6. **Do not** decorate every control — skip dense tables, icon-only row actions that already have `aria-label`, and third-party widgets.
|
|
53
|
+
|
|
54
|
+
## Reference shortcuts (app)
|
|
55
|
+
|
|
56
|
+
| Action | Shortcut |
|
|
57
|
+
|--------|----------|
|
|
58
|
+
| Toggle main sidebar | ⌘/Ctrl + **B** (`components/ui/sidebar.tsx`) |
|
|
59
|
+
| Table search | ⌘/Ctrl + **K** (no Alt — `DataTable`) |
|
|
60
|
+
| Ask Leo | ⌘/Ctrl + **⌥/Alt** + **K** |
|
|
61
|
+
| New placement (Placements header) | ⌘/Ctrl + **⌥/Alt** + **N** |
|
|
62
|
+
| Placements overflow menu | ⌘/Ctrl + **⌥/Alt** + **M** |
|
|
63
|
+
| Export | ⌘/Ctrl + **⇧/Shift** + **E** |
|
|
64
|
+
| Hide/Show metric section | ⌘/Ctrl + **⌥/Alt** + **H** |
|
|
65
|
+
| Rename (view, tab) | **F2** |
|
|
66
|
+
| Duplicate | ⌘/Ctrl + **D** |
|
|
67
|
+
| Review / Info | ⌘/Ctrl + **I** |
|
|
68
|
+
| Remove / Delete | ⌘/Ctrl + **⌫** |
|
|
69
|
+
| Add view (1..n) | **1..9** (plain digit; skipped in inputs / open dialogs) |
|
|
70
|
+
| **Submit a workflow** (Create, Save, Export, Apply) | **Enter** (⏎) — scoped to the form/drawer/dialog |
|
|
71
|
+
| **Cancel / dismiss** a workflow | **Esc** (Radix handles for Dialog/Sheet) |
|
|
72
|
+
| **Advance a multi-step wizard** | ⌘/Ctrl + **Enter** (plain Enter stays in the input) |
|
|
73
|
+
| **Back** in a wizard | ⌘/Ctrl + **⌥/Alt** + **←** |
|
|
74
|
+
|
|
75
|
+
## Every workflow primary/secondary action MUST carry shortcuts
|
|
76
|
+
|
|
77
|
+
Every **workflow surface** (form, dialog, drawer, sheet, multi-step wizard final step) MUST bind:
|
|
78
|
+
|
|
79
|
+
1. **Primary action (submit/commit)** — **Enter** (⏎). Render the `<Kbd>⏎</Kbd>` **inline inside the button** (after the label, inside a `<KbdGroup className="ml-1.5">`) — NOT inside a hover `Tip`. Primary/secondary workflow buttons must expose the shortcut at rest so it is discoverable without hovering. Pair with a `<Shortcut keys="Enter" onInvoke={...}>` mounted while the surface is open. The shared `useShortcut` hook skips events from inputs/textarea/contenteditable, so Enter inside a text field still types normally — it only fires when focus is on the surface chrome.
|
|
80
|
+
2. **Secondary action (Cancel/Dismiss)** — **Esc**. Inline `<Kbd>Esc</Kbd>` inside the Cancel button (same `ml-1.5` pattern). Radix `Dialog` / `Sheet` / `AlertDialog` already bind Esc natively.
|
|
81
|
+
|
|
82
|
+
> Tip-on-hover Kbd hints remain correct for **page-level** actions (e.g. "New placement", ⋯ overflow triggers) where the button is part of dense page chrome and a persistent Kbd would crowd the layout. Workflow buttons inside a form/drawer/dialog are spacious enough to render the Kbd inline.
|
|
83
|
+
|
|
84
|
+
**Variant inside a button:** always use `<Kbd variant="bare">` — no background, no border, inherits `currentColor` at 70% opacity. The default tile variant looks like a pasted-on patch on filled primary buttons. Glue multi-key chords into one `<Kbd variant="bare">⌘⌥←</Kbd>` rather than one tile per key.
|
|
85
|
+
3. **Multi-step wizards** — plain **Enter** must NOT submit on intermediate steps (it would auto-close the review/final step when users hit Enter inside an input). Either:
|
|
86
|
+
- Gate `form.onSubmit` on `step === lastStep` (`if (step !== N) { e.preventDefault(); return }`), **or**
|
|
87
|
+
- Remove `type="submit"` on intermediate Next buttons and bind **⌘Enter** to "Next" via `<Shortcut>`.
|
|
88
|
+
On the final step, plain **Enter** submits and the Kbd hint shows **⏎**.
|
|
89
|
+
4. Examples in-app: `new-placement-form.tsx` (Create placement = Enter on step 5, Back = ⌘⌥←), `export-drawer.tsx` (Export = Enter, Cancel = Esc).
|
|
90
|
+
|
|
91
|
+
## Every action menu MUST carry shortcuts
|
|
92
|
+
|
|
93
|
+
All dropdown action menus (⋯ overflow, view-settings chevron, Add view, row actions) should declare a `shortcut=` on each `DropdownMenuItem` AND pair it with a `<Shortcut>` in a parent that stays mounted. This covers both discoverability (visual hint) and operability (global key binding).
|
|
94
|
+
|
|
95
|
+
Adjust this table when adding new global shortcuts.
|
|
96
|
+
|
|
97
|
+
## See also
|
|
98
|
+
|
|
99
|
+
- **`apps/web/AGENTS.md`** §7 — keyboard rules in project context.
|
|
100
|
+
- **`apps/web/AGENTS.md`** §7.1 — global command palette (⌘K) vs **Ask Leo** (**⌘⌥K**); **`apps/web/docs/command-menu-pattern.md`**.
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
---
|
|
2
|
+
description: KeyMetrics variant flat — transparent band, brand glow only, OKLCH hairlines
|
|
3
|
+
globs: apps/web/components/**/*key-metrics*,apps/web/app/globals.css,apps/web/docs/kpi*.md
|
|
4
|
+
alwaysApply: false
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
# Exxat DS — KPI flat band (`variant="flat"`)
|
|
8
|
+
|
|
9
|
+
**Authoritative detail:** **`apps/web/docs/kpi-flat-band-pattern.md`**, **`.cursor/skills/exxat-kpi-flat-band/SKILL.md`**.
|
|
10
|
+
|
|
11
|
+
## MUST
|
|
12
|
+
|
|
13
|
+
1. **`KeyMetrics variant="flat"`** on list hubs / dashboard mix — **no** opaque band surface; section background is **only** `--key-metrics-flat-band-radial` (brand glow).
|
|
14
|
+
2. **Cells** — **`bg-transparent`**; hairlines via **`flatMetricsHairlineClass`** (cell **borders**, not `gap-px` grid fill).
|
|
15
|
+
3. **Four tiles** — default **4-across** verticals between columns; **2×2** hairlines only when `@container` is narrow (`@[max-width:29.99rem]`). **No** horizontal rule in 4-across layout.
|
|
16
|
+
4. **OKLCH** — `--key-metrics-flat-divider`, glow stops via `color-mix(in oklch, var(--brand-color) …)`; divider uses `var(--sidebar-border)` mix. **Do not** hardcode rose/indigo on one product for all themes.
|
|
17
|
+
5. **`--key-metrics-flat-band-shadow: none`** on flat band. **≤ 4** tiles — **`exxat-kpi-max-four.mdc`**.
|
|
18
|
+
|
|
19
|
+
## MUST NOT
|
|
20
|
+
|
|
21
|
+
- Stack linear gradients, `bg-background` on cells, or `gap-px` + tinted grid background on flat KPI (reads as a grey/lavender **box**).
|
|
22
|
+
- Use **`variant="card"`** for **`ListPageTemplate`** metrics when the strip should sit on the page canvas.
|
|
23
|
+
- Reintroduce **`lg:border-l`** on insight column when `variant="flat"` (insight card ring is enough).
|
|
24
|
+
|
|
25
|
+
## See also
|
|
26
|
+
|
|
27
|
+
- **`exxat-kpi-max-four.mdc`**, **`exxat-kpi-trends.mdc`**, **`exxat-list-page-connected-views.mdc`**
|
|
28
|
+
- **`exxat-primary-nav-secondary-panel.mdc`** — shell elevation (separate from KPI band)
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
---
|
|
2
|
+
description: Exxat DS — at most four KPI tiles on primary hub strips and key-metrics dashboard cards.
|
|
3
|
+
alwaysApply: true
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Exxat DS — KPI strip (max four)
|
|
7
|
+
|
|
8
|
+
## MUST
|
|
9
|
+
|
|
10
|
+
1. **Cap visible KPIs at four** on **`ListPageTemplate`** metric strips and on **Data tab** **`key-metrics`** dashboard cards — align with **`KEY_METRICS_KPI_COUNT_MAX`** in **`lib/dashboard-layout-merge.ts`** and **`clampKeyMetricsKpiCount`** when persisting layout.
|
|
11
|
+
2. **KPI helpers** (`*-kpi.ts`) return **≤ 4** `MetricItem` entries for those surfaces, or **`.slice(0, 4)`** after prioritization.
|
|
12
|
+
3. **Overflow narrative** — Push secondary stats into **`MetricInsight`**, charts, or another section — not a fifth headline tile.
|
|
13
|
+
|
|
14
|
+
## MUST NOT
|
|
15
|
+
|
|
16
|
+
- Render **five or more** KPI tiles in a single **`KeyMetrics`** row/band meant as the **primary** summary for a hub or the **key-metrics** card.
|
|
17
|
+
- Raise **`KEY_METRICS_KPI_COUNT_MAX`** without design-system review.
|
|
18
|
+
|
|
19
|
+
## See also
|
|
20
|
+
|
|
21
|
+
- **`docs/kpi-strip-max-four-pattern.md`** · **`docs/kpi-trend-pattern.md`** · **`docs/kpi-flat-band-pattern.md`** · **`.cursor/skills/exxat-kpi-max-four/SKILL.md`**
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
---
|
|
2
|
+
description: Exxat DS — KPI deltas and trend arrows must be contextual; use trendPolarity when “up” is not good news.
|
|
3
|
+
alwaysApply: true
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Exxat DS — KPI trends (`KeyMetrics` + chart mini-metrics)
|
|
7
|
+
|
|
8
|
+
## MUST
|
|
9
|
+
|
|
10
|
+
1. **`trend` matches reality** — `up` / `down` / `neutral` reflects the **signed change** in the metric; arrows are not “spin for optimism”.
|
|
11
|
+
2. **Set `trendPolarity` on `MetricItem`** when an increase is **not** favorable:
|
|
12
|
+
- **`lower_is_better`** — defect / error / overdue / **low PBI or quality-flag counts**, cost or time when the product goal is to **reduce**.
|
|
13
|
+
- **`informational`** — volume or mix where **direction is not** inherently good or bad (library size, % split between categories); tints stay **muted**, arrows still show direction.
|
|
14
|
+
3. **Default** — Omitting `trendPolarity` means **`higher_is_better`** (legacy): up = positive tint, down = negative tint.
|
|
15
|
+
4. **`delta` is a count, `description` is a caption.** **`delta`** (next to the arrow) is a **numeric change** like `"+5"`, `"-3"`, `"+12%"`. Contextual prose like `"left + right"`, `"vs last week"`, `"across 4 sites"` goes in **`MetricItem.description`** which renders **below** the value row (muted, small). **MUST NOT** stuff prose into **`delta`**.
|
|
16
|
+
5. **Hide the trend chip when there is nothing to say.** If **`trend === "neutral"`** **and** **`delta`** is empty (`""` / `0` / unset), `KeyMetrics` suppresses the chip entirely — no `—` placeholder. Use **`description`** for the supporting caption instead. Only show the chip when the metric has a real direction (`up` / `down`) or a real count to surface.
|
|
17
|
+
6. **Contextual copy** — `label` + `value` + (`delta` when present) + period header should read as one sentence; avoid orphan deltas.
|
|
18
|
+
7. **Accessibility** — Do not rely on colour alone; keep delta text + icon; chip `aria-label` comes from **`metricTrendAriaQualifier`** in **`components/key-metrics.tsx`**.
|
|
19
|
+
|
|
20
|
+
## MUST NOT
|
|
21
|
+
|
|
22
|
+
- Paint an **up** arrow with the “good” tint when the metric is **worse** when it goes up (unless **`trendPolarity: "lower_is_better"`** is set so “up” correctly tints **destructive**).
|
|
23
|
+
- Use **`ResizeObserver`** or JS layout measurement **only** to pick trend colours — polarity is a **product** decision, not a layout one.
|
|
24
|
+
- Render an **empty `—`** trend chip just to keep the layout symmetric. If a metric has no comparison this period, leave **`delta`** empty and let **`KeyMetrics`** hide the chip.
|
|
25
|
+
- Put words like **"left + right"**, **"hidden"**, **"shown"**, **"vs last week"** in **`delta`** — they are not deltas. Put them in **`description`**.
|
|
26
|
+
|
|
27
|
+
## See also
|
|
28
|
+
|
|
29
|
+
- **`docs/kpi-trend-pattern.md`** (app) — narrative + table of examples.
|
|
30
|
+
- **`.cursor/skills/exxat-kpi-trends/SKILL.md`** — checklist for new hubs.
|
|
31
|
+
- **`components/key-metrics.tsx`** — `MetricTrendPolarity`, `metricTrendTone`, `metricTrendAriaQualifier`.
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
---
|
|
2
|
+
description: ListPageTemplate — shared table state across views, mock + KPI helpers, dashboard tab
|
|
3
|
+
alwaysApply: true
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Exxat DS — list page connected views
|
|
7
|
+
|
|
8
|
+
**Authoritative detail:** **`apps/web/AGENTS.md` §4.1** and **`apps/web/docs/data-views-pattern.md`** (mock data, connected views, dashboard view).
|
|
9
|
+
|
|
10
|
+
## When building `ListPageTemplate` + data client
|
|
11
|
+
|
|
12
|
+
1. **One `useTableState` per tab’s table** — Pass full mock/API rows into a single table component; **`list` / `board` / `dashboard`** surfaces consume **`tableState.rows`** (same filters/search/sort as the grid).
|
|
13
|
+
2. **`renderContent`** — Always pass **`view={tab.viewType}`**; use **`key={tab.id}`** (not `viewType`) so switching views does not reset table state. Pass **`onViewChange`** into the table component so **`TablePropertiesDrawer`** stays aligned (**`currentView`** + **`updateTab({ viewType, icon: dataListViewIcon(viewType) })`** — see **`apps/web/AGENTS.md` §4.2** and **`.cursor/rules/exxat-table-properties-drawer.mdc`**).
|
|
14
|
+
3. **Mock data** — Typed arrays in **`lib/mock/<entity>.ts`**; KPI builders in **`lib/mock/<entity>-kpi.ts`** returning **`MetricItem[]`** / **`MetricInsight`** from **`@/components/key-metrics`**.
|
|
15
|
+
4. **Dashboard view tab** — Use **`KeyMetrics`** (`variant="flat"` or `"card"`) and the **same** KPI functions with **`tableState.rows`**. Do **not** add standalone `Card` metric grids that duplicate those numbers. For chart-heavy dashboards reuse **`ChartsOverview`** / **`DashboardTabs`** patterns from the main dashboard route when appropriate.
|
|
16
|
+
5. **List hub metrics strip** — Prefer **`KeyMetrics variant="flat"`** on **`ListPageTemplate`** **`metrics`** slot (transparent band, brand glow only) — **`docs/kpi-flat-band-pattern.md`**, **`.cursor/rules/exxat-kpi-flat-band.mdc`**.
|
|
17
|
+
6. **MUST NOT** ship “not wired” / “switch to table” placeholders for list/board/dashboard when the stack supports those views.
|
|
18
|
+
7. **MUST NOT** add a **primary nav** destination that is only placeholder copy with no **`ListPageTemplate`** hub, mock rows, and wired views — see **`apps/web/AGENTS.md` §4.1** (no empty hubs).
|
|
19
|
+
|
|
20
|
+
## See also
|
|
21
|
+
|
|
22
|
+
- **`.cursor/rules/exxat-centralized-list-dataset.mdc`** — single **`tableState.rows`** source for every hub view, inspectors, and **`TablePropertiesDrawer`** on the same **`DataTable`**.
|
|
23
|
+
- **Centered view bodies + reusable shells:** **`apps/web/AGENTS.md` §4.5**, **`.cursor/rules/exxat-list-page-view-shells.mdc`**, **`ListPageViewFrame`** in **`components/data-views/list-page-view-frame.tsx`**.
|
|
24
|
+
- **Flat KPI band:** **`docs/kpi-flat-band-pattern.md`**, **`.cursor/rules/exxat-kpi-flat-band.mdc`**.
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
---
|
|
2
|
+
description: Exxat DS — centered reusable shells for list-page views (not page-specific markup)
|
|
3
|
+
globs: apps/web/components/**/*.tsx
|
|
4
|
+
alwaysApply: false
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
# Exxat DS — list-page view shells (centered, reusable)
|
|
8
|
+
|
|
9
|
+
## Intent
|
|
10
|
+
|
|
11
|
+
**View bodies** under `ListPageTemplate` (table, list, board, dashboard, **folder**, **panel**, and future view types) **MUST** share one **layout primitive** for horizontal gutter and optional **centered max-width** on wide viewports. **MUST NOT** copy `mx-4 lg:mx-6` + `mx-auto max-w-*` per feature file or bake view-only layout into a single route.
|
|
12
|
+
|
|
13
|
+
Domain logic (columns, tiles, folder trees) stays in **`*-table.tsx` / `*-client.tsx`**; **chrome and rhythm** use **`ListPageViewFrame`** from **`@/components/data-views/list-page-view-frame`** (re-exported from **`@/components/data-views`**). **Data** for those branches still comes from the **same** **`tableState.rows`** / hub state as the grid — see **`.cursor/rules/exxat-centralized-list-dataset.mdc`**.
|
|
14
|
+
|
|
15
|
+
## MUST
|
|
16
|
+
|
|
17
|
+
1. Wrap **non-`DataTable`** view branches (icon folder grid, OS-style explorer, empty folder states, comparable dashboard **sections** that are not the main grid) in **`ListPageViewFrame`**, passing **`maxWidthClassName`** when the design calls for a centered cap (defaults: **`LIST_PAGE_VIEW_FRAME_MAX_ICON_GRID`** (`max-w-6xl`), **`LIST_PAGE_VIEW_FRAME_MAX_WIDE`** (`max-w-7xl`)).
|
|
18
|
+
2. Add **new reusable view surfaces** under **`components/data-views/`** with **generic props** (`rows`, `renderTile`, `getRowId`, etc.) — same pattern as **`FolderGridView`**, **`FinderPanelView`**, **`ListPageBoardTemplate`**. Page files **compose** them; they **MUST NOT** own grid/folder markup.
|
|
19
|
+
3. When extracting an entity-specific view (e.g. question OS folders), plan a **generic** `*View` in **`data-views/`** plus a thin adapter if the product still needs typed mock wiring.
|
|
20
|
+
|
|
21
|
+
## MUST NOT
|
|
22
|
+
|
|
23
|
+
- Wrap **`DataTable`** (or its outer toolbar shell) in **`ListPageViewFrame`** if that **duplicates** horizontal inset already applied by **`DataTable`** / **`DataTableToolbar`** — see **`AGENTS.md` §5** (double indent).
|
|
24
|
+
- Ship **view-only** layout classes only inside **`app/(app)/.../page.tsx`** for a hub that other entities will mirror — belong in **`data-views/`** or **`templates/`**.
|
|
25
|
+
|
|
26
|
+
## See also
|
|
27
|
+
|
|
28
|
+
- **`apps/web/AGENTS.md` §4.5** — handbook table + constants.
|
|
29
|
+
- **`apps/web/docs/data-views-pattern.md`** — “View layout frame”.
|
|
30
|
+
- **`.cursor/rules/exxat-centralized-list-dataset.mdc`** — **`tableState.rows`** into every view branch.
|
|
31
|
+
- **`.cursor/skills/exxat-list-page-view-shells/SKILL.md`** — step-by-step for agents.
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
---
|
|
2
|
+
description: Exxat DS — monospace typography for record IDs, question IDs, and other system identifiers
|
|
3
|
+
globs: apps/web/**/*.tsx
|
|
4
|
+
alwaysApply: false
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
# Exxat DS — monospace IDs
|
|
8
|
+
|
|
9
|
+
Use this when rendering **system identifiers** — values a user copies, searches, or matches in APIs and tables (not human-readable names or prose).
|
|
10
|
+
|
|
11
|
+
## MUST
|
|
12
|
+
|
|
13
|
+
1. **Class** — Wrap identifier text in **`font-mono tabular-nums`**. Add size/color from context: typically **`text-xs text-muted-foreground`** (secondary line, table meta) or **`text-sm`** when the ID is the primary label in a narrow cell.
|
|
14
|
+
2. **What counts as an ID** — Question IDs (`questionId`, `Q-YYMM-XXXX`), record/entity keys shown in UI, folder/surface technical keys when displayed as identifiers, hex tokens in pickers, audit/log principals, site/row **`id`** columns meant for lookup.
|
|
15
|
+
3. **Mixed lines** — When an ID sits beside prose (e.g. page subtitle), only the ID segment is mono; keep separators and labels in the default sans stack.
|
|
16
|
+
|
|
17
|
+
## SHOULD
|
|
18
|
+
|
|
19
|
+
- Match existing hubs: **`question-bank-table.tsx`**, **`question-bank-list-view.tsx`**, **`new-question-composer.tsx`** (header subtitle), **`sites-table.tsx`** (`row.id`).
|
|
20
|
+
- Prefer **`truncate`** / **`min-w-0`** on mono IDs in tight layouts so long tokens do not blow out columns.
|
|
21
|
+
|
|
22
|
+
## MUST NOT
|
|
23
|
+
|
|
24
|
+
- Apply **`font-mono`** to **person names**, **folder display names**, **status labels**, **dates**, **counts**, **currency**, or **body copy** — only the identifier token.
|
|
25
|
+
- Use mono for **option letters** (A/B/C) or **step numbers** unless they are literal system IDs.
|
|
26
|
+
|
|
27
|
+
## See also
|
|
28
|
+
|
|
29
|
+
- **`.cursor/skills/exxat-mono-ids/SKILL.md`**
|
|
30
|
+
- **`apps/web/AGENTS.md`** — §1 item on IDs, §13 checklist
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
# Exxat DS — no SLDS leakage
|
|
2
|
+
|
|
3
|
+
**Context:** Some agents have access to other repos, including the **Salesforce
|
|
4
|
+
`design-system-2-starter-kit`** (LWC + SLDS 2 / Cosmos). Patterns there look
|
|
5
|
+
similar at a glance (`page-header`, `data-table`, `card`) but the
|
|
6
|
+
**implementations are not portable** — they assume LWC, synthetic shadow,
|
|
7
|
+
SLDS class systems, and the Salesforce platform.
|
|
8
|
+
|
|
9
|
+
This rule prevents accidental cross-pollination from any **Salesforce / SLDS**
|
|
10
|
+
codebase into **`apps/web`** or **`packages/ui`**.
|
|
11
|
+
|
|
12
|
+
## MUST NOT
|
|
13
|
+
|
|
14
|
+
1. **CSS class strings** — Do **not** introduce **`slds-*`** classes
|
|
15
|
+
(`slds-page-header`, `slds-m-around_*`, `slds-grid`, `slds-button`,
|
|
16
|
+
`slds-text-*`, etc.) anywhere in `apps/web/**` or `packages/ui/**`. The
|
|
17
|
+
Exxat stack is **Tailwind v4** + the token system documented in
|
|
18
|
+
[`apps/web/docs/token-taxonomy.md`](mdc:apps/web/docs/token-taxonomy.md).
|
|
19
|
+
2. **LWC markup** — Do **not** render `<lightning-*>` tags
|
|
20
|
+
(`<lightning-button>`, `<lightning-datatable>`, `<lightning-card>`,
|
|
21
|
+
`<lightning-icon>`, etc.) or import from `lightning/*` modules. Use the
|
|
22
|
+
shadcn-style primitives in `packages/ui/src/components/ui/` and the
|
|
23
|
+
Exxat compositions in `apps/web/components/`.
|
|
24
|
+
3. **Synthetic-shadow assumptions** — Do **not** call `template.querySelector`,
|
|
25
|
+
`slds-color-scheme_dark`, `shadowRoot === null` checks, or anything that
|
|
26
|
+
only makes sense under Salesforce synthetic shadow. The Next.js app uses
|
|
27
|
+
the real DOM + Radix portals.
|
|
28
|
+
4. **SLDS styling-hook vars** — Do **not** use SLDS custom properties
|
|
29
|
+
(`--slds-g-color-surface-*`, `--slds-g-color-on-surface-*`,
|
|
30
|
+
`--slds-g-color-border-*`, `--slds-g-color-accent-*`, etc.). The Exxat
|
|
31
|
+
equivalents are documented in
|
|
32
|
+
[`apps/web/docs/token-taxonomy.md`](mdc:apps/web/docs/token-taxonomy.md):
|
|
33
|
+
surface → `--background` / `--card` / `--secondary-panel-bg`; ink →
|
|
34
|
+
`--foreground` / `--muted-foreground`; border → `--border` /
|
|
35
|
+
`--border-control` family; brand → `--brand-color` family.
|
|
36
|
+
5. **SLDS theme switching** — Do **not** add UI for selecting "SLDS 1" vs
|
|
37
|
+
"SLDS 2". Exxat ships **Exxat One** (lavender) and **Exxat Prism** (rose)
|
|
38
|
+
themes via `.theme-one` / `.theme-prism` classes — see
|
|
39
|
+
`docs/shell-surface-elevation-pattern.md`.
|
|
40
|
+
6. **Slot-vs-prop confusion** — Do **not** import LWC slot conventions
|
|
41
|
+
(`slot="actions"`, `<slot name="…">`) into React components. React uses
|
|
42
|
+
`children` + named props (`actions={…}`, `header={…}`).
|
|
43
|
+
7. **`lightning-base-components` patterns inside React** — Do **not** add
|
|
44
|
+
per-page form-input wrappers like `lightning-input` clones. Use shadcn
|
|
45
|
+
`Input` / `Select` / `Combobox` from `packages/ui`.
|
|
46
|
+
|
|
47
|
+
## SHOULD
|
|
48
|
+
|
|
49
|
+
- If you're comparing SLDS patterns to gain inspiration (e.g. the
|
|
50
|
+
`object-home` / `record-home` / `related-list` variant model from
|
|
51
|
+
`ui-page-header`), **document the idea** as a blueprint under
|
|
52
|
+
[`apps/web/docs/blueprints/`](mdc:apps/web/docs/blueprints) — do **not**
|
|
53
|
+
copy SLDS markup verbatim.
|
|
54
|
+
- For any "but SLDS does it this way" thought, check
|
|
55
|
+
[`apps/web/docs/component-selection-guide.md`](mdc:apps/web/docs/component-selection-guide.md)
|
|
56
|
+
first to see what Exxat ships for that pattern.
|
|
57
|
+
|
|
58
|
+
## Why this rule exists
|
|
59
|
+
|
|
60
|
+
Salesforce's design system is excellent — but it is **built for a different
|
|
61
|
+
runtime** (LWC + synthetic shadow + classic SLDS layered with SLDS 2 /
|
|
62
|
+
Cosmos). Mixing its CSS class system into a Tailwind v4 + OKLCH token app
|
|
63
|
+
silently breaks:
|
|
64
|
+
|
|
65
|
+
- **Theming** — `slds-*` classes don't react to `.theme-prism` / `.dark` /
|
|
66
|
+
`[data-contrast="high"]`.
|
|
67
|
+
- **Accessibility** — SLDS 1 contrast ratios differ from Exxat's WCAG 2.1 AA
|
|
68
|
+
targets; mixing them produces unverifiable composites.
|
|
69
|
+
- **Bundling** — Importing `@salesforce-ux/design-system` would balloon the
|
|
70
|
+
Next.js bundle and pull in classic SLDS that we explicitly chose not to use.
|
|
71
|
+
|
|
72
|
+
## See also
|
|
73
|
+
|
|
74
|
+
- [`apps/web/docs/token-taxonomy.md`](mdc:apps/web/docs/token-taxonomy.md) — Exxat tokens
|
|
75
|
+
- [`apps/web/docs/blueprints/`](mdc:apps/web/docs/blueprints) — framework-agnostic specs
|
|
76
|
+
- [`apps/web/docs/component-selection-guide.md`](mdc:apps/web/docs/component-selection-guide.md) — what to reach for
|
|
77
|
+
- [`.cursor/rules/exxat-token-discipline.mdc`](mdc:.cursor/rules/exxat-token-discipline.mdc) — token-level enforcement
|
|
78
|
+
- [`.cursor/rules/exxat-reuse-before-custom.mdc`](mdc:.cursor/rules/exxat-reuse-before-custom.mdc) — ask before adding new primitives
|