@exxatdesignux/ui 0.2.19 → 0.4.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 +662 -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 +43 -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-library-hub-header.mdc +28 -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-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 +3 -3
- package/consumer-extras/cursor-skills/exxat-centralized-list-dataset/SKILL.md +5 -16
- package/consumer-extras/cursor-skills/exxat-collaboration-access/SKILL.md +3 -3
- package/consumer-extras/cursor-skills/exxat-dedicated-search-surfaces/SKILL.md +2 -2
- package/consumer-extras/cursor-skills/exxat-ds-skill/SKILL.md +19 -34
- package/consumer-extras/cursor-skills/exxat-ds-skill/references/data-table-pattern.md +1 -1
- package/consumer-extras/cursor-skills/exxat-kpi-flat-band/SKILL.md +1 -1
- package/consumer-extras/cursor-skills/exxat-list-page-view-shells/SKILL.md +1 -1
- package/consumer-extras/cursor-skills/exxat-mono-ids/SKILL.md +4 -4
- package/consumer-extras/cursor-skills/exxat-primary-nav-secondary-panel/SKILL.md +10 -12
- package/consumer-extras/cursor-skills/exxat-token-economy/SKILL.md +277 -0
- package/consumer-extras/handbook/HANDBOOK.md +187 -0
- package/consumer-extras/handbook/glossary.md +58 -0
- package/consumer-extras/handbook/reference-implementations.md +153 -0
- package/consumer-extras/handbook/voice-and-tone.md +262 -0
- package/consumer-extras/patterns/collaboration-access-pattern.md +7 -7
- 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 +31 -66
- package/consumer-extras/patterns/kpi-flat-band-pattern.md +2 -2
- 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 +173 -0
- package/dist/components/data-views/hub-table.js +5783 -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 +6797 -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 +13421 -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 +259 -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 +606 -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/.claude/skills/exxat-ds-skill/SKILL.md +8 -7
- package/template/.cursor/rules/exxat-accessibility.mdc +1 -1
- package/template/.cursor/rules/exxat-command-menu.mdc +2 -2
- package/template/.cursor/rules/exxat-dashboard-view-charts.mdc +7 -7
- package/template/.cursor/rules/exxat-data-tables.mdc +3 -3
- package/template/.cursor/rules/exxat-ds-agents.mdc +2 -2
- package/template/.cursor/rules/exxat-kbd-shortcuts.mdc +7 -7
- package/template/.cursor/rules/exxat-mono-ids.mdc +1 -1
- package/template/.cursor/rules/exxat-page-vs-drawer.mdc +1 -1
- package/template/.cursor/rules/exxat-table-properties-drawer.mdc +1 -1
- package/template/AGENTS.md +135 -103
- package/template/app/(app)/columns/page.tsx +11 -0
- package/template/app/(app)/dashboard/loading.tsx +15 -3
- package/template/app/(app)/dashboard/page.tsx +14 -2
- package/template/app/(app)/layout.tsx +17 -4
- package/template/app/(app)/library/all/page.tsx +11 -0
- package/template/app/(app)/library/find/page.tsx +12 -0
- package/template/app/(app)/{question-bank → library}/layout.tsx +17 -17
- package/template/app/(app)/library/list/page.tsx +12 -0
- package/template/app/(app)/library/new/page.tsx +45 -0
- package/template/app/(app)/library/page.tsx +11 -0
- package/template/app/(app)/loading.tsx +18 -1
- package/template/app/(app)/settings/page.tsx +5 -4
- package/template/app/(app)/tokens-themes/page.tsx +11 -0
- package/template/app/globals.css +14 -16
- package/template/components/ask-leo-composer.tsx +2 -2
- 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/columns-client.tsx +158 -0
- package/template/components/columns-showcase.tsx +541 -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-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 +77 -38
- package/template/components/data-views/{question-bank-folder-tree-branch.tsx → library-folder-tree-branch.tsx} +19 -19
- 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/data-views/table-cells.tsx +673 -0
- 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/folder-details-shell.tsx +11 -11
- package/template/components/hub-tree-panel-view.tsx +26 -26
- 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/{question-bank-board-view.tsx → library-board-view.tsx} +44 -44
- package/template/components/{question-bank-client.tsx → library-client.tsx} +83 -83
- package/template/components/{question-bank-dashboard-charts.tsx → library-dashboard-charts.tsx} +14 -14
- package/template/components/{question-bank-favorite-button.tsx → library-favorite-button.tsx} +7 -7
- package/template/components/{question-bank-hub-client.tsx → library-hub-client.tsx} +44 -44
- package/template/components/{question-bank-new-folder-sheet.tsx → library-new-folder-sheet.tsx} +16 -16
- package/template/components/{question-bank-os-folder-view.tsx → library-os-folder-view.tsx} +31 -31
- package/template/components/{question-bank-page-header.tsx → library-page-header.tsx} +6 -6
- package/template/components/library-panel-activator.tsx +8 -0
- package/template/components/{question-bank-secondary-nav.tsx → library-secondary-nav.tsx} +63 -63
- package/template/components/library-table.tsx +839 -0
- package/template/components/list-hub-status-badge.tsx +2 -2
- package/template/components/{new-question-composer.tsx → new-library-item-form.tsx} +489 -441
- 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/product-switcher.tsx +3 -4
- package/template/components/product-wordmark.tsx +2 -1
- 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} +114 -73
- package/template/components/sidebar/index.ts +16 -0
- package/template/components/{secondary-nav.tsx → sidebar/secondary-nav.tsx} +2 -2
- package/template/components/sidebar/secondary-panel.tsx +316 -0
- package/template/components/sidebar/sidebar-auto-collapse.tsx +27 -0
- package/template/components/{sidebar-auto-open.tsx → sidebar/sidebar-auto-open.tsx} +2 -1
- package/template/components/{sidebar-shell.tsx → sidebar/sidebar-shell.tsx} +1 -1
- package/template/components/site-header.tsx +1 -1
- 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/templates/dedicated-search-landing-template.tsx +1 -124
- package/template/components/templates/dedicated-search-results-template.tsx +1 -19
- package/template/components/templates/discovery-hub-template.tsx +1 -1
- 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 +2 -2
- package/template/components/tokens-secondary-nav.tsx +192 -0
- package/template/components/tokens-themes-client.tsx +476 -0
- package/template/components/tokens-themes-section.tsx +386 -0
- 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/HANDBOOK.md +187 -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/collaboration-access-pattern.md +7 -7
- 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 +31 -66
- package/template/docs/drawer-vs-dialog-pattern.md +1 -3
- package/template/docs/glossary.md +58 -0
- package/template/docs/kpi-flat-band-pattern.md +3 -3
- package/template/docs/kpi-trend-pattern.md +18 -3
- package/template/docs/large-dataset-strategy.md +155 -0
- package/template/docs/library-hub-header-pattern.md +25 -0
- 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/reference-implementations.md +151 -0
- package/template/docs/shell-surface-elevation-pattern.md +3 -5
- package/template/docs/token-taxonomy.md +416 -0
- package/template/docs/voice-and-tone.md +262 -0
- package/template/eslint.config.mjs +27 -0
- package/template/hooks/use-secondary-panel-hub-nav.ts +11 -11
- package/template/lib/ask-leo-route-context.ts +6 -18
- package/template/lib/coach-mark-registry.ts +0 -16
- package/template/lib/command-menu-config.ts +5 -13
- package/template/lib/command-menu-search-data.ts +8 -23
- 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-storage.ts +35 -38
- package/template/lib/dev-log.ts +1 -8
- package/template/lib/editable-target.ts +1 -10
- package/template/lib/{question-bank-authoring.ts → library-authoring.ts} +89 -88
- package/template/lib/library-dedicated-search.ts +19 -0
- package/template/lib/library-hub-search.ts +90 -0
- package/template/lib/library-nav.ts +477 -0
- package/template/lib/library-recent-searches.ts +22 -0
- package/template/lib/{question-bank-supported-views.ts → library-supported-views.ts} +2 -3
- package/template/lib/list-page-table-properties.ts +1 -48
- package/template/lib/list-status-badges.ts +16 -11
- package/template/lib/mock/dashboard.ts +1 -1
- package/template/lib/mock/{question-bank-folders.ts → library-folders.ts} +30 -30
- package/template/lib/mock/library-header-collaborators.ts +54 -0
- package/template/lib/mock/{question-bank-inspector.ts → library-inspector.ts} +29 -29
- package/template/lib/mock/{question-bank-kpi.ts → library-kpi.ts} +20 -20
- package/template/lib/mock/library.ts +249 -0
- package/template/lib/mock/navigation.tsx +32 -35
- 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/table-state-lifecycle.ts +3 -3
- package/template/next.config.mjs +7 -4
- 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/app/(app)/examples/page.tsx +0 -43
- package/template/app/(app)/question-bank/find/page.tsx +0 -13
- package/template/app/(app)/question-bank/library/page.tsx +0 -12
- package/template/app/(app)/question-bank/list/page.tsx +0 -13
- package/template/app/(app)/question-bank/new/page.tsx +0 -50
- package/template/app/(app)/question-bank/page.tsx +0 -12
- 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/question-bank-panel-activator.tsx +0 -8
- package/template/components/question-bank-table.tsx +0 -729
- package/template/components/secondary-panel/nav-link-rows.tsx +0 -83
- package/template/components/secondary-panel.tsx +0 -220
- 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/sidebar-auto-collapse.tsx +0 -23
- 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/docs/question-bank-hub-header-pattern.md +0 -25
- 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/mock/question-bank-header-collaborators.ts +0 -54
- package/template/lib/mock/question-bank.ts +0 -249
- package/template/lib/page-loading-variant.ts +0 -40
- package/template/lib/question-bank-dedicated-search.ts +0 -19
- package/template/lib/question-bank-hub-search.ts +0 -90
- package/template/lib/question-bank-nav.ts +0 -477
- package/template/lib/question-bank-recent-searches.ts +0 -22
- /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
|
@@ -0,0 +1,187 @@
|
|
|
1
|
+
# Exxat DS — Handbook
|
|
2
|
+
|
|
3
|
+
> **Start here.** One page. Read in 10 minutes. Links out to everything else.
|
|
4
|
+
>
|
|
5
|
+
> **Audience:** designers, engineers, contributors, AI agents — anyone shipping UI in the Exxat product.
|
|
6
|
+
>
|
|
7
|
+
> **Working with an AI assistant?** Read [`.cursor/skills/exxat-token-economy/SKILL.md`](../../.cursor/skills/exxat-token-economy/SKILL.md) **first** (or `.claude/skills/exxat-token-economy/SKILL.md` for Claude Code). It's a one-page pre-flight that cuts token usage by ~50%: a task → minimum-file-set table, the five-question rule check, and tiny scaffolds that mean the assistant never has to re-read this handbook for the common case.
|
|
8
|
+
|
|
9
|
+
---
|
|
10
|
+
|
|
11
|
+
## 1. Five principles
|
|
12
|
+
|
|
13
|
+
Every screen, primitive, and pattern in this design system serves one or more of these. When in doubt, the principle wins over the convenience.
|
|
14
|
+
|
|
15
|
+
1. **Clarity over decoration.** Users see one product, one shell, one rhythm. Surprise (mystery icons, hidden states, novel layouts) is a tax on attention.
|
|
16
|
+
2. **Progressive disclosure.** Beginners see what they need. Power users reach what they want. Default to the simpler surface; expose density on opt-in (Properties drawer, view tabs, secondary panel).
|
|
17
|
+
3. **Same-shaped tools.** A hub looks like a hub. A drawer looks like a drawer. A KPI looks like a KPI. Pick the canonical primitive (§5 reference pages) before composing your own.
|
|
18
|
+
4. **Accessibility is non-negotiable.** WCAG 2.1 AA is the **floor**, not the goal. Keyboard, screen-reader, contrast, touch-target, format hints — all enforced by rules, lints, and a checklist.
|
|
19
|
+
5. **The data drives the chrome.** KPIs, status, trend polarity, descriptions — they come from the dataset (or the product) and are honest. No spin arrows, no decorative placeholders.
|
|
20
|
+
|
|
21
|
+
---
|
|
22
|
+
|
|
23
|
+
## 2. How to build a hub in 6 steps
|
|
24
|
+
|
|
25
|
+
This is the **happy path** for the most common task: "I have an entity (records, library items, tokens, …); ship a hub for it." Follow these in order and the page lands at "best UX/UI", not "random design".
|
|
26
|
+
|
|
27
|
+
| Step | What to do | Where it lives | Rule |
|
|
28
|
+
|---|---|---|---|
|
|
29
|
+
| 1 | Add typed mock rows in `lib/mock/<entity>.ts`. Aim for ~12 realistic records. | `apps/web/lib/mock/` | `.cursor/rules/exxat-centralized-list-dataset.mdc` |
|
|
30
|
+
| 2 | Write **one** KPI helper `lib/mock/<entity>-kpi.ts` returning `MetricItem[]` (≤ 4 tiles). | same | `exxat-kpi-max-four.mdc`, `exxat-kpi-trends.mdc` |
|
|
31
|
+
| 3 | Build the column defs (`ColumnDef[]`). Set `filter:` per column to get filter chips automatically. | `apps/web/components/<entity>-table.tsx` | `exxat-data-tables.mdc` |
|
|
32
|
+
| 4 | Mount **`HubTable`** (NOT raw `<DataTable>`) inside `ListPageTemplate.renderContent`. `HubTable` wires `useTableState`, toolbar (search + filter chips + sort), and the **Properties drawer** in one place. | `apps/web/components/<entity>-table.tsx` | `exxat-data-tables.mdc` |
|
|
33
|
+
| 5 | Compose the page client with `PrimaryPageTemplate` → `ListPageTemplate` (KPIs in `metrics`, view tabs in `defaultTabs`, the `HubTable` in `renderContent`). | `apps/web/components/<entity>-client.tsx` | `exxat-list-page-connected-views.mdc` |
|
|
34
|
+
| 6 | Add to nav (`lib/mock/navigation.tsx`). If the hub needs scoped sub-navigation (e.g. categories), declare `secondaryPanel: "<id>"` and register the panel. | `apps/web/lib/mock/navigation.tsx`, `apps/web/components/sidebar/secondary-panel.tsx` | `exxat-primary-nav-secondary-panel.mdc` |
|
|
35
|
+
|
|
36
|
+
**Reference pages to copy:** `apps/web/components/columns-showcase.tsx` (single-view catalog hub composing every reusable cell), `apps/web/components/tokens-themes-client.tsx` (hub with a secondary panel + URL-driven scope), or `apps/web/components/library-table.tsx` (full hub: table / board / dashboard + conditional rules).
|
|
37
|
+
|
|
38
|
+
> **Stop signs.** If you find yourself building a parallel table stack, a second metrics strip, a custom filter row, or pasting raw `<DataTable>` into `renderContent` — **stop and re-read** `.cursor/rules/exxat-reuse-before-custom.mdc`.
|
|
39
|
+
|
|
40
|
+
---
|
|
41
|
+
|
|
42
|
+
## 3. Where everything lives
|
|
43
|
+
|
|
44
|
+
```
|
|
45
|
+
┌─────────────────────────────────────────────────────────────────────┐
|
|
46
|
+
│ PRINCIPLES + HANDBOOK → docs/HANDBOOK.md (this file) │
|
|
47
|
+
│ │
|
|
48
|
+
│ FOUNDATIONS │
|
|
49
|
+
│ tokens → docs/token-taxonomy.md │
|
|
50
|
+
│ icons (Font Awesome) → .cursor/rules/exxat-fontawesome-icons │
|
|
51
|
+
│ typography → docs/token-taxonomy.md (font-* tokens) │
|
|
52
|
+
│ spacing / radius → docs/token-taxonomy.md (--exxat-*) │
|
|
53
|
+
│ color & themes → apps/web/components/tokens-themes-* │
|
|
54
|
+
│ voice & tone → docs/voice-and-tone.md │
|
|
55
|
+
│ glossary → docs/glossary.md │
|
|
56
|
+
│ reference pages → docs/reference-implementations.md │
|
|
57
|
+
│ │
|
|
58
|
+
│ DECIDING (selection guides) │
|
|
59
|
+
│ which component? → docs/component-selection-guide.md │
|
|
60
|
+
│ page vs drawer vs → docs/drawer-vs-dialog-pattern.md │
|
|
61
|
+
│ dialog vs route + .cursor/rules/exxat-{drawer-vs-dialog, │
|
|
62
|
+
│ page-vs-drawer}.mdc │
|
|
63
|
+
│ card vs row vs list → docs/card-vs-rows-pattern.md │
|
|
64
|
+
│ │
|
|
65
|
+
│ BLUEPRINTS (framework-agnostic specs — one per pattern) │
|
|
66
|
+
│ → docs/blueprints/ │
|
|
67
|
+
│ page-header · data-table · │
|
|
68
|
+
│ list-page-template · board-card · │
|
|
69
|
+
│ key-metrics │
|
|
70
|
+
│ │
|
|
71
|
+
│ PATTERNS (long-form narrative — the "why" + the "how") │
|
|
72
|
+
│ → docs/*.md (data-views-pattern, │
|
|
73
|
+
│ kpi-trend-pattern, drawer-vs-dialog- │
|
|
74
|
+
│ pattern, dedicated-search, │
|
|
75
|
+
│ command-menu, …) │
|
|
76
|
+
│ │
|
|
77
|
+
│ RULES (binding MUST / MUST NOT — for AI agents + reviewers) │
|
|
78
|
+
│ → .cursor/rules/*.mdc │
|
|
79
|
+
│ │
|
|
80
|
+
│ SKILLS (workflows + checklists — for AI agents doing a task) │
|
|
81
|
+
│ → .cursor/skills/ + .claude/skills/ │
|
|
82
|
+
│ │
|
|
83
|
+
│ MIGRATIONS (deprecation history, every breaking change) │
|
|
84
|
+
│ → docs/migrations/ │
|
|
85
|
+
│ │
|
|
86
|
+
│ AGENT HANDBOOK (authoritative §-numbered manual) │
|
|
87
|
+
│ → apps/web/AGENTS.md │
|
|
88
|
+
└─────────────────────────────────────────────────────────────────────┘
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
### Quick "which file should I open?" cheat-sheet
|
|
92
|
+
|
|
93
|
+
| You want to… | Open this |
|
|
94
|
+
|---|---|
|
|
95
|
+
| Pick the right component for a job | [`docs/component-selection-guide.md`](./component-selection-guide.md) |
|
|
96
|
+
| Know what "hub" / "view tab" / "KPI band" mean | [`docs/glossary.md`](./glossary.md) |
|
|
97
|
+
| Write empty-state / error / button copy | [`docs/voice-and-tone.md`](./voice-and-tone.md) |
|
|
98
|
+
| Find the canonical reference page to copy | [`docs/reference-implementations.md`](./reference-implementations.md) |
|
|
99
|
+
| Know the spec for a pattern | [`docs/blueprints/`](./blueprints/) |
|
|
100
|
+
| Understand the "why" of a pattern | [`docs/<pattern>-pattern.md`](.) |
|
|
101
|
+
| Know the binding MUST / MUST NOT | [`.cursor/rules/`](../../../.cursor/rules/) |
|
|
102
|
+
| Run a recurring agent workflow | [`.cursor/skills/`](../../../.cursor/skills/) or [`.claude/skills/`](../../../.claude/skills/) |
|
|
103
|
+
| Token name & semantics | [`docs/token-taxonomy.md`](./token-taxonomy.md) |
|
|
104
|
+
| Full authoritative handbook | [`apps/web/AGENTS.md`](../AGENTS.md) |
|
|
105
|
+
|
|
106
|
+
---
|
|
107
|
+
|
|
108
|
+
## 4. Rule precedence (when sources conflict)
|
|
109
|
+
|
|
110
|
+
If two docs say different things, **the higher row wins**:
|
|
111
|
+
|
|
112
|
+
1. **`.cursor/rules/*.mdc`** — these are MUST / MUST NOT; they bind the AI agent and the reviewer.
|
|
113
|
+
2. **`apps/web/AGENTS.md`** — authoritative §-numbered handbook. The rules above are summaries of this.
|
|
114
|
+
3. **`docs/blueprints/*.md`** — framework-agnostic specs for a single pattern.
|
|
115
|
+
4. **`docs/*-pattern.md`** — long-form narrative for a pattern.
|
|
116
|
+
5. **Reference page in code** (`apps/web/components/<reference>.tsx`) — the working implementation.
|
|
117
|
+
6. **This handbook** — orientation only. If it conflicts with rules or AGENTS, the rules/AGENTS win.
|
|
118
|
+
|
|
119
|
+
> **Found a conflict?** Open a PR that updates the *binding* layer (rule or AGENTS section) first, then propagate down. Don't fork the truth.
|
|
120
|
+
|
|
121
|
+
---
|
|
122
|
+
|
|
123
|
+
## 5. The canonical primitives (memorize these)
|
|
124
|
+
|
|
125
|
+
These are the ones you'll use on >90% of screens. If a screen needs something else, it almost certainly already exists — search `components/` before building.
|
|
126
|
+
|
|
127
|
+
| Need | Primitive | Lives in |
|
|
128
|
+
|---|---|---|
|
|
129
|
+
| Page chrome (breadcrumbs, site header, max-width content rail) | `PrimaryPageTemplate` | `apps/web/components/templates/primary-page-template.tsx` |
|
|
130
|
+
| Hub frame (header + metrics + view tabs + content) | `ListPageTemplate` | `packages/ui` |
|
|
131
|
+
| **Hub view body** (table + search + filters + Properties drawer + bulk-actions) | **`HubTable`** | `packages/ui` (re-exported from `@/components/data-views`) |
|
|
132
|
+
| Page header (title + subtitle + actions + collaborators rail) | `PageHeader` | `apps/web/components/page-header.tsx` |
|
|
133
|
+
| KPI strip / band | `KeyMetrics` (`variant="flat"` on hubs) | `packages/ui` |
|
|
134
|
+
| Status chip + icon | `ListHubStatusBadge` + `lib/list-status-badges.ts` | `apps/web/components/` |
|
|
135
|
+
| Board / kanban card | `ListPageBoardCard` + primitives | `packages/ui` |
|
|
136
|
+
| Side overlay | `Sheet` / `Drawer` (NOT toast — `exxat-no-toast.mdc`) | `packages/ui` |
|
|
137
|
+
| Persistent banner | `LocalBanner` / `SystemBanner` | `packages/ui` |
|
|
138
|
+
| Inline status / format hint | `FormDescription`, inline `<small>` | `packages/ui` |
|
|
139
|
+
| Tooltip | `Tip` / `Tooltip` | `packages/ui` |
|
|
140
|
+
| Keyboard shortcut hint | `Kbd` (`variant="bare"` inside buttons) | `packages/ui` |
|
|
141
|
+
| Global search | `CommandMenu` (⌘K) | `apps/web/components/command-menu.tsx` |
|
|
142
|
+
| AI assistant chrome | Ask Leo side panel (⌘⌥K) | `apps/web/components/` |
|
|
143
|
+
|
|
144
|
+
For a fuller decision tree see [`docs/component-selection-guide.md`](./component-selection-guide.md).
|
|
145
|
+
|
|
146
|
+
---
|
|
147
|
+
|
|
148
|
+
## 6. The shortest accessibility checklist
|
|
149
|
+
|
|
150
|
+
Run this on every PR. If you can't tick every box, the change isn't ready. (Full list: `.cursor/skills/exxat-accessibility/SKILL.md` and [`AGENTS.md` §8](../AGENTS.md).)
|
|
151
|
+
|
|
152
|
+
- [ ] **Keyboard.** Every interactive thing reachable via Tab + activatable via Enter / Space. Focus ring visible (≥ 3:1).
|
|
153
|
+
- [ ] **Touch target ≥ 24×24 CSS px** (or 24 px spacing) per WCAG 2.5.8.
|
|
154
|
+
- [ ] **Icons that mean something** have a text alt — either adjacent label (Case A, `aria-hidden`), or `role="img" + aria-label + Tooltip` (Case B), or `aria-label + Tooltip` on the button (Case C). No silent icons.
|
|
155
|
+
- [ ] **Contrast.** Text ≥ 4.5:1; UI components ≥ 3:1. Don't encode state with color alone — pair with icon or label.
|
|
156
|
+
- [ ] **Format hints are persistent**, never placeholder-only. Use `FormDescription`.
|
|
157
|
+
- [ ] **Dialogs / drawers / sheets** have a `Title` (use `sr-only` if visually hidden).
|
|
158
|
+
- [ ] **Tabs** use `role="tablist"` correctly (no mixed children); composite switchers use `role="toolbar"` instead.
|
|
159
|
+
- [ ] **No toast.** Use banners, inline status, or dialogs (`exxat-no-toast.mdc`).
|
|
160
|
+
- [ ] **HC modes.** Forced-colors and `data-contrast="high"` covered for any fill-only state (progress, gauge, pill).
|
|
161
|
+
|
|
162
|
+
---
|
|
163
|
+
|
|
164
|
+
## 7. The "you're done" definition
|
|
165
|
+
|
|
166
|
+
A hub or screen is **done** when:
|
|
167
|
+
|
|
168
|
+
1. It uses `PrimaryPageTemplate` + `ListPageTemplate` (or another canonical template).
|
|
169
|
+
2. The data surface is `HubTable` (or, for non-hubs, the right primitive from §5).
|
|
170
|
+
3. KPIs use `KeyMetrics` with `delta` for counts, `description` for prose, ≤ 4 tiles, polarity set correctly.
|
|
171
|
+
4. The §6 accessibility checklist is green.
|
|
172
|
+
5. Copy passes [`docs/voice-and-tone.md`](./voice-and-tone.md).
|
|
173
|
+
6. No new shared primitives were added without `.cursor/rules/exxat-reuse-before-custom.mdc` approval.
|
|
174
|
+
7. The §13 PR-review checklist in [`AGENTS.md`](../AGENTS.md#section-13) is green.
|
|
175
|
+
|
|
176
|
+
---
|
|
177
|
+
|
|
178
|
+
## 8. Where to ask for help
|
|
179
|
+
|
|
180
|
+
- **Code-level questions** — open the file referenced in a rule's "See also" section.
|
|
181
|
+
- **Pattern-level questions** — open the matching `docs/*-pattern.md`.
|
|
182
|
+
- **"Is this the right approach?"** — read [`.cursor/rules/exxat-reuse-before-custom.mdc`](../../../.cursor/rules/exxat-reuse-before-custom.mdc). If still unsure, ask before building.
|
|
183
|
+
- **AGENTS.md is too long** — that's why this handbook exists. Bring the §-number you're stuck on; we'll split it out.
|
|
184
|
+
|
|
185
|
+
---
|
|
186
|
+
|
|
187
|
+
*This file is intentionally short. If you want to add something, ask whether it belongs in a rule, a pattern, a blueprint, or the glossary instead.*
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
# Exxat DS — Blueprints
|
|
2
|
+
|
|
3
|
+
**Audience:** humans + AI agents.
|
|
4
|
+
**Inspired by:** [SLDS Component Blueprints](https://www.lightningdesignsystem.com/components).
|
|
5
|
+
|
|
6
|
+
A **blueprint** is a **framework-agnostic spec** for a UI pattern. It says
|
|
7
|
+
*what* the pattern is, *what it must do*, and *what tokens it consumes* —
|
|
8
|
+
**without committing to any one implementation**.
|
|
9
|
+
|
|
10
|
+
A **component** is the React + Tailwind implementation that satisfies the
|
|
11
|
+
blueprint inside this app.
|
|
12
|
+
|
|
13
|
+
| Blueprint says… | Component does… |
|
|
14
|
+
|---|---|
|
|
15
|
+
| "A page header has a title, optional icon, optional meta line, optional action slot, optional `+ N collaborators` rail" | `PageHeader` renders that with `variant="object-home" / "record-home" / "collaboration"` etc. |
|
|
16
|
+
| "A data list is a sortable, filterable, columnable grid of records with search, properties drawer, and view tabs" | `DataTable` + `ListPageTemplate` + `TablePropertiesDrawer` compose to satisfy this |
|
|
17
|
+
|
|
18
|
+
---
|
|
19
|
+
|
|
20
|
+
## Why blueprints exist
|
|
21
|
+
|
|
22
|
+
1. **They survive framework changes.** If we ever ship a second consumer
|
|
23
|
+
(mobile, embed widget, design-token export to Figma), the blueprint stays
|
|
24
|
+
true; only the implementation changes.
|
|
25
|
+
2. **They make the design language explicit.** New contributors can read a
|
|
26
|
+
single page that says "this is what a page header **is** at Exxat" without
|
|
27
|
+
spelunking through React props.
|
|
28
|
+
3. **They let designers, engineers, and AI agents share one vocabulary.** The
|
|
29
|
+
blueprint is the contract; the React component is the receipt.
|
|
30
|
+
|
|
31
|
+
---
|
|
32
|
+
|
|
33
|
+
## Anatomy of a blueprint doc
|
|
34
|
+
|
|
35
|
+
Each blueprint follows the same template. Copy it from
|
|
36
|
+
[`_template.md`](./_template.md) when adding a new one.
|
|
37
|
+
|
|
38
|
+
```
|
|
39
|
+
# <Blueprint name>
|
|
40
|
+
|
|
41
|
+
## 1. Intent → What user need does this solve? When NOT to use it.
|
|
42
|
+
## 2. Anatomy → Required + optional slots, with an ASCII or markdown sketch.
|
|
43
|
+
## 3. States → Default, hover, active, disabled, loading, empty, error, RTL.
|
|
44
|
+
## 4. Tokens consumed → Exact token names from `docs/token-taxonomy.md`.
|
|
45
|
+
## 5. Accessibility → Roles, focus order, keyboard, screen-reader.
|
|
46
|
+
## 6. Variants → Named families that share anatomy but swap layout/density.
|
|
47
|
+
## 7. Implementation → Table of frameworks → component(s); React is required.
|
|
48
|
+
## 8. Do / Don't → Anti-patterns + correct alternatives.
|
|
49
|
+
## 9. References → Linked AGENTS.md sections, cursor rules, related blueprints.
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
The React row in §7 is **required**; other frameworks are listed as `—` until
|
|
53
|
+
they ship.
|
|
54
|
+
|
|
55
|
+
---
|
|
56
|
+
|
|
57
|
+
## Authoritative file pointers
|
|
58
|
+
|
|
59
|
+
For most patterns, the blueprint complements an existing narrative doc — it
|
|
60
|
+
does **not** replace it. The blueprint is the spec; the narrative is the deep
|
|
61
|
+
dive.
|
|
62
|
+
|
|
63
|
+
| Blueprint | Narrative doc | Cursor rule(s) | React component(s) |
|
|
64
|
+
|---|---|---|---|
|
|
65
|
+
| [page-header](./page-header.md) | `apps/web/docs/data-views-pattern.md` (Page header section) | `exxat-collaboration-access.mdc` (variant), `exxat-mono-ids.mdc` (subtitle IDs) | `PageHeader`, `PlacementsPageHeader`, `TeamPageHeader`, `LibraryPageHeader` |
|
|
66
|
+
| [data-table](./data-table.md) | `apps/web/docs/data-views-pattern.md` | `exxat-data-tables.mdc`, `exxat-list-page-connected-views.mdc`, `exxat-centralized-list-dataset.mdc`, `exxat-table-properties-drawer.mdc` | `DataTable`, `DataTablePaginated`, `useTableState`, `TablePropertiesDrawer` |
|
|
67
|
+
| [list-page-template](./list-page-template.md) | `apps/web/docs/data-views-pattern.md`, `kpi-flat-band-pattern.md` | `exxat-list-page-connected-views.mdc`, `exxat-centralized-list-dataset.mdc`, `exxat-table-properties-drawer.mdc`, `exxat-list-page-view-shells.mdc` | `ListPageTemplate`, `HubTable`, `useTableState`, `TablePropertiesDrawer` |
|
|
68
|
+
| [board-card](./board-card.md) | `apps/web/docs/data-views-pattern.md` (board UI section) | `exxat-board-cards.mdc`, `exxat-centralized-list-dataset.mdc`, `exxat-card-vs-list-rows.mdc` | `ListPageBoardCard`, `ListPageBoardCardTitleRow`, `ListPageBoardCardBadgeRow`, `BoardCardTwoLineBlock`, `BoardCardIconRow`, `ListHubStatusBadge` |
|
|
69
|
+
| [key-metrics](./key-metrics.md) | `apps/web/docs/kpi-flat-band-pattern.md`, `kpi-strip-max-four-pattern.md`, `kpi-trend-pattern.md` | `exxat-kpi-flat-band.mdc`, `exxat-kpi-max-four.mdc`, `exxat-kpi-trends.mdc` | `KeyMetrics`, `MetricItem`, `MetricInsight`, `KeyMetricsProvider` |
|
|
70
|
+
|
|
71
|
+
Future blueprints to write (open a PR when adding one):
|
|
72
|
+
|
|
73
|
+
- `drawer-vs-dialog.md` — overlay decision (already in `docs/drawer-vs-dialog-pattern.md`, formalize as blueprint)
|
|
74
|
+
- `command-menu.md` — global ⌘K palette + Ask Leo split
|
|
75
|
+
- `dedicated-search.md` — landing vs results
|
|
76
|
+
- `sidebar.md` — primary nav + secondary panel + product switcher
|
|
77
|
+
- `coach-mark.md` — onboarding tours
|
|
78
|
+
- `status-badge.md` — `ListHubStatusBadge` + `lib/list-status-badges.ts`
|
|
79
|
+
|
|
80
|
+
---
|
|
81
|
+
|
|
82
|
+
## See also
|
|
83
|
+
|
|
84
|
+
- [`apps/web/docs/token-taxonomy.md`](../token-taxonomy.md) — the design-token namespace these blueprints reference
|
|
85
|
+
- [`apps/web/docs/component-selection-guide.md`](../component-selection-guide.md) — decision tree across blueprints
|
|
86
|
+
- [`apps/web/AGENTS.md`](../../AGENTS.md) §9 architecture pointers (component reuse table)
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
# Blueprint: <Name>
|
|
2
|
+
|
|
3
|
+
> **Status:** Draft / Stable. **Owner:** <team or person>. **Implements:** <SC refs>.
|
|
4
|
+
|
|
5
|
+
## 1. Intent
|
|
6
|
+
|
|
7
|
+
What user need does this pattern solve? In one paragraph.
|
|
8
|
+
|
|
9
|
+
**Use when:**
|
|
10
|
+
- Bullet
|
|
11
|
+
- Bullet
|
|
12
|
+
|
|
13
|
+
**Do NOT use when:**
|
|
14
|
+
- Bullet
|
|
15
|
+
|
|
16
|
+
## 2. Anatomy
|
|
17
|
+
|
|
18
|
+
ASCII / markdown sketch with labelled slots. List every named slot and whether
|
|
19
|
+
it is required, optional, or conditional.
|
|
20
|
+
|
|
21
|
+
```
|
|
22
|
+
┌──────────────────────────────────────────┐
|
|
23
|
+
│ [icon] Title [actions] │ ← slot: title-row (required)
|
|
24
|
+
│ ─────────────────────────────────────── │
|
|
25
|
+
│ subtitle · ID · meta │ ← slot: meta (optional)
|
|
26
|
+
└──────────────────────────────────────────┘
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
| Slot | Required? | What it carries |
|
|
30
|
+
|---|---|---|
|
|
31
|
+
| `title` | required | Single H1 string |
|
|
32
|
+
| `icon` | optional | FA glyph or product mark |
|
|
33
|
+
| `actions` | optional | Primary CTA + optional `⋯` overflow |
|
|
34
|
+
| `meta` | optional | Count · freshness · sort summary |
|
|
35
|
+
|
|
36
|
+
## 3. States
|
|
37
|
+
|
|
38
|
+
| State | Visual / behavior |
|
|
39
|
+
|---|---|
|
|
40
|
+
| Default | … |
|
|
41
|
+
| Loading | … |
|
|
42
|
+
| Empty | … |
|
|
43
|
+
| Error | … |
|
|
44
|
+
| RTL | … |
|
|
45
|
+
|
|
46
|
+
## 4. Tokens consumed
|
|
47
|
+
|
|
48
|
+
List every token the blueprint references from
|
|
49
|
+
[`docs/token-taxonomy.md`](../token-taxonomy.md). Be precise — no "a brand
|
|
50
|
+
color"; name `--brand-color`.
|
|
51
|
+
|
|
52
|
+
| Token | Used for |
|
|
53
|
+
|---|---|
|
|
54
|
+
| `--background` / `--foreground` | Surface + ink |
|
|
55
|
+
| … | … |
|
|
56
|
+
|
|
57
|
+
## 5. Accessibility
|
|
58
|
+
|
|
59
|
+
| WCAG SC | How this blueprint complies |
|
|
60
|
+
|---|---|
|
|
61
|
+
| 1.1.1 Non-text content | Icons are decorative (Case A) when adjacent to text; standalone icons follow Case B (label + tooltip) |
|
|
62
|
+
| 1.3.1 Info & relationships | … |
|
|
63
|
+
| 2.1.1 Keyboard | Tab order: … |
|
|
64
|
+
| 2.4.6 Headings / labels | The title slot is the `<h1>` for the route |
|
|
65
|
+
| 2.4.11 Focus visible | Inherits `:focus-visible` ring (≥ 3:1) |
|
|
66
|
+
|
|
67
|
+
## 6. Variants
|
|
68
|
+
|
|
69
|
+
| Variant | When to use | Differences from default |
|
|
70
|
+
|---|---|---|
|
|
71
|
+
| `base` | … | — |
|
|
72
|
+
|
|
73
|
+
## 7. Implementation
|
|
74
|
+
|
|
75
|
+
| Framework | Component(s) | File |
|
|
76
|
+
|---|---|---|
|
|
77
|
+
| **React (this app)** | `PrimaryComponent` + `RelatedComponent` | `apps/web/components/<file>.tsx` |
|
|
78
|
+
| Mobile | — | — |
|
|
79
|
+
| Figma | — | — |
|
|
80
|
+
|
|
81
|
+
## 8. Do / Don't
|
|
82
|
+
|
|
83
|
+
| ✅ Do | ❌ Don't |
|
|
84
|
+
|---|---|
|
|
85
|
+
| Bullet | Bullet |
|
|
86
|
+
|
|
87
|
+
## 9. References
|
|
88
|
+
|
|
89
|
+
- `apps/web/docs/<related-narrative>.md`
|
|
90
|
+
- `.cursor/rules/<related-rule>.mdc`
|
|
91
|
+
- `apps/web/AGENTS.md` §<section>
|
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
# Blueprint: Board card
|
|
2
|
+
|
|
3
|
+
> **Status:** Stable. **Owner:** Design system. **Implements:** SC 1.1.1, 1.3.1, 2.5.8, 4.1.2.
|
|
4
|
+
|
|
5
|
+
## 1. Intent
|
|
6
|
+
|
|
7
|
+
A **board card** is the kanban-tile presentation of a single hub record (e.g.
|
|
8
|
+
one Placement, one Team member, one Question-bank item) when the active view
|
|
9
|
+
is `board`. The card surfaces the most-scannable summary fields — title, owner
|
|
10
|
+
avatar, status chip, 1-3 meta lines — and is sized so a column holds 6-10
|
|
11
|
+
cards on a 1280-wide viewport.
|
|
12
|
+
|
|
13
|
+
**Use when:**
|
|
14
|
+
|
|
15
|
+
- The hub's `board` view tab is active.
|
|
16
|
+
- The record has a **status** (or equivalent grouping) that drives column placement.
|
|
17
|
+
- Users compare ~6-30 records side-by-side and would benefit from owner / status visibility.
|
|
18
|
+
|
|
19
|
+
**Do NOT use when:**
|
|
20
|
+
|
|
21
|
+
- The record needs ≥ 4 fields to be useful at a glance (use list / table).
|
|
22
|
+
- The dataset has > ~100 records per column (board UX collapses; use table + filters).
|
|
23
|
+
- The hub does not model status / lifecycle (use folder grid or list).
|
|
24
|
+
|
|
25
|
+
## 2. Anatomy
|
|
26
|
+
|
|
27
|
+
```
|
|
28
|
+
┌──────────────────────────────────────────────┐
|
|
29
|
+
│ Title row [avatar] │ ← slot: title (required) + trailing (optional)
|
|
30
|
+
│ ──────────────────────────────────────────── │
|
|
31
|
+
│ [status chip] │ ← slot: badgeRow (optional, when status exists)
|
|
32
|
+
│ ──────────────────────────────────────────── │
|
|
33
|
+
│ Body — primary stat (large) + sub label │ ← slot: body (optional)
|
|
34
|
+
│ ▣ row icon · meta label · meta value │
|
|
35
|
+
│ ▣ row icon · meta label · meta value │
|
|
36
|
+
└──────────────────────────────────────────────┘
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
| Slot | Required? | What it carries |
|
|
40
|
+
|---|---|---|
|
|
41
|
+
| `title` | required | `ListPageBoardCardTitleRow` — single-line truncated title |
|
|
42
|
+
| `trailing` | optional | `ListPageBoardCardAvatar` (owner) or another single glyph |
|
|
43
|
+
| `badgeRow` | optional | `ListPageBoardCardBadgeRow` + `ListHubStatusBadge surface="board"` |
|
|
44
|
+
| `body` | optional | `ListPageBoardCardBody` containing `BoardCardTwoLineBlock` / `BoardCardIconRow` |
|
|
45
|
+
| `footer` | optional | Counts, freshness, or a small CTA — kept low-emphasis |
|
|
46
|
+
|
|
47
|
+
The shell is `ListPageBoardCard` (`Card size="sm"` treatment) — do NOT compose
|
|
48
|
+
a bespoke `<button>` + border-class wrapper for the same pattern.
|
|
49
|
+
|
|
50
|
+
## 3. States
|
|
51
|
+
|
|
52
|
+
| State | Visual / behavior |
|
|
53
|
+
|---|---|
|
|
54
|
+
| Default | Surface 2 background, hairline border, no shadow |
|
|
55
|
+
| Hover | Border deepens; subtle elevation shift (matches `Card size="sm"`) |
|
|
56
|
+
| Focused | `:focus-visible` ring on the outer element (≥ 3:1) |
|
|
57
|
+
| Selected (drag source / active drag target) | `data-selected` border + brand tint |
|
|
58
|
+
| Loading | Skeleton shell mirroring title row + badge row + body |
|
|
59
|
+
| Empty column | Column footer shows "+ Add" affordance with `aria-label` per column |
|
|
60
|
+
| RTL | All trailing slots flip; status chip flips alignment |
|
|
61
|
+
|
|
62
|
+
## 4. Tokens consumed
|
|
63
|
+
|
|
64
|
+
| Token | Used for |
|
|
65
|
+
|---|---|
|
|
66
|
+
| `--exxat-color-surface-2` / `--card` | Card background |
|
|
67
|
+
| `--exxat-color-border-1` / `--border` | Card hairline |
|
|
68
|
+
| `--exxat-color-ink-1` / `--foreground` | Title text |
|
|
69
|
+
| `--exxat-color-ink-2` / `--muted-foreground` | Meta label text |
|
|
70
|
+
| `--exxat-color-focus-ring` / `--ring` | `:focus-visible` ring |
|
|
71
|
+
| `--exxat-radius-2` / `--radius-md` | Card corners |
|
|
72
|
+
| Status-tint variables (`LIST_HUB_STATUS_TINT_*`) | Status chip background + text |
|
|
73
|
+
|
|
74
|
+
## 5. Accessibility
|
|
75
|
+
|
|
76
|
+
| WCAG SC | How this blueprint complies |
|
|
77
|
+
|---|---|
|
|
78
|
+
| 1.1.1 Non-text content | Icons in `BoardCardIconRow` are decorative when paired with a visible label (Case A); standalone glyphs get Case B label + tooltip |
|
|
79
|
+
| 1.3.1 Info & relationships | The card is one `<article>` (or `role="listitem"` inside the column's `role="list"`); status, owner, and meta rows are programmatically related to the title |
|
|
80
|
+
| 2.5.8 Target size | The whole card is the primary click target — ≥ 24×24 CSS px; small icon controls inside use `size-6` (≥ 24px) |
|
|
81
|
+
| 4.1.2 Name / role / value | If the card is interactive (opens detail) it is rendered as `<button>` with an accessible name combining title + status |
|
|
82
|
+
|
|
83
|
+
## 6. Variants
|
|
84
|
+
|
|
85
|
+
| Variant | When to use | Differences from default |
|
|
86
|
+
|---|---|---|
|
|
87
|
+
| `base` | Most hubs | Title + status badge + body |
|
|
88
|
+
| `no-status` | Hubs without lifecycle (Library items) | Omit `badgeRow`; body carries the differentiator |
|
|
89
|
+
| `compact` | Dense boards (10+ cards visible) | Drop body; show title + status + avatar only |
|
|
90
|
+
| `with-progress` | Workflow boards with completion bar | Add a `<Progress>` row in the body slot |
|
|
91
|
+
|
|
92
|
+
## 6.1 List-row counterpart
|
|
93
|
+
|
|
94
|
+
`ListPageBoardCard layout="row"` is the same component shape rendered as a
|
|
95
|
+
horizontal row for the `list` view tab. Use one renderer for both views so the
|
|
96
|
+
**title / status / owner / meta** mapping stays consistent — never define two
|
|
97
|
+
parallel components for "card" and "row" of the same hub.
|
|
98
|
+
|
|
99
|
+
## 7. Implementation
|
|
100
|
+
|
|
101
|
+
| Framework | Component(s) | File |
|
|
102
|
+
|---|---|---|
|
|
103
|
+
| **React (this app)** | `ListPageBoardCard` + `ListPageBoardCardTitleRow` + `ListPageBoardCardBadgeRow` + `ListPageBoardCardBody` + `BoardCardTwoLineBlock` + `BoardCardIconRow` + `ListHubStatusBadge` | `@exxatdesignux/ui/components/data-views` + `apps/web/lib/list-status-badges.ts` |
|
|
104
|
+
| Board template | `ListPageBoardTemplate` (column shells + `renderCard`) | `@exxatdesignux/ui/components/data-views/list-page-board-template` |
|
|
105
|
+
| Mobile | — | — |
|
|
106
|
+
| Figma | "Board card – hub" component in DS library | — |
|
|
107
|
+
|
|
108
|
+
## 8. Do / Don't
|
|
109
|
+
|
|
110
|
+
| ✅ Do | ❌ Don't |
|
|
111
|
+
|---|---|
|
|
112
|
+
| Use `ListPageBoardCard` as the shell; compose primitives inside | Wrap a bespoke `<button>` with border / padding utility classes for the same pattern |
|
|
113
|
+
| Status: `ListHubStatusBadge surface="board"` + entity-specific map from `lib/list-status-badges.ts` | Show status as plain body text when the hub uses `ListHubStatusBadge` elsewhere |
|
|
114
|
+
| Pull rows from `tableState.rows` so board honors filters / search | Hydrate cards from a separate `BOARD_MOCK[]` array |
|
|
115
|
+
| Match list-row + table-row + card field choices via one mapper per hub | Define a card-only field projection that diverges from the table |
|
|
116
|
+
| Use `Tip` on any icon-only control inside the card | Rely on `aria-label` alone for icon-only affordances inside the card |
|
|
117
|
+
|
|
118
|
+
## 9. References
|
|
119
|
+
|
|
120
|
+
- `apps/web/docs/data-views-pattern.md` — board UI section
|
|
121
|
+
- `.cursor/rules/exxat-board-cards.mdc`, `exxat-centralized-list-dataset.mdc`, `exxat-card-vs-list-rows.mdc`
|
|
122
|
+
- `apps/web/AGENTS.md` §4.4 (board cards), §13 (checklist)
|
|
123
|
+
- `apps/web/lib/list-status-badges.ts` — `LIST_HUB_STATUS_TINT_*` + entity maps
|
|
@@ -0,0 +1,139 @@
|
|
|
1
|
+
# Blueprint: Data Table
|
|
2
|
+
|
|
3
|
+
> **Status:** Stable. **Owner:** Exxat DS core. **Implements:** WCAG 2.1 AA. **References:** SC 1.3.1, 2.1.1, 2.4.3, 2.4.6, 2.5.8, 4.1.2.
|
|
4
|
+
|
|
5
|
+
## 1. Intent
|
|
6
|
+
|
|
7
|
+
A **data table** is the canonical Exxat surface for browsing a homogeneous,
|
|
8
|
+
comparable dataset (placements, team members, questions, compliance records).
|
|
9
|
+
It pairs a **sortable / filterable / columnable grid** with a single state
|
|
10
|
+
object (`useTableState`) that **every connected view** — list, board,
|
|
11
|
+
dashboard, folder, panel — reads from.
|
|
12
|
+
|
|
13
|
+
**Use when:**
|
|
14
|
+
- The hub shows ≥ ~10 comparable records.
|
|
15
|
+
- Users need to sort, filter, pin columns, change density, or export the data.
|
|
16
|
+
- The hub is a primary nav destination.
|
|
17
|
+
|
|
18
|
+
**Do NOT use when:**
|
|
19
|
+
- The hub is **visual browse** (kanban, gallery, finder) — use
|
|
20
|
+
`ListPageBoardCard` + `data-views/` primitives. See
|
|
21
|
+
[`card-vs-rows-pattern.md`](../card-vs-rows-pattern.md).
|
|
22
|
+
- The data is < ~10 rows and never grows — a simple list (or `<dl>`) suffices.
|
|
23
|
+
- The view is read-only inside an analytics card — that may use minimal markup
|
|
24
|
+
per [`AGENTS.md` §3](../../AGENTS.md).
|
|
25
|
+
|
|
26
|
+
## 2. Anatomy
|
|
27
|
+
|
|
28
|
+
```
|
|
29
|
+
┌─ ListPageTemplate ────────────────────────────────────────────────────┐
|
|
30
|
+
│ [view tabs] [Add view +] [metrics slot] │
|
|
31
|
+
│ ├ DataTableToolbar ──────────────────────────────────────────────┐ │
|
|
32
|
+
│ │ [search] [filter chips] [sort] [columns] [⋯ properties] │ │
|
|
33
|
+
│ ├ DataTable header ──────────────────────────────────────────────┤ │
|
|
34
|
+
│ │ Col A ↕ │ Col B │ Col C │ … │ │
|
|
35
|
+
│ ├ DataTable body ───────────────────────────────────────────────┤ │
|
|
36
|
+
│ │ …rows from `tableState.rows`… │ │
|
|
37
|
+
│ ├ DataTablePaginated footer (optional) ──────────────────────────┤ │
|
|
38
|
+
│ │ ‹ 1 / N › │ │
|
|
39
|
+
│ └────────────────────────────────────────────────────────────────┘ │
|
|
40
|
+
└───────────────────────────────────────────────────────────────────────┘
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
| Slot | Required? | What it carries |
|
|
44
|
+
|---|---|---|
|
|
45
|
+
| `view tabs` | required when ≥ 1 view type | `table / list / board / dashboard` per `ListPageTemplate` |
|
|
46
|
+
| `toolbar.search` | required | `⌘K` / `Ctrl K` find-in-list |
|
|
47
|
+
| `toolbar.filter` | required when entity has filterable fields | Shared `FilterFieldDef` chips |
|
|
48
|
+
| `toolbar.sort` | optional (column headers also sort) | Multi-column sort summary |
|
|
49
|
+
| `toolbar.columns` | required | Column visibility / order chooser |
|
|
50
|
+
| `toolbar.overflow` | required | `⋯` → `TablePropertiesDrawer` |
|
|
51
|
+
| `header` | required | One row of column heads; sortable cells expose `aria-sort` |
|
|
52
|
+
| `body` | required | Rows from **`tableState.rows`** — no parallel data source |
|
|
53
|
+
| `pagination` | optional | When the result set exceeds the virtualization budget |
|
|
54
|
+
|
|
55
|
+
## 3. States
|
|
56
|
+
|
|
57
|
+
| State | Visual / behavior |
|
|
58
|
+
|---|---|
|
|
59
|
+
| Empty result | Inline empty-state row (icon + 1 sentence + clear filters action) |
|
|
60
|
+
| Empty entity | Empty-state card (no rows in entity) |
|
|
61
|
+
| Loading | Skeleton header + 5 skeleton rows; toolbar still interactable |
|
|
62
|
+
| Sorted | Active column shows ↑ / ↓ with `aria-sort`; multi-sort shows index pill |
|
|
63
|
+
| Filtered | Chips in toolbar; "X of Y" indicator |
|
|
64
|
+
| Selected rows | Row check + bulk-action bar above toolbar |
|
|
65
|
+
| Pinned cells | Opaque using `--dt-row-bg` / `--dt-header-bg` (never translucent) |
|
|
66
|
+
| New row (just created) | `--dt-new-row-bg` + `--dt-new-row-border` (fades after N seconds) |
|
|
67
|
+
| RTL | Header sort arrows and column resize handles mirror |
|
|
68
|
+
|
|
69
|
+
## 4. Tokens consumed
|
|
70
|
+
|
|
71
|
+
| Token | Used for |
|
|
72
|
+
|---|---|
|
|
73
|
+
| `--dt-row-bg`, `--dt-row-hover`, `--dt-row-selected`, `--dt-row-selected-fg` | Row chrome (must be **opaque** for pinned cells) |
|
|
74
|
+
| `--dt-header-bg`, `--dt-group-bg` | Header + group rows |
|
|
75
|
+
| `--dt-new-row-bg`, `--dt-new-row-border` | "Just created" highlight |
|
|
76
|
+
| `--sticky-edge-fade` | Edge-of-pinned-column gradient |
|
|
77
|
+
| `--border` | Hairlines between rows / columns |
|
|
78
|
+
| `--ring` | Focus ring on cells, sort headers, row actions |
|
|
79
|
+
| `--interactive-hover-row` | Hover-row tint |
|
|
80
|
+
| `--avatar-initials-bg`, `--avatar-initials-fg` | Initials cells |
|
|
81
|
+
| `--font-mono` (via `font-mono tabular-nums` class) | System IDs in cells |
|
|
82
|
+
| `--table-row-height` | Default row height (`48px * --scaling`) |
|
|
83
|
+
|
|
84
|
+
## 5. Accessibility
|
|
85
|
+
|
|
86
|
+
| WCAG SC | How this blueprint complies |
|
|
87
|
+
|---|---|
|
|
88
|
+
| 1.3.1 Info & relationships | `<table>` / `<thead>` / `<tbody>` / `<tr>` / `<th scope="col">` semantics preserved through TanStack Table renderers |
|
|
89
|
+
| 1.4.3 Contrast | Row hover + selection tints stay ≥ 4.5:1 against `--foreground` |
|
|
90
|
+
| 1.4.11 UI contrast | Cell borders use `--border`; focus uses `--ring` (≥ 3:1) |
|
|
91
|
+
| 2.1.1 Keyboard | Cells reachable by `Tab`; arrow-key cell nav inside the body; `Esc` clears active filter chip |
|
|
92
|
+
| 2.4.3 Focus order | Header → toolbar → body → pagination; never traps |
|
|
93
|
+
| 2.4.6 Headings & labels | Column heads are `<th>` with visible text labels; icon-only sort affordance carries `aria-label` + `Tooltip` (SC 1.1.1 Case C) |
|
|
94
|
+
| 2.5.8 Target size | Sort handles, sort/filter chips, row checkboxes ≥ 24×24 CSS px |
|
|
95
|
+
| 4.1.2 Name, role, value | Sortable headers expose `aria-sort`; row selection checkboxes expose checked state |
|
|
96
|
+
|
|
97
|
+
## 6. Variants
|
|
98
|
+
|
|
99
|
+
| Variant | When to use | Differences |
|
|
100
|
+
|---|---|---|
|
|
101
|
+
| `DataTable` | Default — virtualized, sticky header | All features above |
|
|
102
|
+
| `DataTablePaginated` | Server-paginated result sets where virtualization is wrong | Page footer + page-size selector |
|
|
103
|
+
| `DataTable size="compact"` | Dense data (admin tools, reconciliation views) | Reduced `--table-row-height` |
|
|
104
|
+
|
|
105
|
+
## 7. Implementation
|
|
106
|
+
|
|
107
|
+
| Framework | Component(s) | File |
|
|
108
|
+
|---|---|---|
|
|
109
|
+
| **React (this app)** | `DataTable`, `DataTablePaginated`, `useTableState`, `DataTableToolbar`, `TablePropertiesDrawer`, **importable cell renderers** in `components/data-views/table-cells.tsx` (`ProgressCell`, `CurrencyCell`, `RatingCell`, `RowActionsCell<TRow>`, …) | [`packages/ui/src/components/data-table/`](../../../../packages/ui/src/components/data-table/), [`apps/web/components/data-views/table-cells.tsx`](../../components/data-views/table-cells.tsx), [`packages/ui/src/components/table-properties/`](../../../../packages/ui/src/components/table-properties/) |
|
|
110
|
+
| Mobile | — | — |
|
|
111
|
+
| Figma | — | — |
|
|
112
|
+
|
|
113
|
+
Reference compositions:
|
|
114
|
+
|
|
115
|
+
- **Placements** — `PlacementsClient` + `PlacementsTable` (most complete reference)
|
|
116
|
+
- **Team** — `TeamClient` + `TeamTable`
|
|
117
|
+
- **Compliance** — `ComplianceClient` + `ComplianceTable`
|
|
118
|
+
- **Library** — `LibraryClient` + `LibraryTable` (adds folder
|
|
119
|
+
scope from URL)
|
|
120
|
+
|
|
121
|
+
## 8. Do / Don't
|
|
122
|
+
|
|
123
|
+
| ✅ Do | ❌ Don't |
|
|
124
|
+
|---|---|
|
|
125
|
+
| Use **one** `useTableState` per logical table; pass `tableState.rows` to every connected view (list/board/dashboard) | Hydrate a board / list view from a parallel mock array — the count will diverge from the table |
|
|
126
|
+
| Wrap the table in `ListPageTemplate` so view tabs exist | Render `DataTable` directly under `PageHeader` for a primary hub |
|
|
127
|
+
| Pass `currentView` + `onViewChange` to `TablePropertiesDrawer` so Properties matches the active tab | Mount `TablePropertiesDrawer` on a multi-view page without `currentView` — it defaults to "Table display" copy on Board |
|
|
128
|
+
| Use `font-mono tabular-nums` on system IDs only | Apply `font-mono` to names, statuses, or dates |
|
|
129
|
+
| Mark sort headers with `aria-sort` and visible direction glyph | Use color alone to communicate sort direction |
|
|
130
|
+
| Search keyboard hint shows `⌘K` (no Alt) | Use `⌘⌥K` for the table search — that chord is Ask Leo |
|
|
131
|
+
|
|
132
|
+
## 9. References
|
|
133
|
+
|
|
134
|
+
- [`apps/web/docs/data-views-pattern.md`](../data-views-pattern.md) — architecture narrative
|
|
135
|
+
- [`.cursor/rules/exxat-data-tables.mdc`](../../../.cursor/rules/exxat-data-tables.mdc) — the mandatory stack
|
|
136
|
+
- [`.cursor/rules/exxat-list-page-connected-views.mdc`](../../../.cursor/rules/exxat-list-page-connected-views.mdc) — `tableState.rows` across views
|
|
137
|
+
- [`.cursor/rules/exxat-centralized-list-dataset.mdc`](../../../.cursor/rules/exxat-centralized-list-dataset.mdc) — one dataset rule
|
|
138
|
+
- [`.cursor/rules/exxat-table-properties-drawer.mdc`](../../../.cursor/rules/exxat-table-properties-drawer.mdc) — Properties drawer + active view
|
|
139
|
+
- [`apps/web/AGENTS.md`](../../AGENTS.md) §3, §4, §5
|