@exxatdesignux/ui 0.5.10 → 0.5.12
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 +37 -0
- package/bin/cli.mjs +70 -1
- package/bin/init.mjs +18 -4
- package/bin/sync-extras.mjs +28 -4
- package/consumer-extras/README.md +41 -5
- package/consumer-extras/cursor-rules/exxat-accessibility.mdc +2 -1
- package/consumer-extras/cursor-rules/exxat-board-cards.mdc +5 -3
- package/consumer-extras/cursor-rules/exxat-breadcrumbs-no-back.mdc +1 -0
- package/consumer-extras/cursor-rules/exxat-card-vs-list-rows.mdc +1 -0
- package/consumer-extras/cursor-rules/exxat-centralized-list-dataset.mdc +4 -2
- package/consumer-extras/cursor-rules/exxat-collaboration-access.mdc +1 -0
- package/consumer-extras/cursor-rules/exxat-command-menu.mdc +3 -2
- package/consumer-extras/cursor-rules/exxat-data-tables.mdc +5 -3
- package/consumer-extras/cursor-rules/exxat-dedicated-search-surfaces.mdc +7 -0
- package/consumer-extras/cursor-rules/exxat-drawer-vs-dialog.mdc +2 -1
- package/consumer-extras/cursor-rules/exxat-ds-agents.mdc +13 -2
- package/consumer-extras/cursor-rules/exxat-fontawesome-icons.mdc +1 -0
- package/consumer-extras/cursor-rules/exxat-hub-supported-views.mdc +6 -4
- package/consumer-extras/cursor-rules/exxat-kbd-shortcuts.mdc +6 -5
- package/consumer-extras/cursor-rules/exxat-kpi-flat-band.mdc +1 -0
- package/consumer-extras/cursor-rules/exxat-kpi-max-four.mdc +1 -0
- package/consumer-extras/cursor-rules/exxat-kpi-trends.mdc +1 -0
- package/consumer-extras/cursor-rules/exxat-library-hub-header.mdc +2 -1
- package/consumer-extras/cursor-rules/exxat-list-page-connected-views.mdc +6 -2
- package/consumer-extras/cursor-rules/exxat-list-page-view-shells.mdc +2 -1
- package/consumer-extras/cursor-rules/exxat-mono-ids.mdc +2 -1
- package/consumer-extras/cursor-rules/exxat-nav-single-active.mdc +4 -3
- package/consumer-extras/cursor-rules/exxat-no-image-pixel-copy.mdc +25 -14
- package/consumer-extras/cursor-rules/exxat-no-slds-leakage.mdc +8 -2
- package/consumer-extras/cursor-rules/exxat-no-toast.mdc +1 -0
- package/consumer-extras/cursor-rules/exxat-no-vaul.mdc +2 -1
- package/consumer-extras/cursor-rules/exxat-page-header-actions.mdc +6 -4
- package/consumer-extras/cursor-rules/exxat-page-vs-drawer.mdc +2 -1
- package/consumer-extras/cursor-rules/exxat-person-identity-display.mdc +1 -0
- package/consumer-extras/cursor-rules/exxat-primary-nav-secondary-panel.mdc +2 -1
- package/consumer-extras/cursor-rules/exxat-reuse-before-custom.mdc +1 -0
- package/consumer-extras/cursor-rules/exxat-sidebar-shell.mdc +13 -7
- package/consumer-extras/cursor-rules/exxat-table-properties-drawer.mdc +5 -3
- package/consumer-extras/cursor-rules/exxat-table-row-preview.mdc +1 -0
- package/consumer-extras/cursor-rules/exxat-tabs-chrome.mdc +6 -4
- package/consumer-extras/cursor-rules/exxat-token-discipline.mdc +6 -0
- package/consumer-extras/cursor-rules/exxat-ux-discovery-protocol.mdc +92 -12
- package/consumer-extras/cursor-rules/exxat-ux-principles.mdc +1 -0
- package/consumer-extras/cursor-skills/exxat-ds-skill/SKILL.md +1 -1
- package/consumer-extras/cursor-skills/exxat-kpi-trends/SKILL.md +5 -3
- package/consumer-extras/cursor-skills/exxat-senior-ux/SKILL.md +70 -17
- package/consumer-extras/patterns/command-menu-pattern.md +2 -2
- package/consumer-extras/patterns/consumer-upgrade-checklist.md +1 -1
- package/consumer-extras/patterns/jobs/README.md +1 -1
- package/consumer-extras/patterns/perf-memory-pattern.md +115 -150
- package/consumer-extras/scripts/dev-guard.mjs +156 -0
- package/consumer-extras/templates/README.md +23 -0
- package/consumer-extras/templates/handoff.md +190 -0
- package/dist/hooks/use-app-theme.d.ts +1 -1
- package/package.json +2 -2
- package/{template → template-vite}/.claude/skills/exxat-ds-skill/SKILL.md +184 -23
- package/template-vite/.cursor/rules/exxat-accessibility.mdc +40 -0
- package/template-vite/.cursor/rules/exxat-board-cards.mdc +28 -0
- package/template-vite/.cursor/rules/exxat-breadcrumbs-no-back.mdc +22 -0
- package/template-vite/.cursor/rules/exxat-card-vs-list-rows.mdc +22 -0
- package/template-vite/.cursor/rules/exxat-centralized-list-dataset.mdc +46 -0
- package/template-vite/.cursor/rules/exxat-collaboration-access.mdc +33 -0
- package/{template → template-vite}/.cursor/rules/exxat-command-menu.mdc +5 -5
- package/template-vite/.cursor/rules/exxat-data-tables.mdc +47 -0
- package/template-vite/.cursor/rules/exxat-dedicated-search-surfaces.mdc +32 -0
- package/template-vite/.cursor/rules/exxat-drawer-vs-dialog.mdc +23 -0
- package/template-vite/.cursor/rules/exxat-ds-agents.mdc +87 -0
- package/template-vite/.cursor/rules/exxat-fontawesome-icons.mdc +32 -0
- package/template-vite/.cursor/rules/exxat-hub-supported-views.mdc +56 -0
- package/{template → template-vite}/.cursor/rules/exxat-kbd-shortcuts.mdc +1 -0
- package/template-vite/.cursor/rules/exxat-kpi-flat-band.mdc +29 -0
- package/template-vite/.cursor/rules/exxat-kpi-max-four.mdc +22 -0
- package/template-vite/.cursor/rules/exxat-kpi-trends.mdc +32 -0
- package/template-vite/.cursor/rules/exxat-library-hub-header.mdc +29 -0
- package/template-vite/.cursor/rules/exxat-list-page-connected-views.mdc +28 -0
- package/template-vite/.cursor/rules/exxat-list-page-view-shells.mdc +32 -0
- package/{template → template-vite}/.cursor/rules/exxat-mono-ids.mdc +1 -0
- package/template-vite/.cursor/rules/exxat-nav-single-active.mdc +32 -0
- package/template-vite/.cursor/rules/exxat-no-image-pixel-copy.mdc +46 -0
- package/template-vite/.cursor/rules/exxat-no-slds-leakage.mdc +84 -0
- package/{template → template-vite}/.cursor/rules/exxat-no-toast.mdc +2 -2
- package/template-vite/.cursor/rules/exxat-no-vaul.mdc +26 -0
- package/template-vite/.cursor/rules/exxat-page-header-actions.mdc +33 -0
- package/{template → template-vite}/.cursor/rules/exxat-page-vs-drawer.mdc +5 -3
- package/template-vite/.cursor/rules/exxat-person-identity-display.mdc +48 -0
- package/template-vite/.cursor/rules/exxat-primary-nav-secondary-panel.mdc +53 -0
- package/template-vite/.cursor/rules/exxat-reuse-before-custom.mdc +37 -0
- package/template-vite/.cursor/rules/exxat-sidebar-shell.mdc +41 -0
- package/template-vite/.cursor/rules/exxat-table-properties-drawer.mdc +79 -0
- package/template-vite/.cursor/rules/exxat-table-row-preview.mdc +25 -0
- package/template-vite/.cursor/rules/exxat-tabs-chrome.mdc +33 -0
- package/template-vite/.cursor/rules/exxat-token-discipline.mdc +109 -0
- package/template-vite/.cursor/rules/exxat-ux-discovery-protocol.mdc +202 -0
- package/template-vite/.cursor/rules/exxat-ux-principles.mdc +187 -0
- package/template-vite/.cursor/skills/exxat-accessibility/SKILL.md +282 -0
- package/template-vite/.cursor/skills/exxat-board-cards/SKILL.md +68 -0
- package/template-vite/.cursor/skills/exxat-card-vs-list-rows/SKILL.md +20 -0
- package/template-vite/.cursor/skills/exxat-centralized-list-dataset/SKILL.md +99 -0
- package/template-vite/.cursor/skills/exxat-collaboration-access/SKILL.md +35 -0
- package/template-vite/.cursor/skills/exxat-dedicated-search-surfaces/SKILL.md +45 -0
- package/template-vite/.cursor/skills/exxat-drawer-vs-dialog/SKILL.md +20 -0
- package/template-vite/.cursor/skills/exxat-ds-skill/SKILL.md +893 -0
- package/template-vite/.cursor/skills/exxat-ds-skill/references/accessibility.md +142 -0
- package/template-vite/.cursor/skills/exxat-ds-skill/references/coach-marks.md +169 -0
- package/template-vite/.cursor/skills/exxat-ds-skill/references/data-table-pattern.md +392 -0
- package/template-vite/.cursor/skills/exxat-fontawesome-icons/SKILL.md +31 -0
- package/template-vite/.cursor/skills/exxat-kpi-flat-band/SKILL.md +38 -0
- package/template-vite/.cursor/skills/exxat-kpi-max-four/SKILL.md +19 -0
- package/template-vite/.cursor/skills/exxat-kpi-trends/SKILL.md +29 -0
- package/template-vite/.cursor/skills/exxat-list-page-view-shells/SKILL.md +36 -0
- package/template-vite/.cursor/skills/exxat-mono-ids/SKILL.md +56 -0
- package/template-vite/.cursor/skills/exxat-primary-nav-secondary-panel/SKILL.md +49 -0
- package/template-vite/.cursor/skills/exxat-senior-ux/SKILL.md +198 -0
- package/template-vite/.cursor/skills/exxat-token-economy/SKILL.md +287 -0
- package/template-vite/.cursor/skills/exxat-ux-audit/SKILL.md +303 -0
- package/{template → template-vite}/components/ask-leo-sidebar.tsx +10 -8
- package/{template → template-vite}/components/command-menu.tsx +1 -1
- package/{template → template-vite}/components/data-views/library-folder-tree-branch.tsx +1 -1
- package/{template → template-vite}/components/dedicated-search-recents.tsx +1 -1
- package/{template → template-vite}/components/dedicated-search-url-composer.tsx +1 -1
- package/{template → template-vite}/components/library-client.tsx +1 -1
- package/{template → template-vite}/components/library-hub-client.tsx +2 -2
- package/{template → template-vite}/components/library-secondary-nav.tsx +2 -2
- package/{template → template-vite}/components/library-table.tsx +35 -27
- package/{template → template-vite}/components/new-library-item-form.tsx +1 -1
- package/{template → template-vite}/components/page-breadcrumb-trail.tsx +1 -1
- package/{template → template-vite}/components/settings-client.tsx +1 -1
- package/{template → template-vite}/components/sidebar/app-sidebar.tsx +2 -2
- package/{template → template-vite}/components/sidebar/nav-main.tsx +1 -1
- package/{template → template-vite}/components/sidebar/nav-user.tsx +1 -1
- package/{template → template-vite}/components/sidebar/secondary-nav.tsx +1 -1
- package/{template → template-vite}/components/system-banner-slot.tsx +1 -1
- package/{template → template-vite}/components/templates/discovery-hub-template.tsx +2 -2
- package/{template → template-vite}/components/templates/new-focus-template.tsx +1 -1
- package/{template → template-vite}/components/tokens-secondary-nav.tsx +2 -2
- package/{template → template-vite}/components/tokens-themes-client.tsx +1 -1
- package/{template → template-vite}/hooks/use-secondary-panel-hub-nav.ts +1 -1
- package/template-vite/index.html +49 -0
- package/template-vite/lib/next-compat.tsx +98 -0
- package/{template → template-vite}/package.json +15 -27
- package/template-vite/scripts/port-next-imports.mjs +70 -0
- package/template-vite/src/App.tsx +103 -0
- package/template-vite/src/main.tsx +50 -0
- package/{template/app/(app)/error.tsx → template-vite/src/pages/_error.tsx} +12 -24
- package/{template/app/(app)/loading.tsx → template-vite/src/pages/_loading.tsx} +4 -2
- package/template-vite/src/pages/_not-found.tsx +17 -0
- package/template-vite/src/pages/dashboard.tsx +48 -0
- package/{template/app/(app)/help/page.tsx → template-vite/src/pages/help.tsx} +3 -2
- package/{template/app/(app)/library/layout.tsx → template-vite/src/pages/library/_layout.tsx} +18 -16
- package/{template/app/(app)/library/all/page.tsx → template-vite/src/pages/library/all.tsx} +1 -1
- package/{template/app/(app)/library/new/page.tsx → template-vite/src/pages/library/new.tsx} +12 -18
- package/template-vite/src/routes.tsx +72 -0
- package/{template/app → template-vite/src/styles}/globals.css +6 -2
- package/{template → template-vite}/tsconfig.json +5 -14
- package/template-vite/vite.config.ts +52 -0
- package/consumer-extras/cursor-rules/exxat-dashboard-view-charts.mdc +0 -53
- package/template/.agents/skills/shadcn/SKILL.md +0 -242
- package/template/.agents/skills/shadcn/agents/openai.yml +0 -5
- package/template/.agents/skills/shadcn/assets/shadcn-small.png +0 -0
- package/template/.agents/skills/shadcn/assets/shadcn.png +0 -0
- package/template/.agents/skills/shadcn/cli.md +0 -257
- package/template/.agents/skills/shadcn/customization.md +0 -202
- package/template/.agents/skills/shadcn/evals/evals.json +0 -47
- package/template/.agents/skills/shadcn/mcp.md +0 -94
- package/template/.agents/skills/shadcn/rules/base-vs-radix.md +0 -306
- package/template/.agents/skills/shadcn/rules/composition.md +0 -195
- package/template/.agents/skills/shadcn/rules/forms.md +0 -192
- package/template/.agents/skills/shadcn/rules/icons.md +0 -101
- package/template/.agents/skills/shadcn/rules/styling.md +0 -162
- package/template/.cursor/rules/exxat-accessibility.mdc +0 -33
- package/template/.cursor/rules/exxat-data-tables.mdc +0 -32
- package/template/.cursor/rules/exxat-ds-agents.mdc +0 -26
- package/template/.cursor/rules/exxat-list-page-connected-views.mdc +0 -16
- package/template/.cursor/rules/exxat-table-properties-drawer.mdc +0 -40
- package/template/.nvmrc +0 -1
- package/template/.prettierignore +0 -7
- package/template/Logo/Exxat_Prism.svg +0 -39
- package/template/Logo/Exxat_one.svg +0 -36
- package/template/app/(app)/dashboard/loading.tsx +0 -18
- package/template/app/(app)/dashboard/page.tsx +0 -36
- package/template/app/(app)/layout.tsx +0 -77
- package/template/app/global-error.tsx +0 -63
- package/template/app/layout.tsx +0 -133
- package/template/app/page.tsx +0 -9
- package/template/docs/HANDBOOK.md +0 -187
- package/template/docs/blueprints/README.md +0 -86
- package/template/docs/blueprints/_template.md +0 -91
- package/template/docs/blueprints/board-card.md +0 -123
- package/template/docs/blueprints/data-table.md +0 -139
- package/template/docs/blueprints/key-metrics.md +0 -128
- package/template/docs/blueprints/list-page-template.md +0 -123
- package/template/docs/blueprints/page-header.md +0 -130
- package/template/docs/card-vs-rows-pattern.md +0 -36
- package/template/docs/collaboration-access-pattern.md +0 -116
- package/template/docs/command-menu-pattern.md +0 -45
- package/template/docs/component-selection-guide.md +0 -224
- package/template/docs/components-audit-2026-05.md +0 -158
- package/template/docs/consumer-upgrade-checklist.md +0 -52
- package/template/docs/data-views-pattern.md +0 -185
- package/template/docs/drawer-vs-dialog-pattern.md +0 -50
- package/template/docs/glossary.md +0 -59
- package/template/docs/hub-supported-views-pattern.md +0 -53
- package/template/docs/jobs/README.md +0 -59
- package/template/docs/jobs/record-detail.md +0 -177
- package/template/docs/kpi-flat-band-pattern.md +0 -57
- package/template/docs/kpi-strip-max-four-pattern.md +0 -30
- package/template/docs/kpi-trend-pattern.md +0 -58
- package/template/docs/large-dataset-strategy.md +0 -155
- package/template/docs/library-hub-header-pattern.md +0 -25
- package/template/docs/migrations/0001-brand-deep-alias-stabilization.md +0 -95
- package/template/docs/migrations/0002-exxat-token-namespace.md +0 -154
- package/template/docs/migrations/0003-globals-css-canonical.md +0 -110
- package/template/docs/migrations/README.md +0 -100
- package/template/docs/migrations/_template.md +0 -64
- package/template/docs/modern-saas-patterns.md +0 -165
- package/template/docs/perf-memory-pattern.md +0 -206
- package/template/docs/reference-implementations.md +0 -153
- package/template/docs/shell-surface-elevation-pattern.md +0 -52
- package/template/docs/token-taxonomy.md +0 -416
- package/template/docs/voice-and-tone.md +0 -262
- package/template/ecosystem.config.cjs +0 -32
- package/template/next.config.mjs +0 -216
- package/template/postcss.config.mjs +0 -8
- package/template/public/favicon/favicon.ico +0 -0
- package/template/tests/setup.ts +0 -26
- package/template/vitest.config.ts +0 -18
- /package/{template → template-vite}/.cursor/rules/exxat-dashboard-view-charts.mdc +0 -0
- /package/{template → template-vite}/.prettierrc +0 -0
- /package/{template → template-vite}/AGENTS.md +0 -0
- /package/{template → template-vite}/README.md +0 -0
- /package/{template → template-vite}/components/.gitkeep +0 -0
- /package/{template → template-vite}/components/ask-leo-composer.tsx +0 -0
- /package/{template → template-vite}/components/brand-color-picker.tsx +0 -0
- /package/{template → template-vite}/components/chart-area-interactive.tsx +0 -0
- /package/{template → template-vite}/components/charts-overview.tsx +0 -0
- /package/{template → template-vite}/components/collaboration-access-flow.tsx +0 -0
- /package/{template → template-vite}/components/columns-client.tsx +0 -0
- /package/{template → template-vite}/components/columns-showcase.tsx +0 -0
- /package/{template → template-vite}/components/dashboard-promo-banner.tsx +0 -0
- /package/{template → template-vite}/components/dashboard-quota-progress-card.tsx +0 -0
- /package/{template → template-vite}/components/dashboard-report-charts.tsx +0 -0
- /package/{template → template-vite}/components/dashboard-section-heading.tsx +0 -0
- /package/{template → template-vite}/components/dashboard-tabs.tsx +0 -0
- /package/{template → template-vite}/components/data-table/filter-date-calendar.tsx +0 -0
- /package/{template → template-vite}/components/data-table/filter-text-value-input.tsx +0 -0
- /package/{template → template-vite}/components/data-table/index.tsx +0 -0
- /package/{template → template-vite}/components/data-table/pagination.tsx +0 -0
- /package/{template → template-vite}/components/data-table/types.ts +0 -0
- /package/{template → template-vite}/components/data-table/use-table-state.test.ts +0 -0
- /package/{template → template-vite}/components/data-table/use-table-state.ts +0 -0
- /package/{template → template-vite}/components/data-views/board-card-primitives.tsx +0 -0
- /package/{template → template-vite}/components/data-views/data-row-list.tsx +0 -0
- /package/{template → template-vite}/components/data-views/finder-panel-view.tsx +0 -0
- /package/{template → template-vite}/components/data-views/folder-grid-view.tsx +0 -0
- /package/{template → template-vite}/components/data-views/hub-table.tsx +0 -0
- /package/{template → template-vite}/components/data-views/index.ts +0 -0
- /package/{template → template-vite}/components/data-views/list-page-board-card.tsx +0 -0
- /package/{template → template-vite}/components/data-views/list-page-board-template.tsx +0 -0
- /package/{template → template-vite}/components/data-views/list-page-connected-view-body.tsx +0 -0
- /package/{template → template-vite}/components/data-views/list-page-split-details-placeholder.tsx +0 -0
- /package/{template → template-vite}/components/data-views/list-page-split-hub-chrome.tsx +0 -0
- /package/{template → template-vite}/components/data-views/list-page-split-hub-tokens.ts +0 -0
- /package/{template → template-vite}/components/data-views/list-page-tree-column-header.tsx +0 -0
- /package/{template → template-vite}/components/data-views/list-page-tree-panel-shell.tsx +0 -0
- /package/{template → template-vite}/components/data-views/list-page-view-frame.tsx +0 -0
- /package/{template → template-vite}/components/data-views/os-folder-glyph.tsx +0 -0
- /package/{template → template-vite}/components/data-views/outline-tree-menu.tsx +0 -0
- /package/{template → template-vite}/components/data-views/table-cells.tsx +0 -0
- /package/{template → template-vite}/components/dev-chunk-load-recovery.tsx +0 -0
- /package/{template → template-vite}/components/export-drawer.test.tsx +0 -0
- /package/{template → template-vite}/components/export-drawer.tsx +0 -0
- /package/{template → template-vite}/components/exxat-product-logo.tsx +0 -0
- /package/{template → template-vite}/components/folder-details-shell.tsx +0 -0
- /package/{template → template-vite}/components/form-layout-01.tsx +0 -0
- /package/{template → template-vite}/components/hub-tree-panel-view.tsx +0 -0
- /package/{template → template-vite}/components/invite-collaborators-drawer.tsx +0 -0
- /package/{template → template-vite}/components/key-metrics-ask-leo-bridge.tsx +0 -0
- /package/{template → template-vite}/components/key-metrics.tsx +0 -0
- /package/{template → template-vite}/components/leo-insight-indicator.tsx +0 -0
- /package/{template → template-vite}/components/leo-typing-dots.tsx +0 -0
- /package/{template → template-vite}/components/library-board-view.tsx +0 -0
- /package/{template → template-vite}/components/library-dashboard-charts.tsx +0 -0
- /package/{template → template-vite}/components/library-favorite-button.tsx +0 -0
- /package/{template → template-vite}/components/library-new-folder-sheet.tsx +0 -0
- /package/{template → template-vite}/components/library-os-folder-view.tsx +0 -0
- /package/{template → template-vite}/components/library-page-header.tsx +0 -0
- /package/{template → template-vite}/components/library-panel-activator.tsx +0 -0
- /package/{template → template-vite}/components/list-hub-status-badge.tsx +0 -0
- /package/{template → template-vite}/components/list-page-dashboard-charts.tsx +0 -0
- /package/{template → template-vite}/components/onboarding/getting-started.tsx +0 -0
- /package/{template → template-vite}/components/onboarding/index.ts +0 -0
- /package/{template → template-vite}/components/onboarding/onboarding-01.tsx +0 -0
- /package/{template → template-vite}/components/onboarding/onboarding-02.tsx +0 -0
- /package/{template → template-vite}/components/onboarding/onboarding-03.tsx +0 -0
- /package/{template → template-vite}/components/onboarding/onboarding-04.tsx +0 -0
- /package/{template → template-vite}/components/page-header.tsx +0 -0
- /package/{template → template-vite}/components/product-switcher.tsx +0 -0
- /package/{template → template-vite}/components/product-wordmark.tsx +0 -0
- /package/{template → template-vite}/components/settings-appearance-card.tsx +0 -0
- /package/{template → template-vite}/components/settings-form-row.tsx +0 -0
- /package/{template → template-vite}/components/sidebar/app-sidebar-dynamic.tsx +0 -0
- /package/{template → template-vite}/components/sidebar/index.ts +0 -0
- /package/{template → template-vite}/components/sidebar/nav-documents.tsx +0 -0
- /package/{template → template-vite}/components/sidebar/nav-secondary.tsx +0 -0
- /package/{template → template-vite}/components/sidebar/secondary-panel.tsx +0 -0
- /package/{template → template-vite}/components/sidebar/sidebar-auto-collapse.tsx +0 -0
- /package/{template → template-vite}/components/sidebar/sidebar-auto-open.tsx +0 -0
- /package/{template → template-vite}/components/sidebar/sidebar-shell.tsx +0 -0
- /package/{template → template-vite}/components/site-header.tsx +0 -0
- /package/{template → template-vite}/components/table-properties/column-row.tsx +0 -0
- /package/{template → template-vite}/components/table-properties/draggable-list.ts +0 -0
- /package/{template → template-vite}/components/table-properties/drawer-button.tsx +0 -0
- /package/{template → template-vite}/components/table-properties/drawer.tsx +0 -0
- /package/{template → template-vite}/components/table-properties/filter-card.tsx +0 -0
- /package/{template → template-vite}/components/table-properties/index.ts +0 -0
- /package/{template → template-vite}/components/table-properties/sort-card.tsx +0 -0
- /package/{template → template-vite}/components/table-properties/types.ts +0 -0
- /package/{template → template-vite}/components/task-list-panel.tsx +0 -0
- /package/{template → template-vite}/components/task-priority-badge.tsx +0 -0
- /package/{template → template-vite}/components/templates/dedicated-search-landing-template.tsx +0 -0
- /package/{template → template-vite}/components/templates/dedicated-search-results-template.tsx +0 -0
- /package/{template → template-vite}/components/templates/list-page.tsx +0 -0
- /package/{template → template-vite}/components/templates/nested-secondary-panel-shell.tsx +0 -0
- /package/{template → template-vite}/components/templates/primary-page-template.tsx +0 -0
- /package/{template → template-vite}/components/templates/secondary-panel-hub-template.tsx +0 -0
- /package/{template → template-vite}/components/theme-color-sync.tsx +0 -0
- /package/{template → template-vite}/components/theme-provider.tsx +0 -0
- /package/{template → template-vite}/components/tinted-icon-disc.tsx +0 -0
- /package/{template → template-vite}/components/tokens-hub-auxiliary-views.tsx +0 -0
- /package/{template → template-vite}/components/tokens-themes-section.tsx +0 -0
- /package/{template → template-vite}/components/ui/accordion.tsx +0 -0
- /package/{template → template-vite}/components/ui/ai-thinking-surface.tsx +0 -0
- /package/{template → template-vite}/components/ui/alert-dialog.tsx +0 -0
- /package/{template → template-vite}/components/ui/avatar.tsx +0 -0
- /package/{template → template-vite}/components/ui/badge.tsx +0 -0
- /package/{template → template-vite}/components/ui/banner.tsx +0 -0
- /package/{template → template-vite}/components/ui/breadcrumb.tsx +0 -0
- /package/{template → template-vite}/components/ui/button.tsx +0 -0
- /package/{template → template-vite}/components/ui/calendar.tsx +0 -0
- /package/{template → template-vite}/components/ui/card.tsx +0 -0
- /package/{template → template-vite}/components/ui/chart.tsx +0 -0
- /package/{template → template-vite}/components/ui/checkbox.tsx +0 -0
- /package/{template → template-vite}/components/ui/coach-mark.tsx +0 -0
- /package/{template → template-vite}/components/ui/collapsible.tsx +0 -0
- /package/{template → template-vite}/components/ui/command.tsx +0 -0
- /package/{template → template-vite}/components/ui/context-menu.tsx +0 -0
- /package/{template → template-vite}/components/ui/date-picker-field.tsx +0 -0
- /package/{template → template-vite}/components/ui/dialog.tsx +0 -0
- /package/{template → template-vite}/components/ui/dot-pattern.tsx +0 -0
- /package/{template → template-vite}/components/ui/drag-handle-grip.tsx +0 -0
- /package/{template → template-vite}/components/ui/dropdown-menu.tsx +0 -0
- /package/{template → template-vite}/components/ui/field.tsx +0 -0
- /package/{template → template-vite}/components/ui/form.tsx +0 -0
- /package/{template → template-vite}/components/ui/hover-card.tsx +0 -0
- /package/{template → template-vite}/components/ui/input-group.tsx +0 -0
- /package/{template → template-vite}/components/ui/input-mask.tsx +0 -0
- /package/{template → template-vite}/components/ui/input.tsx +0 -0
- /package/{template → template-vite}/components/ui/kbd.tsx +0 -0
- /package/{template → template-vite}/components/ui/label.tsx +0 -0
- /package/{template → template-vite}/components/ui/leo-icon.tsx +0 -0
- /package/{template → template-vite}/components/ui/payment-card-fields.tsx +0 -0
- /package/{template → template-vite}/components/ui/popover.tsx +0 -0
- /package/{template → template-vite}/components/ui/radio-group.tsx +0 -0
- /package/{template → template-vite}/components/ui/resizable.tsx +0 -0
- /package/{template → template-vite}/components/ui/scroll-area.tsx +0 -0
- /package/{template → template-vite}/components/ui/select.tsx +0 -0
- /package/{template → template-vite}/components/ui/selection-tile-grid.tsx +0 -0
- /package/{template → template-vite}/components/ui/separator.tsx +0 -0
- /package/{template → template-vite}/components/ui/sheet.tsx +0 -0
- /package/{template → template-vite}/components/ui/sidebar.tsx +0 -0
- /package/{template → template-vite}/components/ui/skeleton.tsx +0 -0
- /package/{template → template-vite}/components/ui/slider.tsx +0 -0
- /package/{template → template-vite}/components/ui/sonner.tsx +0 -0
- /package/{template → template-vite}/components/ui/status-badge.tsx +0 -0
- /package/{template → template-vite}/components/ui/table.tsx +0 -0
- /package/{template → template-vite}/components/ui/tabs.tsx +0 -0
- /package/{template → template-vite}/components/ui/textarea.tsx +0 -0
- /package/{template → template-vite}/components/ui/tip.tsx +0 -0
- /package/{template → template-vite}/components/ui/toggle-group.tsx +0 -0
- /package/{template → template-vite}/components/ui/toggle-switch.tsx +0 -0
- /package/{template → template-vite}/components/ui/toggle.tsx +0 -0
- /package/{template → template-vite}/components/ui/tooltip.tsx +0 -0
- /package/{template → template-vite}/components/ui/view-segmented-control.tsx +0 -0
- /package/{template → template-vite}/components.json +0 -0
- /package/{template → template-vite}/contexts/chart-variant-context.tsx +0 -0
- /package/{template → template-vite}/contexts/command-menu-context.tsx +0 -0
- /package/{template → template-vite}/contexts/dashboard-view-context.tsx +0 -0
- /package/{template → template-vite}/contexts/product-context.tsx +0 -0
- /package/{template → template-vite}/contexts/system-banner-context.tsx +0 -0
- /package/{template → template-vite}/eslint.config.mjs +0 -0
- /package/{template → template-vite}/fontawesome-subset.manifest.json +0 -0
- /package/{template → template-vite}/hooks/.gitkeep +0 -0
- /package/{template → template-vite}/hooks/use-app-theme.ts +0 -0
- /package/{template → template-vite}/hooks/use-coach-mark.ts +0 -0
- /package/{template → template-vite}/hooks/use-location-hash.ts +0 -0
- /package/{template → template-vite}/hooks/use-mobile.ts +0 -0
- /package/{template → template-vite}/hooks/use-mod-key-label.ts +0 -0
- /package/{template → template-vite}/hooks/use-sidebar-reflow-zoom.ts +0 -0
- /package/{template → template-vite}/lib/.gitkeep +0 -0
- /package/{template → template-vite}/lib/ask-leo-route-context.ts +0 -0
- /package/{template → template-vite}/lib/chart-keyboard-selection.test.ts +0 -0
- /package/{template → template-vite}/lib/chart-keyboard-selection.ts +0 -0
- /package/{template → template-vite}/lib/chart-line-dash.ts +0 -0
- /package/{template → template-vite}/lib/chunk-load-error.ts +0 -0
- /package/{template → template-vite}/lib/coach-mark-registry.ts +0 -0
- /package/{template → template-vite}/lib/collaborator-access.ts +0 -0
- /package/{template → template-vite}/lib/command-menu-config.ts +0 -0
- /package/{template → template-vite}/lib/command-menu-search-data.ts +0 -0
- /package/{template → template-vite}/lib/conditional-rule-match.ts +0 -0
- /package/{template → template-vite}/lib/dashboard-customize-coach-mark.ts +0 -0
- /package/{template → template-vite}/lib/dashboard-layout-merge.ts +0 -0
- /package/{template → template-vite}/lib/data-list-display-options.ts +0 -0
- /package/{template → template-vite}/lib/data-list-persistence.ts +0 -0
- /package/{template → template-vite}/lib/data-list-view-registry.ts +0 -0
- /package/{template → template-vite}/lib/data-list-view-surface.ts +0 -0
- /package/{template → template-vite}/lib/data-list-view.ts +0 -0
- /package/{template → template-vite}/lib/data-view-dashboard-storage.ts +0 -0
- /package/{template → template-vite}/lib/date-filter.ts +0 -0
- /package/{template → template-vite}/lib/dedicated-search-recents.ts +0 -0
- /package/{template → template-vite}/lib/dedicated-search-url.ts +0 -0
- /package/{template → template-vite}/lib/dev-log.test.ts +0 -0
- /package/{template → template-vite}/lib/dev-log.ts +0 -0
- /package/{template → template-vite}/lib/discovery-hub.ts +0 -0
- /package/{template → template-vite}/lib/editable-target.ts +0 -0
- /package/{template → template-vite}/lib/exxat-palette.json +0 -0
- /package/{template → template-vite}/lib/exxat-palette.ts +0 -0
- /package/{template → template-vite}/lib/floating-sheet-panel.ts +0 -0
- /package/{template → template-vite}/lib/full-hub-supported-views.ts +0 -0
- /package/{template → template-vite}/lib/hub-connected-view-renderers.ts +0 -0
- /package/{template → template-vite}/lib/initials-from-name.ts +0 -0
- /package/{template → template-vite}/lib/library-authoring.ts +0 -0
- /package/{template → template-vite}/lib/library-dedicated-search.ts +0 -0
- /package/{template → template-vite}/lib/library-hub-search.ts +0 -0
- /package/{template → template-vite}/lib/library-nav.ts +0 -0
- /package/{template → template-vite}/lib/library-recent-searches.ts +0 -0
- /package/{template → template-vite}/lib/library-supported-views.ts +0 -0
- /package/{template → template-vite}/lib/list-hub-supported-views.ts +0 -0
- /package/{template → template-vite}/lib/list-page-table-properties.ts +0 -0
- /package/{template → template-vite}/lib/list-status-badges.ts +0 -0
- /package/{template → template-vite}/lib/logo-dev.ts +0 -0
- /package/{template → template-vite}/lib/mailto.ts +0 -0
- /package/{template → template-vite}/lib/mock/dashboard.ts +0 -0
- /package/{template → template-vite}/lib/mock/library-folders.ts +0 -0
- /package/{template → template-vite}/lib/mock/library-header-collaborators.ts +0 -0
- /package/{template → template-vite}/lib/mock/library-inspector.ts +0 -0
- /package/{template → template-vite}/lib/mock/library-kpi.ts +0 -0
- /package/{template → template-vite}/lib/mock/library.ts +0 -0
- /package/{template → template-vite}/lib/mock/navigation.tsx +0 -0
- /package/{template → template-vite}/lib/motion-ui.ts +0 -0
- /package/{template → template-vite}/lib/product-brand.ts +0 -0
- /package/{template → template-vite}/lib/raf-throttle.ts +0 -0
- /package/{template → template-vite}/lib/row-height.ts +0 -0
- /package/{template → template-vite}/lib/sidebar-state-cookie.ts +0 -0
- /package/{template → template-vite}/lib/stock-portrait.ts +0 -0
- /package/{template → template-vite}/lib/table-state-lifecycle.ts +0 -0
- /package/{template → template-vite}/lib/utils.test.ts +0 -0
- /package/{template → template-vite}/lib/utils.ts +0 -0
- /package/{template → template-vite}/public/.gitkeep +0 -0
- /package/{template → template-vite}/public/Illustration/Rotation.svg +0 -0
- /package/{template → template-vite}/public/avatars/user.svg +0 -0
- /package/{template/public → template-vite/public/favicon}/favicon.ico +0 -0
- /package/{template/app → template-vite/public}/favicon.ico +0 -0
- /package/{template → template-vite}/public/folders/icons8-folder-windows-11.svg +0 -0
- /package/{template → template-vite}/public/logos/exxat-one.svg +0 -0
- /package/{template → template-vite}/public/logos/exxat-prism.svg +0 -0
- /package/{template → template-vite}/public/mock-schools/emory.svg +0 -0
- /package/{template → template-vite}/public/mock-schools/rush.svg +0 -0
- /package/{template → template-vite}/scripts/fontawesome-subset-audit.mjs +0 -0
- /package/{template → template-vite}/scripts/pm2-startup-macos.sh +0 -0
- /package/{template → template-vite}/skills-lock.json +0 -0
- /package/{template/app/(app)/columns/page.tsx → template-vite/src/pages/columns.tsx} +0 -0
- /package/{template/app/(app)/library/find/page.tsx → template-vite/src/pages/library/find.tsx} +0 -0
- /package/{template/app/(app)/library/page.tsx → template-vite/src/pages/library/index.tsx} +0 -0
- /package/{template/app/(app)/library/list/page.tsx → template-vite/src/pages/library/list.tsx} +0 -0
- /package/{template/app/(app)/settings/page.tsx → template-vite/src/pages/settings.tsx} +0 -0
- /package/{template/app/(app)/tokens-themes/page.tsx → template-vite/src/pages/tokens-themes.tsx} +0 -0
- /package/{template → template-vite}/stores/app-store.ts +0 -0
- /package/{template → template-vite}/types/react-payment-inputs.d.ts +0 -0
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
---
|
|
2
|
-
description: ListPageTemplate — shared table state across views, mock + KPI helpers, dashboard tab
|
|
3
|
-
|
|
2
|
+
description: ListPageTemplate — shared table state across views, mock + KPI helpers, dashboard tab. Auto-attaches when editing list-page React clients.
|
|
3
|
+
globs: apps/web/{components,lib,app}/**/*.{tsx,ts}
|
|
4
|
+
alwaysApply: false
|
|
5
|
+
appliesTo: [react]
|
|
4
6
|
---
|
|
5
7
|
|
|
6
8
|
# Exxat DS — list page connected views
|
|
@@ -16,9 +18,11 @@ alwaysApply: true
|
|
|
16
18
|
5. **List hub metrics strip** — Prefer **`KeyMetrics variant="flat"`** on **`ListPageTemplate`** **`metrics`** slot (transparent band, brand glow only) — **`docs/kpi-flat-band-pattern.md`**, **`.cursor/rules/exxat-kpi-flat-band.mdc`**.
|
|
17
19
|
6. **MUST NOT** ship “not wired” / “switch to table” placeholders for list/board/dashboard when the stack supports those views.
|
|
18
20
|
7. **MUST NOT** add a **primary nav** destination that is only placeholder copy with no **`ListPageTemplate`** hub, mock rows, and wired views — see **`apps/web/AGENTS.md` §4.1** (no empty hubs).
|
|
21
|
+
8. **Add view parity** — Use **`FULL_HUB_SUPPORTED_VIEWS`** (default) and implement **all seven** views with real bodies — **`.cursor/rules/exxat-hub-supported-views.mdc`**. List rows **MUST** use **`ListPageBoardCard`** (`library-table.tsx`), not bare title + id lines.
|
|
19
22
|
|
|
20
23
|
## See also
|
|
21
24
|
|
|
22
25
|
- **`.cursor/rules/exxat-centralized-list-dataset.mdc`** — single **`tableState.rows`** source for every hub view, inspectors, and **`TablePropertiesDrawer`** on the same **`DataTable`**.
|
|
23
26
|
- **Centered view bodies + reusable shells:** **`apps/web/AGENTS.md` §4.5**, **`.cursor/rules/exxat-list-page-view-shells.mdc`**, **`ListPageViewFrame`** in **`components/data-views/list-page-view-frame.tsx`**.
|
|
24
27
|
- **Flat KPI band:** **`docs/kpi-flat-band-pattern.md`**, **`.cursor/rules/exxat-kpi-flat-band.mdc`**.
|
|
28
|
+
- **Hub supported views:** **`docs/hub-supported-views-pattern.md`**, **`.cursor/rules/exxat-hub-supported-views.mdc`**.
|
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
description: Exxat DS — centered reusable shells for list-page views (not page-specific markup)
|
|
3
3
|
globs: apps/web/components/**/*.tsx
|
|
4
4
|
alwaysApply: false
|
|
5
|
+
appliesTo: [react]
|
|
5
6
|
---
|
|
6
7
|
|
|
7
8
|
# Exxat DS — list-page view shells (centered, reusable)
|
|
@@ -21,7 +22,7 @@ Domain logic (columns, tiles, folder trees) stays in **`*-table.tsx` / `*-client
|
|
|
21
22
|
## MUST NOT
|
|
22
23
|
|
|
23
24
|
- Wrap **`DataTable`** (or its outer toolbar shell) in **`ListPageViewFrame`** if that **duplicates** horizontal inset already applied by **`DataTable`** / **`DataTableToolbar`** — see **`AGENTS.md` §5** (double indent).
|
|
24
|
-
- Ship **view-only** layout classes only inside **`
|
|
25
|
+
- Ship **view-only** layout classes only inside **`src/views/<route>.tsx`** (or any route entry) for a hub that other entities will mirror — belong in **`data-views/`** or **`templates/`**.
|
|
25
26
|
|
|
26
27
|
## See also
|
|
27
28
|
|
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
description: Exxat DS — monospace typography for record IDs, question IDs, and other system identifiers
|
|
3
3
|
globs: apps/web/**/*.tsx
|
|
4
4
|
alwaysApply: false
|
|
5
|
+
appliesTo: [react]
|
|
5
6
|
---
|
|
6
7
|
|
|
7
8
|
# Exxat DS — monospace IDs
|
|
@@ -16,7 +17,7 @@ Use this when rendering **system identifiers** — values a user copies, searche
|
|
|
16
17
|
|
|
17
18
|
## SHOULD
|
|
18
19
|
|
|
19
|
-
- Match existing hubs: **`library-table.tsx`**, **`
|
|
20
|
+
- Match existing hubs: **`library-table.tsx`**, **`columns-showcase.tsx`** (mono record IDs in the showcase row), **`new-library-item-form.tsx`** (header subtitle).
|
|
20
21
|
- Prefer **`truncate`** / **`min-w-0`** on mono IDs in tight layouts so long tokens do not blow out columns.
|
|
21
22
|
|
|
22
23
|
## MUST NOT
|
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
description: Sidebar and secondary nav — exactly one active item per route (longest path match)
|
|
3
3
|
globs: "**/app-sidebar.tsx,**/secondary-nav.tsx,**/navigation.tsx,**/lib/nav-active.ts"
|
|
4
4
|
alwaysApply: false
|
|
5
|
+
appliesTo: [react]
|
|
5
6
|
---
|
|
6
7
|
|
|
7
8
|
# Exxat DS — single active nav item (MUST)
|
|
@@ -17,7 +18,7 @@ Only **one** primary sidebar row, collapsible child, or secondary-panel link may
|
|
|
17
18
|
2. **Never** mark a nav item active with bare `pathname === href` or `pathname.startsWith(href + "/")` when other nav targets share that prefix (e.g. `/dashboard` vs `/dashboard/students`).
|
|
18
19
|
3. **Hash disambiguation** — when multiple items share the same path (e.g. `/settings` vs `/settings#appearance`), use `buildNavHashClaims` so the no-fragment row defers to the hash-specific row.
|
|
19
20
|
4. **Collapsible parents** — when any child is active, the **parent** row stays visually neutral in the expanded sidebar; only the child gets `data-active` (icon rail may still highlight the parent — see `isCollapsibleParentMenuButtonActive` in `app-sidebar.tsx`).
|
|
20
|
-
5. **Keep `ListPageTemplate.supportedViewTypes` and `HubTable.supportedViewTypes` in sync** on the same hub —
|
|
21
|
+
5. **Keep `ListPageTemplate.supportedViewTypes` and `HubTable.supportedViewTypes` in sync** on the same hub — default **`FULL_HUB_SUPPORTED_VIEWS`** (seven views). See **`exxat-hub-supported-views.mdc`** for renderer requirements.
|
|
21
22
|
|
|
22
23
|
## MUST NOT
|
|
23
24
|
|
|
@@ -27,5 +28,5 @@ Only **one** primary sidebar row, collapsible child, or secondary-panel link may
|
|
|
27
28
|
## Reference
|
|
28
29
|
|
|
29
30
|
- `packages/ui/src/lib/nav-active.ts`
|
|
30
|
-
- `packages/ui/template/components/sidebar/app-sidebar.tsx`
|
|
31
|
-
- `packages/ui/template/components/sidebar/secondary-nav.tsx`
|
|
31
|
+
- `packages/ui/template-vite/components/sidebar/app-sidebar.tsx`
|
|
32
|
+
- `packages/ui/template-vite/components/sidebar/secondary-nav.tsx`
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
description: Uploaded screenshots/mockups are IA reference only — map to Exxat DS patterns; never pixel-copy
|
|
3
3
|
alwaysApply: true
|
|
4
|
+
appliesTo: [universal]
|
|
4
5
|
---
|
|
5
6
|
|
|
6
7
|
# Exxat DS — uploaded images are not the implementation spec
|
|
@@ -11,25 +12,35 @@ When the user attaches a **screenshot**, **mockup**, **Figma export**, **legacy
|
|
|
11
12
|
|
|
12
13
|
## Allowed to take from an image (content / IA)
|
|
13
14
|
|
|
14
|
-
- **Screen purpose
|
|
15
|
-
- **
|
|
16
|
-
- **
|
|
15
|
+
- **Screen purpose** — list hub, detail record, settings, search, etc.
|
|
16
|
+
- **Nav labels**, **section grouping**, **route slugs**, **field names**, **column headers**
|
|
17
|
+
- **Data the user cares about** — which KPIs, filters, actions, statuses exist
|
|
18
|
+
- **Icon choice** (Font Awesome suffix) when obvious — still use **`fa-light` / `fa-solid`** DS pairing
|
|
19
|
+
- **Workflow** — e.g. “export from ⋯”, “row opens profile”, “invite from header”
|
|
17
20
|
|
|
18
21
|
## MUST NOT copy from an image (visual / stack)
|
|
19
22
|
|
|
20
|
-
- **Hex / RGB colors**, rainbow
|
|
21
|
-
- **
|
|
22
|
-
- **Bespoke
|
|
23
|
-
- **
|
|
23
|
+
- **Hex / RGB colors**, per-section rainbow text, custom sidebar washes, one-off pill shapes
|
|
24
|
+
- **Layout chrome** that duplicates DS shell — sidebar, **`SiteHeader`**, **`PageHeader`**, **`ListPageTemplate`** toolbar, tab bars
|
|
25
|
+
- **Bespoke components** when a DS primitive exists — raw `<table>`, custom popovers, hand-built buttons, full-width tabs, Vaul drawers
|
|
26
|
+
- **Forking shared files** (`app-sidebar.tsx`, `sidebar.tsx`, `globals.css`) to match a legacy product
|
|
27
|
+
- **Implementing “because it’s in the picture”** without naming the **DS pattern + reference file** you are using
|
|
24
28
|
|
|
25
|
-
## REQUIRED workflow (before UI code)
|
|
29
|
+
## REQUIRED workflow (before writing UI code)
|
|
26
30
|
|
|
27
|
-
1. Classify
|
|
28
|
-
2. Pick **`reference-implementations`**
|
|
29
|
-
3. State mapping (
|
|
30
|
-
4.
|
|
31
|
-
5.
|
|
31
|
+
1. **Classify the screen** — use **`docs/component-selection-guide.md`** + **`docs/blueprints/`** (list page, page header, data table, dedicated search, …).
|
|
32
|
+
2. **Pick a reference hub** — **`docs/reference-implementations.md`** (Placements, Team, Library, Compliance, …).
|
|
33
|
+
3. **State the mapping** (briefly in your reply): e.g. “Students roster → **`ListPageTemplate`** + **`HubTable`** like Team; nav rows → **`lib/mock/navigation.tsx`** only; sidebar chrome unchanged.”
|
|
34
|
+
4. **Implement with DS components + tokens** — **`AGENTS.md`**, **`exxat-ds-agents.mdc`**, topic rules (`exxat-tabs-chrome`, `exxat-page-header-actions`, `exxat-sidebar-shell`, …).
|
|
35
|
+
5. **If the image conflicts with DS** — follow DS; ask **one** clarifying question only when the **business requirement** (not pixels) cannot be met with existing patterns.
|
|
36
|
+
|
|
37
|
+
## Consumer apps
|
|
38
|
+
|
|
39
|
+
- Product UI lives in the **customer repo** with **`@exxatdesignux/ui`** — not by restyling the DS monorepo to match uploads.
|
|
40
|
+
- After upgrade, run **`exxat-ui sync-extras`** so this rule and siblings stay on disk.
|
|
32
41
|
|
|
33
42
|
## See also
|
|
34
43
|
|
|
35
|
-
- **`exxat-reuse-before-custom.mdc
|
|
44
|
+
- **`exxat-reuse-before-custom.mdc`** — compose before inventing
|
|
45
|
+
- **`exxat-sidebar-shell.mdc`** — sidebar-specific anti-patterns
|
|
46
|
+
- **`exxat-token-economy`** skill §2 — pre-flight includes image discipline
|
|
@@ -1,3 +1,9 @@
|
|
|
1
|
+
---
|
|
2
|
+
description: No Salesforce SLDS leakage — never copy slds-* classes, lightning-* elements, SLDS token names, or synthetic-shadow assumptions into Exxat DS code.
|
|
3
|
+
alwaysApply: true
|
|
4
|
+
appliesTo: [universal]
|
|
5
|
+
---
|
|
6
|
+
|
|
1
7
|
# Exxat DS — no SLDS leakage
|
|
2
8
|
|
|
3
9
|
**Context:** Some agents have access to other repos, including the **Salesforce
|
|
@@ -23,7 +29,7 @@ codebase into **`apps/web`** or **`packages/ui`**.
|
|
|
23
29
|
Exxat compositions in `apps/web/components/`.
|
|
24
30
|
3. **Synthetic-shadow assumptions** — Do **not** call `template.querySelector`,
|
|
25
31
|
`slds-color-scheme_dark`, `shadowRoot === null` checks, or anything that
|
|
26
|
-
only makes sense under Salesforce synthetic shadow. The
|
|
32
|
+
only makes sense under Salesforce synthetic shadow. The Vite + React app uses
|
|
27
33
|
the real DOM + Radix portals.
|
|
28
34
|
4. **SLDS styling-hook vars** — Do **not** use SLDS custom properties
|
|
29
35
|
(`--slds-g-color-surface-*`, `--slds-g-color-on-surface-*`,
|
|
@@ -67,7 +73,7 @@ silently breaks:
|
|
|
67
73
|
- **Accessibility** — SLDS 1 contrast ratios differ from Exxat's WCAG 2.1 AA
|
|
68
74
|
targets; mixing them produces unverifiable composites.
|
|
69
75
|
- **Bundling** — Importing `@salesforce-ux/design-system` would balloon the
|
|
70
|
-
|
|
76
|
+
Vite bundle and pull in classic SLDS that we explicitly chose not to use.
|
|
71
77
|
|
|
72
78
|
## See also
|
|
73
79
|
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
description: Exxat DS — no Vaul Drawer primitive; side panels use Sheet only
|
|
3
3
|
alwaysApply: true
|
|
4
|
+
appliesTo: [universal]
|
|
4
5
|
---
|
|
5
6
|
|
|
6
7
|
# Exxat DS — no Vaul
|
|
@@ -22,4 +23,4 @@ After upgrading to **`@exxatdesignux/ui@0.5.3`**, remove **`vaul`** from the app
|
|
|
22
23
|
## See also
|
|
23
24
|
|
|
24
25
|
- **`.cursor/rules/exxat-drawer-vs-dialog.mdc`**
|
|
25
|
-
- **`
|
|
26
|
+
- **`apps/web/docs/drawer-vs-dialog-pattern.md`**
|
|
@@ -1,11 +1,13 @@
|
|
|
1
1
|
---
|
|
2
|
-
description: Exxat DS — PageHeader actions slot; View as / overflow / primary CTA patterns
|
|
3
|
-
|
|
2
|
+
description: Exxat DS — PageHeader actions slot; View as / overflow / primary CTA patterns. Auto-attaches when editing React PageHeader callsites; the universal "one filled primary" rule lives in P3 of exxat-ux-principles.
|
|
3
|
+
globs: apps/web/{components,app}/**/*.{tsx,ts}
|
|
4
|
+
alwaysApply: false
|
|
5
|
+
appliesTo: [react]
|
|
4
6
|
---
|
|
5
7
|
|
|
6
8
|
# Exxat DS — page header actions
|
|
7
9
|
|
|
8
|
-
**Blueprint:** `
|
|
10
|
+
**Blueprint:** `apps/web/docs/blueprints/page-header.md`
|
|
9
11
|
|
|
10
12
|
## Anatomy (actions slot only)
|
|
11
13
|
|
|
@@ -28,4 +30,4 @@ alwaysApply: true
|
|
|
28
30
|
|
|
29
31
|
## Reference
|
|
30
32
|
|
|
31
|
-
-
|
|
33
|
+
- `components/library-page-header.tsx`, Placements/Team header patterns in **`apps/web/docs/reference-implementations.md`**
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
description: Exxat DS — when to use a drawer vs a new page for actions and auxiliary UI.
|
|
3
3
|
alwaysApply: true
|
|
4
|
+
appliesTo: [universal]
|
|
4
5
|
---
|
|
5
6
|
|
|
6
7
|
# Exxat DS — page vs drawer
|
|
@@ -14,7 +15,7 @@ alwaysApply: true
|
|
|
14
15
|
## Product examples (this repo)
|
|
15
16
|
|
|
16
17
|
- **Drawer-appropriate:** `TablePropertiesDrawer`, `ExportDrawer`, lightweight panels that supplement a hub.
|
|
17
|
-
- **Page-appropriate:** Full
|
|
18
|
+
- **Page-appropriate:** Full settings flows, multi-step record-creation wizards (e.g. `new-library-item-form.tsx`), or any task that is itself the user's primary intent.
|
|
18
19
|
|
|
19
20
|
## Authoritative detail
|
|
20
21
|
|
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
description: Primary sidebar item opens nested SecondaryPanel (Library pattern)
|
|
3
3
|
globs: apps/web/components/**/*.tsx
|
|
4
4
|
alwaysApply: false
|
|
5
|
+
appliesTo: [react]
|
|
5
6
|
---
|
|
6
7
|
|
|
7
8
|
# Exxat DS — primary nav → secondary panel
|
|
@@ -15,7 +16,7 @@ Some hubs expose **scoped navigation** (All / My / tree / filters) in a **nested
|
|
|
15
16
|
1. **`NavLinkItem`** — On the **primary** row that should drive the panel, set **`secondaryPanel`** to a **stable string id** (e.g. **`"library"`**). Keep **`url`** pointing at the **hub route**.
|
|
16
17
|
2. **`SecondaryPanel` registry** — In **`components/secondary-panel.tsx`**, add **`PANELS[id]`** → component that renders **panel chrome** (title, optional search) + **your secondary nav** list. **MUST** keep ids in sync with **`NAV_PRIMARY`**.
|
|
17
18
|
3. **Auto-open on route** — The hub **`client`** (or layout slot) **MUST** mount **`*PanelActivator`** that calls **`useAutoPanel(id)`** with the **same id**, so deep links and first visit open the panel while the route is mounted (e.g. **`LibraryPanelActivator`** + **`beforeSiteHeader`** on **`LibraryClient`**).
|
|
18
|
-
4. **Same-route reopen** — **`AppSidebar`** already calls **`openPanel(secondaryPanel)`** when the user clicks the primary item **again** while already on that **`url`** (prevents no-op navigation). Secondary nav rows that stay on the same path **SHOULD** call **`openPanel`** on click where
|
|
19
|
+
4. **Same-route reopen** — **`AppSidebar`** already calls **`openPanel(secondaryPanel)`** when the user clicks the primary item **again** while already on that **`url`** (prevents no-op navigation). Secondary nav rows that stay on the same path **SHOULD** call **`openPanel`** on click where **`react-router-dom` `Link`** would not fire (same **`to`**).
|
|
19
20
|
|
|
20
21
|
## Surface elevation (brand chrome)
|
|
21
22
|
|
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
description: Application sidebar — DS shell only; legacy screenshots are IA reference, not visual spec
|
|
3
3
|
globs: "**/app-sidebar.tsx,**/navigation*.tsx,**/lib/mock/navigation.tsx,**/lib/*-navigation.tsx"
|
|
4
4
|
alwaysApply: false
|
|
5
|
+
appliesTo: [react]
|
|
5
6
|
---
|
|
6
7
|
|
|
7
8
|
# Exxat DS — application sidebar shell (MUST)
|
|
@@ -23,13 +24,18 @@ Customer / legacy app **screenshots** may show **what links exist** — not **ho
|
|
|
23
24
|
|
|
24
25
|
## MUST — DS sidebar chrome
|
|
25
26
|
|
|
26
|
-
1. **Shell:** **`AppSidebar`** + **`SidebarMenuButton`** / **`SidebarGroup`** / **`SidebarGroupLabel`** from **`@exxatdesignux/ui
|
|
27
|
-
2. **Typography:** Row labels **`text-sidebar-foreground
|
|
28
|
-
3. **Active state:** **`
|
|
29
|
-
4. **Icons:** **`fa-light`** / **`fa-solid`** on
|
|
30
|
-
5. **Nav data:**
|
|
31
|
-
6. **Consumer products:**
|
|
27
|
+
1. **Shell:** **`AppSidebar`** + **`SidebarMenuButton`** / **`SidebarGroup`** / **`SidebarGroupLabel`** from **`@exxatdesignux/ui`** (or app shims). Reference: **`apps/web/components/sidebar/app-sidebar.tsx`**, **`AGENTS.md` §9.1**, **`exxat-ds-skill` §3.1–§3.2**.
|
|
28
|
+
2. **Typography:** Row labels **`text-sidebar-foreground`** (default from `SidebarMenuButton`). Section headings **`SidebarGroupLabel`** + **`text-sidebar-section-label`** — not rainbow section body text.
|
|
29
|
+
3. **Active state:** Pass **`isActive`** into **`SidebarMenuButton`** only. Expanded rail: **one** active row (`data-active` → background pill + ring from DS). Collapsible parent stays **neutral** when a child is active. Icon rail: parent icon may light up when any child is active.
|
|
30
|
+
4. **Icons:** **`fa-light`** idle / **`fa-solid`** active on the **icon** only — do **not** recolor the label per module.
|
|
31
|
+
5. **Nav data:** Add or extend **`lib/mock/navigation.tsx`** (or a file it imports). **MUST NOT** paste a full legacy sidebar component from a customer repo into **`apps/web`**.
|
|
32
|
+
6. **Consumer products:** Prism / customer hubs belong in a **separate consumer repo** with **`@exxatdesignux/ui`** — not product-specific rewrites of the DS monorepo sidebar.
|
|
33
|
+
|
|
34
|
+
## Reference (canonical visual)
|
|
35
|
+
|
|
36
|
+
- **`apps/web/components/sidebar/app-sidebar.tsx`** + **`lib/mock/navigation.tsx`**
|
|
37
|
+
- **`packages/ui/src/components/ui/sidebar.tsx`** — `data-active:bg-background` pill
|
|
32
38
|
|
|
33
39
|
## Anti-pattern
|
|
34
40
|
|
|
35
|
-
Legacy
|
|
41
|
+
Legacy Exxat Prism sidebar: color-coded **text** per module block, pink sidebar wash, bespoke selection chrome — **do not reproduce** when building on Exxat DS.
|
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
---
|
|
2
|
-
description: TablePropertiesDrawer must receive currentView and onViewChange when used with ListPageTemplate view tabs
|
|
3
|
-
|
|
2
|
+
description: TablePropertiesDrawer must receive currentView and onViewChange when used with ListPageTemplate view tabs. Auto-attaches when editing apps/web React files; ask explicitly when wiring view-type-aware drawers.
|
|
3
|
+
globs: apps/web/{components,packages/ui}/**/*.{tsx,ts}
|
|
4
|
+
alwaysApply: false
|
|
5
|
+
appliesTo: [react]
|
|
4
6
|
---
|
|
5
7
|
|
|
6
8
|
# Exxat DS — Table properties + active view
|
|
@@ -28,7 +30,7 @@ When **`ListPageTemplate`** drives **`tab.viewType`** and the page renders **`Ta
|
|
|
28
30
|
|
|
29
31
|
3. Thread **`view`** and **`onViewChange`** through: **client → table component → drawer toolbar → `TablePropertiesDrawer`**.
|
|
30
32
|
|
|
31
|
-
**Reference implementations:** `components/
|
|
33
|
+
**Reference implementations:** `components/library-hub-client.tsx` + `library-table.tsx` (canonical seven-view hub), `components/columns-showcase.tsx` (`LibraryTable` + custom `columnDefs`), `components/tokens-themes-client.tsx` (`FULL_HUB_SUPPORTED_VIEWS` + `tokens-hub-auxiliary-views.tsx`). **Add view allowlist:** **`.cursor/rules/exxat-hub-supported-views.mdc`**.
|
|
32
34
|
|
|
33
35
|
## Deep-linking into a specific panel
|
|
34
36
|
|
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
---
|
|
2
|
-
description: Exxat DS — Tabs and view toolbars must not stretch full width; use ListPageTemplate for hub views
|
|
3
|
-
|
|
2
|
+
description: Exxat DS — Tabs and view toolbars must not stretch full width; use ListPageTemplate for hub views. Auto-attaches when editing React surfaces with tabs or view toolbars.
|
|
3
|
+
globs: apps/web/{components,app}/**/*.{tsx,ts}
|
|
4
|
+
alwaysApply: false
|
|
5
|
+
appliesTo: [react]
|
|
4
6
|
---
|
|
5
7
|
|
|
6
8
|
# Exxat DS — tabs chrome (no full-width stretch)
|
|
@@ -27,5 +29,5 @@ alwaysApply: true
|
|
|
27
29
|
|
|
28
30
|
## See also
|
|
29
31
|
|
|
30
|
-
- **`docs/
|
|
31
|
-
- **`
|
|
32
|
+
- **`apps/web/docs/blueprints/page-header.md`** — header never carries view tabs
|
|
33
|
+
- **`apps/web/docs/data-views-pattern.md`** — `ListPageTemplate` view toolbar
|
|
@@ -1,3 +1,9 @@
|
|
|
1
|
+
---
|
|
2
|
+
description: Token discipline — no hex literals, prefer Exxat L0 tokens (--exxat-color-*, --exxat-radius-*, --exxat-spacing-*), no deprecated tokens. ESLint enforces via @exxatdesignux/eslint-plugin.
|
|
3
|
+
alwaysApply: true
|
|
4
|
+
appliesTo: [universal]
|
|
5
|
+
---
|
|
6
|
+
|
|
1
7
|
# Exxat DS — token discipline
|
|
2
8
|
|
|
3
9
|
**Authoritative reference:** [`apps/web/docs/token-taxonomy.md`](mdc:apps/web/docs/token-taxonomy.md).
|
|
@@ -1,25 +1,73 @@
|
|
|
1
1
|
---
|
|
2
|
-
description: Exxat DS —
|
|
2
|
+
description: Exxat DS — STOP before code on any surface design (new, rebuild, redesign, replace); output a design brief and WAIT for user go-ahead
|
|
3
3
|
alwaysApply: true
|
|
4
|
+
appliesTo: [universal]
|
|
4
5
|
---
|
|
5
6
|
|
|
6
7
|
# Exxat DS — UX discovery protocol
|
|
7
8
|
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
9
|
+
## STOP — read before you write any file
|
|
10
|
+
|
|
11
|
+
If the user's prompt asks you to **design, create, build, rebuild, redesign,
|
|
12
|
+
replace, redo, refresh, modernize, re-imagine, or "make a new version of"**
|
|
13
|
+
any **page, route, screen, hub, detail view, wizard, settings section,
|
|
14
|
+
dashboard, dialog, sheet, drawer, panel, layout, or significant component**:
|
|
15
|
+
|
|
16
|
+
1. **Do NOT write code, do NOT edit files, do NOT call edit tools yet.**
|
|
17
|
+
2. **Output the design brief** (template below) in chat.
|
|
18
|
+
3. **Wait for the user to reply** with `yes` / `proceed` / `ship it` / edits.
|
|
19
|
+
4. **Only then** move to implementation.
|
|
20
|
+
|
|
21
|
+
If your next tool call would be `write_file`, `str_replace`, `create_file`,
|
|
22
|
+
or any code-mutating action **and** you have not posted a brief and received
|
|
23
|
+
go-ahead, you are violating this rule. **Stop and post the brief.**
|
|
24
|
+
|
|
25
|
+
## When this gate fires (and when it doesn't)
|
|
26
|
+
|
|
27
|
+
This gate fires on **any task that decides what a surface should look like
|
|
28
|
+
or how it works** — whether the surface exists today or not. Treat
|
|
29
|
+
"replace what we have" and "create from scratch" identically — both need a
|
|
30
|
+
brief, because both make a design decision.
|
|
31
|
+
|
|
32
|
+
**Fires (brief required):**
|
|
33
|
+
|
|
34
|
+
- "Create a new student detail page."
|
|
35
|
+
- "Rebuild the dashboard."
|
|
36
|
+
- "Redesign the settings screen instead of what we have."
|
|
37
|
+
- "Make a new version of the placements table."
|
|
38
|
+
- "Replace the current onboarding flow."
|
|
39
|
+
- "Build a wizard for adding a site."
|
|
40
|
+
- "Design a sheet for inviting collaborators."
|
|
41
|
+
- User attaches a screenshot / mockup / Figma link and asks to "build this".
|
|
42
|
+
|
|
43
|
+
**Does NOT fire (brief not required, edit freely):**
|
|
44
|
+
|
|
45
|
+
- Single-class restyle of an existing surface that already follows DS rules.
|
|
46
|
+
- Copy / label edits.
|
|
47
|
+
- Bug fixes (a11y violation, broken state, wrong data).
|
|
48
|
+
- Dependency bumps, ESLint passes, type fixes, test-only changes.
|
|
49
|
+
- Adding a new column / filter to an *existing* `HubTable` that doesn't
|
|
50
|
+
change the page's IA.
|
|
51
|
+
|
|
52
|
+
When in doubt, ask: **"Am I deciding what this surface should be?"** Yes →
|
|
53
|
+
brief. No → edit.
|
|
12
54
|
|
|
13
55
|
## MUST
|
|
14
56
|
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
57
|
+
0. **Output the brief, then WAIT.** The brief is a checkpoint, not a
|
|
58
|
+
preamble. Do not bundle the brief and the first file edit in the same
|
|
59
|
+
turn. After posting the brief, end your turn with an explicit
|
|
60
|
+
"Ready to build — confirm or edit." prompt. Resume only on the user's
|
|
61
|
+
next message.
|
|
62
|
+
1. **No code without a confirmed brief.** "Confirmed" means the user wrote
|
|
63
|
+
`yes`, `proceed`, `ship it`, `LGTM`, `build it`, accepted edits, or asked
|
|
64
|
+
a follow-up that implies acceptance. Silence is not consent.
|
|
18
65
|
2. **Cite a reference.** Every brief names **one repo reference** + **two
|
|
19
|
-
modern SaaS analogues** (Linear / Notion / Stripe / Figma / Vercel /
|
|
20
|
-
|
|
21
|
-
product name + pattern
|
|
22
|
-
`apps/web/docs/modern-saas-patterns.md` (e.g.
|
|
66
|
+
modern SaaS analogues** (Linear / Notion / Stripe / Figma / Vercel /
|
|
67
|
+
Linear / Airtable / Coda / Height / etc.) that solve the same
|
|
68
|
+
**job-to-be-done**. Cite the SaaS analogues by product name + pattern
|
|
69
|
+
codes from `apps/web/docs/modern-saas-patterns.md` (e.g.
|
|
70
|
+
`Linear issue detail (M1, M4, M7)`).
|
|
23
71
|
3. **Name principles + breaks.** Brief lists the principles applied
|
|
24
72
|
(`exxat-ux-principles.mdc`) and any deviations with one-sentence reasons.
|
|
25
73
|
**Never-break** principles (P1–P8) cannot be deviated from.
|
|
@@ -30,6 +78,11 @@ BEFORE writing files. Brief format is defined in
|
|
|
30
78
|
|
|
31
79
|
## MUST NOT
|
|
32
80
|
|
|
81
|
+
- **Skip the brief because the prompt sounds like a refactor.** "Rebuild",
|
|
82
|
+
"redesign", "replace", "instead of what we have", and "from scratch" are
|
|
83
|
+
design decisions, not refactors. Brief required.
|
|
84
|
+
- **Post a brief and then write 8 files in the same turn.** That's not a
|
|
85
|
+
brief — that's a press release. End the turn after the brief.
|
|
33
86
|
- Generate files before the brief.
|
|
34
87
|
- Ask more than **3** questions in one batch.
|
|
35
88
|
- Ask questions whose answer is already in the prompt, the file tree, or
|
|
@@ -113,6 +166,32 @@ Open questions: <max 2; ideally 0>
|
|
|
113
166
|
> User: "make a settings page". *Agent writes generic form.* Should have
|
|
114
167
|
> asked: scope (personal/workspace), search needed, apply-on-change vs Save.
|
|
115
168
|
|
|
169
|
+
## Closing artifact: the design → engineering handoff
|
|
170
|
+
|
|
171
|
+
When the build is complete (files written, surface working in dev), produce
|
|
172
|
+
**one filled-in handoff document** before declaring the task done.
|
|
173
|
+
|
|
174
|
+
**Template** lives at:
|
|
175
|
+
|
|
176
|
+
- Workspace: `apps/web/docs/templates/handoff.md` (or workspace root if not yet copied — copy from `packages/ui/consumer-extras/templates/handoff.md`)
|
|
177
|
+
- Consumer apps (after `exxat-ui sync-extras`): `docs/exxat-ds/templates/handoff.md`
|
|
178
|
+
|
|
179
|
+
**Fill it in** with the actual primitives, tokens, icons, and shortcuts the
|
|
180
|
+
build used. Save the filled copy at:
|
|
181
|
+
|
|
182
|
+
- `apps/web/docs/handoff/<surface-slug>.md` (workspace)
|
|
183
|
+
- `docs/exxat-ds/handoff/<surface-slug>.md` (consumer)
|
|
184
|
+
|
|
185
|
+
Attach the filled handoff to the PR description (or paste inline). The
|
|
186
|
+
engineer reads it once, runs `exxat-ui audit <generated-file>` to verify
|
|
187
|
+
the floor, and is done.
|
|
188
|
+
|
|
189
|
+
**MUST sections:** 1 (job-to-be-done), 3 (pattern + IA), 5 (DS components
|
|
190
|
+
used), 6 (tokens), 8 (a11y checklist — every box ticked), 11 (keyboard map),
|
|
191
|
+
12 (any deviations from P9–P20).
|
|
192
|
+
|
|
193
|
+
If the handoff is incomplete or hand-wavy, the design task is not finished.
|
|
194
|
+
|
|
116
195
|
## See also
|
|
117
196
|
|
|
118
197
|
- `.cursor/skills/exxat-senior-ux/SKILL.md` — the persona + full protocol
|
|
@@ -120,3 +199,4 @@ Open questions: <max 2; ideally 0>
|
|
|
120
199
|
- `apps/web/docs/jobs/` — canonical references per job type
|
|
121
200
|
- `apps/web/docs/modern-saas-patterns.md` — pattern codes (M1–M12)
|
|
122
201
|
- `.cursor/rules/exxat-no-image-pixel-copy.mdc` — IA from screenshots only
|
|
202
|
+
- **Closing artifact:** `packages/ui/consumer-extras/templates/handoff.md`
|
|
@@ -23,7 +23,7 @@ description: >
|
|
|
23
23
|
- **Single source of truth:** `apps/web/AGENTS.md` for full prose explanations; this skill is the actionable summary
|
|
24
24
|
- **Companion skills (narrow topics):** `exxat-fontawesome-icons`, `exxat-mono-ids`, `exxat-primary-nav-secondary-panel`, `exxat-centralized-list-dataset`, `exxat-list-page-view-shells`, `exxat-dedicated-search-surfaces`, `exxat-accessibility`, `exxat-board-cards`, `exxat-collaboration-access` — live under `.cursor/skills/`; vetted copies ship with **`@exxatdesignux/ui`** in `consumer-extras/cursor-skills/` after **`pnpm --filter @exxatdesignux/ui vendor:consumer-extras`**.
|
|
25
25
|
- **Library folder-scoped header (rule + doc):** **`.cursor/rules/exxat-library-hub-header.mdc`** and **`docs/library-hub-header-pattern.md`** — pair with **`exxat-primary-nav-secondary-panel`** when URL **`scope=folder`** drives the hub title.
|
|
26
|
-
- **Consumer repos (npm install of `@exxatdesignux/ui`):** After a version bump, read **`node_modules/@exxatdesignux/ui/CHANGELOG.md`**, run **`npx --package=@exxatdesignux/ui@latest exxat-ui sync-extras`** so **`docs/exxat-ds/consumer-upgrade-checklist.md`** and Cursor skills match the tarball, and diff the host app against **`node_modules/@exxatdesignux/ui/template/`** for anything new to port (routes, re-exports, AGENTS). Use **`exxat-ui changelog`**, **`exxat-ui update`**, and **`exxat-ui doctor`** for CLI guidance.
|
|
26
|
+
- **Consumer repos (npm install of `@exxatdesignux/ui`):** After a version bump, read **`node_modules/@exxatdesignux/ui/CHANGELOG.md`**, run **`npx --package=@exxatdesignux/ui@latest exxat-ui sync-extras`** so **`docs/exxat-ds/consumer-upgrade-checklist.md`** and Cursor skills match the tarball, and diff the host app against **`node_modules/@exxatdesignux/ui/template-vite/`** for anything new to port (routes, re-exports, AGENTS). Use **`exxat-ui changelog`**, **`exxat-ui update`**, and **`exxat-ui doctor`** for CLI guidance.
|
|
27
27
|
|
|
28
28
|
---
|
|
29
29
|
|
|
@@ -12,9 +12,11 @@ Use when adding or reviewing **`KeyMetrics`**, **`lib/mock/*-kpi.ts`** helpers,
|
|
|
12
12
|
|
|
13
13
|
1. **Delta honest?** `trend` follows the sign of the change vs the comparison period.
|
|
14
14
|
2. **Polarity correct?** If “more” is bad → **`trendPolarity: "lower_is_better"`**. If no value judgment → **`"informational"`** (muted tints).
|
|
15
|
-
3. **
|
|
16
|
-
4. **
|
|
17
|
-
5. **
|
|
15
|
+
3. **Delta is a count, not prose.** **`delta`** is `"+5"`, `"-3"`, `"+12%"`. Captions like `"left + right"`, `"vs last week"`, `"scheduled for removal"` go in **`description`** (renders **below** the value, muted).
|
|
16
|
+
4. **No empty `—` chip.** If there’s no direction *and* no count, leave **`delta: ""`** + **`trend: "neutral"`** — **`KeyMetrics`** hides the chip. Don’t hand-roll a placeholder.
|
|
17
|
+
5. **Copy contextual?** Label + value + (delta when present) + description tell users *what* moved, not only *how much*.
|
|
18
|
+
6. **Screen readers** — Chip keeps icon + visible delta; `aria-label` reflects favorable / unfavorable wording automatically when polarity is set.
|
|
19
|
+
7. **Chart cards** — When using **`ChartCard`** `miniMetrics`, pass **`trendPolarity`** the same way as on **`MetricItem`**.
|
|
18
20
|
|
|
19
21
|
## Quick examples
|
|
20
22
|
|