@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
|
@@ -1,183 +1 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* DotPattern — dot grid revealed by a soft drifting "cloud" mask.
|
|
5
|
-
*
|
|
6
|
-
* Inspiration: Google/Apple AI loading states — a diffuse dot field that
|
|
7
|
-
* softly fades in, drifts diagonally across the surface, then fades out.
|
|
8
|
-
* No bright glow cores, no particles — just one or two large soft halos
|
|
9
|
-
* sliding across the grid so the dots appear as an ambient cloud.
|
|
10
|
-
*/
|
|
11
|
-
|
|
12
|
-
import * as React from "react"
|
|
13
|
-
import { motion } from "motion/react"
|
|
14
|
-
import { cn } from "@/lib/utils"
|
|
15
|
-
|
|
16
|
-
interface DotPatternProps extends React.SVGProps<SVGSVGElement> {
|
|
17
|
-
width?: number
|
|
18
|
-
height?: number
|
|
19
|
-
x?: number
|
|
20
|
-
y?: number
|
|
21
|
-
cx?: number
|
|
22
|
-
cy?: number
|
|
23
|
-
cr?: number
|
|
24
|
-
className?: string
|
|
25
|
-
glow?: boolean
|
|
26
|
-
/** Number of drifting soft clouds (keep small: 1–2). */
|
|
27
|
-
glowCount?: number
|
|
28
|
-
/** Cloud radius — large values produce a wide, diffuse reveal. */
|
|
29
|
-
glowRadius?: number
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
type Cloud = {
|
|
33
|
-
key: number
|
|
34
|
-
xs: string[]
|
|
35
|
-
ys: string[]
|
|
36
|
-
duration: number
|
|
37
|
-
delay: number
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
/**
|
|
41
|
-
* Tiny deterministic PRNG (mulberry32). We use a seeded RNG instead of
|
|
42
|
-
* `Math.random()` so the SVG attributes emitted on the server match the
|
|
43
|
-
* client's first paint — otherwise React reports a hydration mismatch and
|
|
44
|
-
* has to re-paint every drifting `<motion.circle>` on mount, which is both
|
|
45
|
-
* a perf cost and a visible jump.
|
|
46
|
-
*/
|
|
47
|
-
function mulberry32(seed: number): () => number {
|
|
48
|
-
let s = seed >>> 0
|
|
49
|
-
return () => {
|
|
50
|
-
s = (s + 0x6d2b79f5) >>> 0
|
|
51
|
-
let t = s
|
|
52
|
-
t = Math.imul(t ^ (t >>> 15), t | 1)
|
|
53
|
-
t ^= t + Math.imul(t ^ (t >>> 7), t | 61)
|
|
54
|
-
return ((t ^ (t >>> 14)) >>> 0) / 4294967296
|
|
55
|
-
}
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
function hashString(str: string): number {
|
|
59
|
-
// Cheap FNV-1a-style hash. Stable across SSR + CSR for the same input.
|
|
60
|
-
let h = 2166136261
|
|
61
|
-
for (let i = 0; i < str.length; i++) {
|
|
62
|
-
h ^= str.charCodeAt(i)
|
|
63
|
-
h = Math.imul(h, 16777619)
|
|
64
|
-
}
|
|
65
|
-
return h >>> 0
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
export function DotPattern({
|
|
69
|
-
width = 14,
|
|
70
|
-
height = 14,
|
|
71
|
-
x = 0,
|
|
72
|
-
y = 0,
|
|
73
|
-
cx = 1,
|
|
74
|
-
cy = 1,
|
|
75
|
-
cr = 0.8,
|
|
76
|
-
className,
|
|
77
|
-
glow = false,
|
|
78
|
-
glowCount = 2,
|
|
79
|
-
glowRadius = 240,
|
|
80
|
-
...props
|
|
81
|
-
}: DotPatternProps) {
|
|
82
|
-
const id = React.useId()
|
|
83
|
-
const maskId = `${id}-mask`
|
|
84
|
-
const gradId = `${id}-grad`
|
|
85
|
-
|
|
86
|
-
const clouds = React.useMemo<Cloud[]>(() => {
|
|
87
|
-
const rng = mulberry32(hashString(`${id}|${glowCount}`))
|
|
88
|
-
const rand = (min: number, max: number) => min + rng() * (max - min)
|
|
89
|
-
return Array.from({ length: glowCount }).map((_, i) => {
|
|
90
|
-
// Drift diagonally: bottom-right → top-left. Start/end partly off-canvas
|
|
91
|
-
// so the cloud enters and exits softly without a visible edge.
|
|
92
|
-
const startX = rand(85, 120)
|
|
93
|
-
const endX = rand(-20, 15)
|
|
94
|
-
const midX = (startX + endX) / 2 + rand(-6, 6)
|
|
95
|
-
|
|
96
|
-
const startY = rand(85, 115)
|
|
97
|
-
const endY = rand(-15, 10)
|
|
98
|
-
const midY = (startY + endY) / 2 + rand(-4, 4)
|
|
99
|
-
|
|
100
|
-
const duration = rand(8, 12)
|
|
101
|
-
// Offset clouds by half a cycle so one is arriving as the other leaves.
|
|
102
|
-
const delay = -(i / glowCount) * duration
|
|
103
|
-
|
|
104
|
-
return {
|
|
105
|
-
key: i,
|
|
106
|
-
xs: [`${startX}%`, `${midX}%`, `${endX}%`],
|
|
107
|
-
ys: [`${startY}%`, `${midY}%`, `${endY}%`],
|
|
108
|
-
duration,
|
|
109
|
-
delay,
|
|
110
|
-
}
|
|
111
|
-
})
|
|
112
|
-
}, [glowCount, id])
|
|
113
|
-
|
|
114
|
-
return (
|
|
115
|
-
<svg
|
|
116
|
-
aria-hidden="true"
|
|
117
|
-
className={cn(
|
|
118
|
-
"pointer-events-none absolute inset-0 h-full w-full fill-neutral-400/80",
|
|
119
|
-
className,
|
|
120
|
-
)}
|
|
121
|
-
{...props}
|
|
122
|
-
>
|
|
123
|
-
<defs>
|
|
124
|
-
<pattern
|
|
125
|
-
id={id}
|
|
126
|
-
width={width}
|
|
127
|
-
height={height}
|
|
128
|
-
patternUnits="userSpaceOnUse"
|
|
129
|
-
patternContentUnits="userSpaceOnUse"
|
|
130
|
-
x={x}
|
|
131
|
-
y={y}
|
|
132
|
-
>
|
|
133
|
-
<circle cx={cx} cy={cy} r={cr} />
|
|
134
|
-
</pattern>
|
|
135
|
-
|
|
136
|
-
{glow ? (
|
|
137
|
-
<>
|
|
138
|
-
{/* Very soft falloff — no visible ring edge, dots dissolve gradually. */}
|
|
139
|
-
<radialGradient id={gradId}>
|
|
140
|
-
<stop offset="0%" stopColor="white" stopOpacity="0.9" />
|
|
141
|
-
<stop offset="40%" stopColor="white" stopOpacity="0.55" />
|
|
142
|
-
<stop offset="75%" stopColor="white" stopOpacity="0.18" />
|
|
143
|
-
<stop offset="100%" stopColor="white" stopOpacity="0" />
|
|
144
|
-
</radialGradient>
|
|
145
|
-
|
|
146
|
-
<mask id={maskId}>
|
|
147
|
-
{clouds.map((c) => (
|
|
148
|
-
<motion.circle
|
|
149
|
-
key={`cloud-${c.key}`}
|
|
150
|
-
r={glowRadius}
|
|
151
|
-
fill={`url(#${gradId})`}
|
|
152
|
-
initial={{ cx: c.xs[0], cy: c.ys[0], opacity: 0 }}
|
|
153
|
-
animate={{
|
|
154
|
-
cx: c.xs,
|
|
155
|
-
cy: c.ys,
|
|
156
|
-
// Long hold with soft fade at both ends.
|
|
157
|
-
opacity: [0, 1, 1, 0],
|
|
158
|
-
}}
|
|
159
|
-
transition={{
|
|
160
|
-
duration: c.duration,
|
|
161
|
-
delay: c.delay,
|
|
162
|
-
repeat: Infinity,
|
|
163
|
-
ease: "linear",
|
|
164
|
-
times: [0, 0.3, 0.7, 1],
|
|
165
|
-
}}
|
|
166
|
-
/>
|
|
167
|
-
))}
|
|
168
|
-
</mask>
|
|
169
|
-
</>
|
|
170
|
-
) : null}
|
|
171
|
-
</defs>
|
|
172
|
-
|
|
173
|
-
{/* Dot grid — only visible inside the drifting soft clouds when glow is on. */}
|
|
174
|
-
<rect
|
|
175
|
-
width="100%"
|
|
176
|
-
height="100%"
|
|
177
|
-
strokeWidth={0}
|
|
178
|
-
fill={`url(#${id})`}
|
|
179
|
-
mask={glow ? `url(#${maskId})` : undefined}
|
|
180
|
-
/>
|
|
181
|
-
</svg>
|
|
182
|
-
)
|
|
183
|
-
}
|
|
1
|
+
export * from "@exxatdesignux/ui/components/dot-pattern"
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from "@exxatdesignux/ui/components/hover-card"
|
|
@@ -1,68 +1 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
import * as React from "react"
|
|
4
|
-
import { GripVertical } from "lucide-react"
|
|
5
|
-
import { Group, Panel, Separator } from "react-resizable-panels"
|
|
6
|
-
import type { GroupProps, PanelProps, SeparatorProps } from "react-resizable-panels"
|
|
7
|
-
|
|
8
|
-
import { cn } from "@/lib/utils"
|
|
9
|
-
|
|
10
|
-
// ─── ResizablePanelGroup ──────────────────────────────────────────────────────
|
|
11
|
-
|
|
12
|
-
export type ResizablePanelGroupProps = Omit<GroupProps, "orientation"> & {
|
|
13
|
-
direction?: "horizontal" | "vertical"
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
export function ResizablePanelGroup({
|
|
17
|
-
direction = "horizontal",
|
|
18
|
-
className,
|
|
19
|
-
...props
|
|
20
|
-
}: ResizablePanelGroupProps) {
|
|
21
|
-
return (
|
|
22
|
-
<Group
|
|
23
|
-
orientation={direction}
|
|
24
|
-
className={cn(
|
|
25
|
-
"flex h-full w-full",
|
|
26
|
-
direction === "vertical" && "flex-col",
|
|
27
|
-
className,
|
|
28
|
-
)}
|
|
29
|
-
{...props}
|
|
30
|
-
/>
|
|
31
|
-
)
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
// ─── ResizablePanel ───────────────────────────────────────────────────────────
|
|
35
|
-
|
|
36
|
-
export type ResizablePanelProps = PanelProps
|
|
37
|
-
|
|
38
|
-
export const ResizablePanel = Panel
|
|
39
|
-
|
|
40
|
-
// ─── ResizableHandle ──────────────────────────────────────────────────────────
|
|
41
|
-
|
|
42
|
-
export type ResizableHandleProps = Omit<SeparatorProps, "children"> & {
|
|
43
|
-
/** Render a visible grip icon on the handle. */
|
|
44
|
-
withHandle?: boolean
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
export function ResizableHandle({ withHandle, className, ...props }: ResizableHandleProps) {
|
|
48
|
-
return (
|
|
49
|
-
<Separator
|
|
50
|
-
className={cn(
|
|
51
|
-
// Base — horizontal handle (between side-by-side panels)
|
|
52
|
-
"relative flex w-1 shrink-0 cursor-col-resize items-center justify-center bg-border/60",
|
|
53
|
-
"transition-colors hover:bg-border active:bg-primary/30",
|
|
54
|
-
"focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-1",
|
|
55
|
-
// Vertical handle (between stacked panels)
|
|
56
|
-
"data-[orientation=vertical]:h-1 data-[orientation=vertical]:w-full data-[orientation=vertical]:cursor-row-resize data-[orientation=vertical]:flex-row",
|
|
57
|
-
className,
|
|
58
|
-
)}
|
|
59
|
-
{...props}
|
|
60
|
-
>
|
|
61
|
-
{withHandle && (
|
|
62
|
-
<div className="z-10 flex h-5 w-3.5 items-center justify-center rounded-sm border border-border bg-background shadow-sm">
|
|
63
|
-
<GripVertical className="h-3 w-3 text-muted-foreground" />
|
|
64
|
-
</div>
|
|
65
|
-
)}
|
|
66
|
-
</Separator>
|
|
67
|
-
)
|
|
68
|
-
}
|
|
1
|
+
export * from "@exxatdesignux/ui/components/resizable"
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from "@exxatdesignux/ui/components/scroll-area"
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from "@exxatdesignux/ui/components/slider"
|
|
@@ -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`, `QuestionBankPageHeader` |
|
|
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 (Question bank 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
|