@exxatdesignux/ui 0.5.11 → 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 +26 -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 +1 -0
- 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 +28 -0
- 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/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/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
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,31 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 0.5.12
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- **The legacy `template/` (Next.js scaffold) is retired and no longer ships in the npm tarball.** It was already unreachable from the CLI as of 0.5.11 (`create-exxat-app` scaffolds from `template-vite/` only) and was being half-regenerated from the now-Vite `apps/web/` at publish time, leaving consumers with a Next.js eslint config layered over a Vite source tree. Three concrete changes in this release:
|
|
8
|
+
- **`packages/ui/package.json` `files`** drops `template` — `template-vite` is the only scaffold shipped.
|
|
9
|
+
- **CLI help (`exxat-ui update`)** points at `node_modules/@exxatdesignux/ui/template-vite/` when it suggests "compare your app with the reference template".
|
|
10
|
+
- **Workspace rules and skills** (`exxat-nav-single-active.mdc`, `exxat-library-hub-header.mdc`, `exxat-ds-skill`) point at `template-vite/` paths instead of `template/`. `consumer-extras/` regenerates from those sources.
|
|
11
|
+
- The `sync-template-from-web.mjs` script and the workflow step that runs it are kept (now a no-op for the published tarball) so the build pipeline continues to typecheck/lint a known-shaped reference, and so the next migration off it is a small follow-up rather than a workflow edit. Consumers see no regression — `exxat-ui sync-extras` continues to be the supported channel for rules + skills + patterns.
|
|
12
|
+
- **The reference app (`apps/web`) is now Vite + React + react-router-dom — Next.js fully removed.** A six-PR program (May 2026) cut steady-state dev memory from **1.4–4 GB RSS per `next-server`** down to **~250–500 MB per `vite`**, and cold start from 8–12 s to **~150–300 ms**. Designers running long sessions and customers comparing two branches side-by-side were the practical reason; the stack swap is what made it possible. Three layers of the published package change because of this.
|
|
13
|
+
- **`scripts/dev-guard.mjs`** is now Vite-only. The detector that previously listed running `next-server` parents was carrying dead code branches after PR-6; it now matches `vite` processes only and the warning copy is rewritten ("Two parallel Vite servers stabilize at ~500–800 MB combined and confuse HMR"). Customer apps that wired `predev: exxat-ui dev-guard` keep working unchanged — the guard simply reflects the new stack.
|
|
14
|
+
- **`bin/init.mjs`** drops `--stack=vite|next`. There is one starter now and it is `template-vite/` — Vite 6 + React 19 + react-router-dom + Tailwind v4 + TypeScript. The CLI's `--help` text and on-screen messages were rewritten to match. Customers that need a Next.js scaffold can copy `template-vite/` and bring their own `next.config.mjs` — the components, tokens, and rules are all stack-agnostic.
|
|
15
|
+
- **`bin/cli.mjs`** help text is updated: `dev-guard` reads "Detect concurrent Vite dev servers" instead of "Next.js + Vite", and `audit` audits a "React component / route" rather than a "Next.js component / route".
|
|
16
|
+
- **Consumer-extras and patterns refreshed for the Vite stack.** Every `npx exxat-ui sync-extras` payload that mentioned Next now reads as it does in the workspace today:
|
|
17
|
+
- **`patterns/perf-memory-pattern.md`** rewritten end-to-end. It used to be Next + Turbopack tuning ("`NODE_OPTIONS=--max-old-space-size=6144`", "Turbopack mmap'd FS cache", `pnpm clean:cache` for `.next/dev/cache`). It is now a Vite + Node 24 doc — the four knobs that matter (`dev-guard`, `optimizeDeps.include`, `optimizeDeps.exclude` for the workspace package, `resolve.dedupe` for React), how to bust `node_modules/.vite/`, and how to diagnose RSS climbing past 1 GB. A short "History" callout still explains where the 8× memory drop came from for anyone reading the migration in context.
|
|
18
|
+
- **`patterns/consumer-upgrade-checklist.md`** §3 now points at `node_modules/@exxatdesignux/ui/template-vite/` (was `template/`) and adds a "Migrating an existing Next.js consumer to Vite?" pointer for customers ready to follow the same path the reference app took.
|
|
19
|
+
- **`cursor-rules/exxat-no-slds-leakage.mdc`**, **`cursor-rules/exxat-primary-nav-secondary-panel.mdc`**, **`cursor-rules/exxat-list-page-view-shells.mdc`**, **`cursor-rules/exxat-command-menu.mdc`**, **`apps/web/.cursor/rules/exxat-dashboard-view-charts.mdc`** updated: where they cited `app/(app)/...` paths and `Next.js bundle` / `next/Link` / `Next.js app`, they now cite `src/views/...`, `src/App.tsx`, `Vite bundle`, and `react-router-dom Link`. Pure documentation — no rule logic changed, no globs broadened.
|
|
20
|
+
- **`consumer-extras/README.md`** drops the `--stack=next` example and rewords the `dev-guard` description to be Vite-only.
|
|
21
|
+
- **Designer landing page (`DESIGNER_LANDING.html`) refreshed.** The hero hint, "Starting fresh" / "Already coding" paths, and the *Sixty seconds* §ii ("Teach Next to transpile" → "No bundler config needed") all match the new stack. The "Layout that speaks Arabic." highlight card was removed — the DS doesn't yet ship logical-property layout end-to-end and the claim overstated 0.5.3.
|
|
22
|
+
- **Why this is a `0.5.x` patch and not a major bump:** the **runtime API** of `@exxatdesignux/ui` did not change. Every component, hook, token, and CSS export has the same shape it had in 0.5.11. What changed is which sample stack the published `template-vite/` runs, what `dev-guard` looks for in `ps`, and what the bundled rules / patterns / handbook say about the reference app. Customer apps that already install the package keep working with no code changes; running `exxat-ui sync-extras` after the upgrade refreshes the docs and rules in place.
|
|
23
|
+
- **Customer migration steps** (only if you want the new dev-experience pattern):
|
|
24
|
+
1. **`pnpm add @exxatdesignux/ui@0.5.12`** in your app.
|
|
25
|
+
2. **`npx --package=@exxatdesignux/ui@latest exxat-ui sync-extras`** to pull the refreshed rules + patterns.
|
|
26
|
+
3. If you ran a *Next.js* app and want to migrate to Vite, follow the new §7 "Upgrading an existing customer app to the Vite stack" in `perf-memory-pattern.md` (the same six-step program the reference app followed; the codemod for `next/*` → `react-router-dom` lives in commit `d16ec77` of this repo if you need a starting point).
|
|
27
|
+
4. If you stay on Next.js, no action required — the package supports any React app via `transpilePackages: ["@exxatdesignux/ui"]`.
|
|
28
|
+
|
|
3
29
|
## 0.5.11
|
|
4
30
|
|
|
5
31
|
### Patch Changes
|
package/bin/cli.mjs
CHANGED
|
@@ -33,6 +33,65 @@ function runSyncExtras() {
|
|
|
33
33
|
})
|
|
34
34
|
}
|
|
35
35
|
|
|
36
|
+
function runDevGuard(extraArgs) {
|
|
37
|
+
const script = resolve(__dirname, "../consumer-extras/scripts/dev-guard.mjs")
|
|
38
|
+
if (!existsSync(script)) {
|
|
39
|
+
// Old install — pass through silently so predev hooks never break a build.
|
|
40
|
+
process.exit(0)
|
|
41
|
+
}
|
|
42
|
+
try {
|
|
43
|
+
execFileSync(process.execPath, [script, ...extraArgs], {
|
|
44
|
+
stdio: "inherit",
|
|
45
|
+
cwd: process.cwd(),
|
|
46
|
+
})
|
|
47
|
+
} catch (err) {
|
|
48
|
+
process.exit(err?.status ?? 1)
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
/**
|
|
53
|
+
* `exxat-ui audit <file>` — engineer-facing quality gate.
|
|
54
|
+
*
|
|
55
|
+
* The full audit logic lives in the `exxat-ux-audit` skill (consumed by
|
|
56
|
+
* Cursor / Claude). This subcommand is a *stub* that prints the right
|
|
57
|
+
* invocation for both clients and exits. It is *not* a standalone linter —
|
|
58
|
+
* a full machine audit lives behind the agent so the rules stay in one
|
|
59
|
+
* place (the skill) instead of being duplicated in JS.
|
|
60
|
+
*/
|
|
61
|
+
function runAudit(args) {
|
|
62
|
+
const target = args[0]
|
|
63
|
+
if (!target) {
|
|
64
|
+
console.error("Usage: exxat-ui audit <file-or-route>\n")
|
|
65
|
+
console.error("Audits a React component / route against the Exxat DS")
|
|
66
|
+
console.error("rules + UX principles (P1–P20) + modern SaaS patterns (M1–M12).\n")
|
|
67
|
+
console.error("This stub prints the agent prompt to run; the actual audit is")
|
|
68
|
+
console.error("performed by the `exxat-ux-audit` skill in your agent client.")
|
|
69
|
+
process.exitCode = 1
|
|
70
|
+
return
|
|
71
|
+
}
|
|
72
|
+
console.log(`
|
|
73
|
+
Audit target: ${target}
|
|
74
|
+
|
|
75
|
+
Run inside Cursor or Claude Code:
|
|
76
|
+
|
|
77
|
+
/skill exxat-ux-audit
|
|
78
|
+
audit ${target}
|
|
79
|
+
|
|
80
|
+
The skill loads:
|
|
81
|
+
• .cursor/rules/exxat-accessibility.mdc (a11y floor)
|
|
82
|
+
• .cursor/rules/exxat-ux-principles.mdc (P1–P20)
|
|
83
|
+
• .cursor/rules/exxat-token-discipline.mdc (no hex)
|
|
84
|
+
• .cursor/rules/exxat-no-toast.mdc (no Sonner)
|
|
85
|
+
• .cursor/rules/exxat-ds-agents.mdc (top of stack)
|
|
86
|
+
|
|
87
|
+
…and produces a Blocker / Issue / Nit findings report with code citations
|
|
88
|
+
and a fix plan. Text-only Blocker fixes are auto-applied on confirmation.
|
|
89
|
+
|
|
90
|
+
For headless / CI use: hit the same skill via the SDK
|
|
91
|
+
(\`@cursor/sdk\` Agent.prompt) and grep the JSON output for "Blocker:".
|
|
92
|
+
`)
|
|
93
|
+
}
|
|
94
|
+
|
|
36
95
|
/** @returns {number} negative if a < b, 0 if equal, positive if a > b (x.y.z only) */
|
|
37
96
|
function compareSemver(a, b) {
|
|
38
97
|
const pa = a.split(".").map(n => parseInt(n, 10) || 0)
|
|
@@ -55,6 +114,10 @@ Commands:
|
|
|
55
114
|
update How to upgrade an existing project that depends on this package.
|
|
56
115
|
changelog Print CHANGELOG.md from the installed package (release notes + AI upgrade hints).
|
|
57
116
|
doctor Compare this CLI version vs npm registry "latest" (diagnose stale installs).
|
|
117
|
+
dev-guard Detect concurrent Vite dev servers — the #1 memory killer.
|
|
118
|
+
Wire as a "predev" hook to abort if a sibling dev server is already running.
|
|
119
|
+
audit <f> Print the prompt to audit a file against DS rules + UX principles (P1–P20).
|
|
120
|
+
The audit runs inside your agent client (the exxat-ux-audit skill).
|
|
58
121
|
|
|
59
122
|
Do NOT use plain npx @exxatdesignux/ui — use the scoped form below.
|
|
60
123
|
|
|
@@ -100,7 +163,7 @@ After upgrading — for humans and AI tools:
|
|
|
100
163
|
npx --package=@exxatdesignux/ui@latest exxat-ui sync-extras
|
|
101
164
|
|
|
102
165
|
3. Compare your app with the reference template when something new is unclear:
|
|
103
|
-
node_modules/@exxatdesignux/ui/template/
|
|
166
|
+
node_modules/@exxatdesignux/ui/template-vite/
|
|
104
167
|
|
|
105
168
|
**Still seeing old code?** Run **exxat-ui doctor** — the npm "latest" tag can lag
|
|
106
169
|
this Git repo until maintainers publish (git tag **ui-v<version>**).
|
|
@@ -191,6 +254,12 @@ switch (cmd) {
|
|
|
191
254
|
case "doctor":
|
|
192
255
|
printDoctor()
|
|
193
256
|
break
|
|
257
|
+
case "dev-guard":
|
|
258
|
+
runDevGuard(process.argv.slice(3))
|
|
259
|
+
break
|
|
260
|
+
case "audit":
|
|
261
|
+
runAudit(process.argv.slice(3))
|
|
262
|
+
break
|
|
194
263
|
case "help":
|
|
195
264
|
case "--help":
|
|
196
265
|
case "-h":
|
package/bin/init.mjs
CHANGED
|
@@ -18,15 +18,27 @@ import { fileURLToPath } from "node:url"
|
|
|
18
18
|
import { execSync } from "node:child_process"
|
|
19
19
|
|
|
20
20
|
const __dirname = dirname(fileURLToPath(import.meta.url))
|
|
21
|
-
const templateDir = resolve(__dirname, "../template")
|
|
22
21
|
const selfPkgPath = resolve(__dirname, "../package.json")
|
|
23
22
|
const selfPkg = JSON.parse(readFileSync(selfPkgPath, "utf8"))
|
|
24
23
|
|
|
25
24
|
const args = process.argv.slice(2)
|
|
26
|
-
const
|
|
25
|
+
const allFlags = args.filter((a) => a.startsWith("--"))
|
|
26
|
+
const flags = new Set(allFlags.map((f) => (f.includes("=") ? f.slice(0, f.indexOf("=")) : f)))
|
|
27
27
|
const positional = args.filter((a) => !a.startsWith("--"))
|
|
28
28
|
const targetArg = positional[0] ?? "."
|
|
29
29
|
const targetDir = resolve(process.cwd(), targetArg)
|
|
30
|
+
|
|
31
|
+
// `template-vite/` is the canonical scaffold source. The `template/`
|
|
32
|
+
// (Next.js) directory was retired alongside the apps/web Next removal
|
|
33
|
+
// (PR-6, May 2026); customers who need a Next scaffold can copy
|
|
34
|
+
// `template-vite/` and migrate it.
|
|
35
|
+
const templateDirName = "template-vite"
|
|
36
|
+
const templateDir = resolve(__dirname, `../${templateDirName}`)
|
|
37
|
+
if (!existsSync(templateDir)) {
|
|
38
|
+
console.error(`❌ Template directory ${templateDirName}/ not found in this @exxatdesignux/ui release.`)
|
|
39
|
+
console.error(` Try upgrading: npm i @exxatdesignux/ui@latest`)
|
|
40
|
+
process.exit(1)
|
|
41
|
+
}
|
|
30
42
|
// `displayName` is what we show in messages and use to derive package.json
|
|
31
43
|
// `name`. For "." or an absolute path we just use the basename; for a
|
|
32
44
|
// relative path the user typed (`my-app`, `apps/sandbox`) we keep it as-is.
|
|
@@ -41,7 +53,9 @@ const skipExtras = flags.has("--no-extras") || flags.has("--skip-extras")
|
|
|
41
53
|
|
|
42
54
|
if (flags.has("--help") || flags.has("-h")) {
|
|
43
55
|
console.log(`
|
|
44
|
-
create-exxat-app — scaffold a
|
|
56
|
+
create-exxat-app — scaffold a starter app on @exxatdesignux/ui
|
|
57
|
+
|
|
58
|
+
Stack: Vite + React + react-router-dom (low-memory, fast HMR).
|
|
45
59
|
|
|
46
60
|
Usage:
|
|
47
61
|
create-exxat-app [target-directory] [options]
|
|
@@ -97,7 +111,7 @@ if (blockers.length > 0 && !force) {
|
|
|
97
111
|
process.exit(1)
|
|
98
112
|
}
|
|
99
113
|
|
|
100
|
-
console.log(`📦 Copying Exxat DS starter app into ${displayName}/ …`)
|
|
114
|
+
console.log(`📦 Copying Exxat DS starter app (Vite) into ${displayName}/ …`)
|
|
101
115
|
cpSync(templateDir, targetDir, { recursive: true })
|
|
102
116
|
|
|
103
117
|
// Pin DS to this CLI's published version so `latest` cache drift cannot
|
package/bin/sync-extras.mjs
CHANGED
|
@@ -37,10 +37,11 @@ function log(...m) {
|
|
|
37
37
|
}
|
|
38
38
|
|
|
39
39
|
const SOURCES = {
|
|
40
|
-
skills:
|
|
41
|
-
rules:
|
|
42
|
-
patterns:
|
|
43
|
-
handbook:
|
|
40
|
+
skills: join(pkgRoot, "consumer-extras", "cursor-skills"),
|
|
41
|
+
rules: join(pkgRoot, "consumer-extras", "cursor-rules"),
|
|
42
|
+
patterns: join(pkgRoot, "consumer-extras", "patterns"),
|
|
43
|
+
handbook: join(pkgRoot, "consumer-extras", "handbook"),
|
|
44
|
+
templates: join(pkgRoot, "consumer-extras", "templates"),
|
|
44
45
|
}
|
|
45
46
|
|
|
46
47
|
const DESTINATIONS = {
|
|
@@ -49,6 +50,7 @@ const DESTINATIONS = {
|
|
|
49
50
|
cursorRules: join(cwd, ".cursor", "rules"),
|
|
50
51
|
patterns: join(cwd, "docs", "exxat-ds"),
|
|
51
52
|
handbook: join(cwd, "docs", "exxat-ds", "handbook"),
|
|
53
|
+
templates: join(cwd, "docs", "exxat-ds", "templates"),
|
|
52
54
|
}
|
|
53
55
|
|
|
54
56
|
let wrote = 0
|
|
@@ -150,11 +152,33 @@ function syncHandbook() {
|
|
|
150
152
|
}
|
|
151
153
|
}
|
|
152
154
|
|
|
155
|
+
/**
|
|
156
|
+
* Templates (handoff.md etc.) land in `docs/exxat-ds/templates/` next to the
|
|
157
|
+
* patterns + handbook. The agent fills them in via the `exxat-ux-discovery-protocol`
|
|
158
|
+
* rule at the close of any design task.
|
|
159
|
+
*/
|
|
160
|
+
function syncTemplates() {
|
|
161
|
+
if (!existsSync(SOURCES.templates)) {
|
|
162
|
+
console.warn("[sync-extras] no packaged templates (optional)")
|
|
163
|
+
skipped++
|
|
164
|
+
return
|
|
165
|
+
}
|
|
166
|
+
mkdirSync(DESTINATIONS.templates, { recursive: true })
|
|
167
|
+
for (const name of readdirSync(SOURCES.templates)) {
|
|
168
|
+
const src = join(SOURCES.templates, name)
|
|
169
|
+
if (!statSync(src).isFile()) continue
|
|
170
|
+
cpSync(src, join(DESTINATIONS.templates, name))
|
|
171
|
+
log(`[sync-extras] wrote docs/exxat-ds/templates/${name}`)
|
|
172
|
+
wrote++
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
|
|
153
176
|
syncSkillsTo(".cursor/skills", DESTINATIONS.cursorSkills)
|
|
154
177
|
syncSkillsTo(".claude/skills", DESTINATIONS.claudeSkills)
|
|
155
178
|
syncRules()
|
|
156
179
|
syncPatterns()
|
|
157
180
|
syncHandbook()
|
|
181
|
+
syncTemplates()
|
|
158
182
|
|
|
159
183
|
console.log(`[sync-extras] Done. ${wrote} files / dirs written; ${skipped} optional sources missing.`)
|
|
160
184
|
if (!QUIET) console.log("[sync-extras] Product routes and app content were not modified.")
|
|
@@ -11,6 +11,40 @@ touching product routes or pages.
|
|
|
11
11
|
| `cursor-rules/exxat-*.mdc` | `.cursor/rules/exxat-*.mdc` (replaced) — binding **MUST / MUST NOT** files |
|
|
12
12
|
| `patterns/*.md` | `docs/exxat-ds/*.md` (replaced) — pattern docs + **`consumer-upgrade-checklist.md`** |
|
|
13
13
|
| `handbook/*.md` | `docs/exxat-ds/handbook/*.md` (replaced) — `HANDBOOK`, `glossary`, `voice-and-tone`, `reference-implementations` |
|
|
14
|
+
| `templates/handoff.md` | `docs/exxat-ds/templates/handoff.md` (replaced) — design → engineering handoff artifact (the agent fills this in at the close of every design task) |
|
|
15
|
+
| `scripts/dev-guard.mjs` | Runs in place via `exxat-ui dev-guard` (no copy) — wire as `predev` to abort if a sibling `vite` is already running and stacking memory |
|
|
16
|
+
|
|
17
|
+
## CLI — what each subcommand does for your team
|
|
18
|
+
|
|
19
|
+
```bash
|
|
20
|
+
# Scaffold a new app (Vite + React + react-router-dom — fast cold start, ~250–400 MB RSS):
|
|
21
|
+
npx --package=@exxatdesignux/ui@latest create-exxat-app my-app
|
|
22
|
+
|
|
23
|
+
# Engineering quality-gate — read DS rules + UX principles for a file:
|
|
24
|
+
npx --package=@exxatdesignux/ui@latest exxat-ui audit src/views/students.tsx
|
|
25
|
+
|
|
26
|
+
# Memory guard for designers running long dev sessions:
|
|
27
|
+
"scripts": { "predev": "exxat-ui dev-guard" }
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
`dev-guard` lists every running `vite` parent and refuses to start a second
|
|
31
|
+
one without confirmation. Per `patterns/perf-memory-pattern.md` §2, two
|
|
32
|
+
parallel Vite servers stabilize at ~500–800 MB combined and confuse HMR —
|
|
33
|
+
even though they're 8× lighter than the Next dev servers this CLI used to
|
|
34
|
+
guard against (May 2026 migration).
|
|
35
|
+
|
|
36
|
+
## Rule tiers (`appliesTo:` metadata)
|
|
37
|
+
|
|
38
|
+
Every shipped `.mdc` rule carries an `appliesTo:` field:
|
|
39
|
+
|
|
40
|
+
- `[universal]` — UX principles, accessibility floor, anti-patterns, decision
|
|
41
|
+
frameworks. Works for any framework (HTML, React, Vue, iOS).
|
|
42
|
+
- `[react]` — cites React component names / hooks / JSX. Auto-attaches via
|
|
43
|
+
`globs:` when the agent edits matching files; not always-on.
|
|
44
|
+
|
|
45
|
+
Today this is documentation metadata. It is positioned for a future
|
|
46
|
+
`exxat-ui sync-extras --stack=html` flag that filters out `[react]` rules
|
|
47
|
+
for non-React consumers.
|
|
14
48
|
|
|
15
49
|
The CLI is **namespaced**: it only touches files starting with `exxat-` (skills + rules)
|
|
16
50
|
so a consumer's own non-Exxat rules / skills are preserved. Product code under `app/`,
|
|
@@ -41,11 +75,13 @@ pnpm --filter @exxatdesignux/ui vendor:consumer-extras
|
|
|
41
75
|
└── exxat-ds/
|
|
42
76
|
├── *-pattern.md ← narrative pattern docs (patterns/)
|
|
43
77
|
├── consumer-upgrade-checklist.md
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
78
|
+
├── handbook/
|
|
79
|
+
│ ├── HANDBOOK.md
|
|
80
|
+
│ ├── glossary.md
|
|
81
|
+
│ ├── voice-and-tone.md
|
|
82
|
+
│ └── reference-implementations.md
|
|
83
|
+
└── templates/
|
|
84
|
+
└── handoff.md ← design → engineering handoff artifact
|
|
49
85
|
```
|
|
50
86
|
|
|
51
87
|
## Note on handbook link rewriting
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
description: Exxat DS — WCAG 2.1 AA, ARIA tablists, 24px targets, contrast; see AGENTS.md §8 and exxat-accessibility skill
|
|
3
3
|
alwaysApply: true
|
|
4
|
+
appliesTo: [universal]
|
|
4
5
|
---
|
|
5
6
|
|
|
6
7
|
# Exxat DS — accessibility (binding summary)
|
|
@@ -26,7 +27,7 @@ alwaysApply: true
|
|
|
26
27
|
- **C. Interactive icon-only button/link** (close `×`, chevron, overflow `⋯`, sort direction, filter chip dismiss, copy, Ask Leo toggle, row actions) → MUST pair **`aria-label`** on the `<button>` with a wrapping **`Tooltip`**. `aria-label` alone is NOT enough — sighted mouse users and keyboard users rely on the tooltip to discover what a bare icon does.
|
|
27
28
|
|
|
28
29
|
In all three cases, the inner `<i>` / `<svg>` MUST be `aria-hidden`; the accessible name lives on the wrapping element. Tooltip text MUST match the accessible name. Narrow exception: a chevron inside a labelled composite (`Select`, `Combobox`) where the parent control already names the whole thing. See **§8.6 (Case A/B/C)** in `AGENTS.md` and the accessibility skill.
|
|
29
|
-
10. **Keyboard shortcut hints inside buttons** MUST use **`<Kbd variant="bare">`** (no background, no border, inherits `currentColor` at 70%). The default `tile` variant is reserved for **tooltips** and **menu `shortcut=` slots**. Glue multi-key chords into one bare kbd (e.g. `<Kbd variant="bare">⌘⌥K</Kbd>`), not one tile per key. Reference: `Next` / `Back` buttons in `new-
|
|
30
|
+
10. **Keyboard shortcut hints inside buttons** MUST use **`<Kbd variant="bare">`** (no background, no border, inherits `currentColor` at 70%). The default `tile` variant is reserved for **tooltips** and **menu `shortcut=` slots**. Glue multi-key chords into one bare kbd (e.g. `<Kbd variant="bare">⌘⌥K</Kbd>`), not one tile per key. Reference: `Next` / `Back` buttons in `new-library-item-form.tsx`; see `.cursor/rules/exxat-kbd-shortcuts.mdc`.
|
|
30
31
|
|
|
31
32
|
After changing **views toolbar** or **tab** UIs, re-run **axe** (or equivalent) on **Placements** (or the affected page).
|
|
32
33
|
|
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
---
|
|
2
|
-
description: Exxat DS — board (kanban) cards
|
|
3
|
-
|
|
2
|
+
description: Exxat DS — board (kanban) cards via ListPageBoardCard, badges, primitives. Auto-attaches when editing React board/list files; ask explicitly when designing kanban surfaces.
|
|
3
|
+
globs: apps/web/components/**/*.{tsx,ts}
|
|
4
|
+
alwaysApply: false
|
|
5
|
+
appliesTo: [react]
|
|
4
6
|
---
|
|
5
7
|
|
|
6
8
|
# Exxat DS — board cards
|
|
@@ -11,7 +13,7 @@ alwaysApply: true
|
|
|
11
13
|
|
|
12
14
|
1. **Shell** — Use **`ListPageBoardCard`** from **`components/data-views/list-page-board-card.tsx`** for product board cards (same **`Card` `size="sm"`** treatment as Placements).
|
|
13
15
|
2. **Hierarchy** — **Title** (`ListPageBoardCardTitleRow`) → optional **avatar** (`ListPageBoardCardAvatar` on `trailing`) → **status row** (`ListPageBoardCardBadgeRow` + **`ListHubStatusBadge`** **`surface="board"`**) when the entity has status → **body** (`ListPageBoardCardBody`) with **`BoardCardTwoLineBlock`** / **`BoardCardIconRow`** (**`components/data-views/board-card-primitives.tsx`**).
|
|
14
|
-
3. **Status** —
|
|
16
|
+
3. **Status** — Use **`ListHubStatusBadge`** with **`surface="table"`** in grid / list rows and **`surface="board"`** on kanban cards. Generic semantic tints live in **`lib/list-status-badges.ts`** (**`LIST_HUB_STATUS_TINT_SUCCESS / WARNING / INFO / NEUTRAL / DANGER`**); compose per-domain label / icon maps next to the entity's mock data. Reference: **`library-board-view.tsx`** + **`lib/mock/library.ts`**. **MUST NOT** use **`uppercase`** on those chips.
|
|
15
17
|
4. **Simple column boards** — **`ListPageBoardTemplate`** + **`renderCard`**; compose **`ListPageBoardCard`** inside **`renderCard`**.
|
|
16
18
|
|
|
17
19
|
## MUST NOT
|
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
---
|
|
2
|
-
description: Single source of truth for hub rows, KPIs, table properties, detail views, and shared view chrome — dataset + presentation consistency across DataListViewType surfaces
|
|
3
|
-
|
|
2
|
+
description: Single source of truth for hub rows, KPIs, table properties, detail views, and shared view chrome — dataset + presentation consistency across DataListViewType surfaces. Auto-attaches when editing list-hub React files.
|
|
3
|
+
globs: apps/web/{components,lib}/**/*.{tsx,ts}
|
|
4
|
+
alwaysApply: false
|
|
5
|
+
appliesTo: [react]
|
|
4
6
|
---
|
|
5
7
|
|
|
6
8
|
# Exxat DS — centralized list hub dataset + presentation
|
|
@@ -1,19 +1,20 @@
|
|
|
1
1
|
---
|
|
2
2
|
description: Exxat DS — global command palette (⌘K) as search + quick AI vs Ask Leo for long answers.
|
|
3
3
|
alwaysApply: true
|
|
4
|
+
appliesTo: [universal]
|
|
4
5
|
---
|
|
5
6
|
|
|
6
7
|
# Exxat DS — global command palette (`CommandMenu`)
|
|
7
8
|
|
|
8
9
|
## Intent
|
|
9
10
|
|
|
10
|
-
- **`CommandMenu`** (**⌘K** / **Ctrl+K**) is **global search** (routes, library, patterns, AI starters, optional row data such as
|
|
11
|
+
- **`CommandMenu`** (**⌘K** / **Ctrl+K**) is **global search** (routes, library, patterns, AI starters, optional row data such as student names / question stems) — see **`apps/web/AGENTS.md` §7.1** and **`apps/web/docs/command-menu-pattern.md`**.
|
|
11
12
|
- **Quick / lookup / short AI:** Prefer **results inside the palette** when the product can return compact answers or lightweight “research” without leaving the flow.
|
|
12
13
|
- **Long or complex answers:** **Ask Leo** side panel (**⌘⌥K** / **Ctrl+Alt+K**)—not forced into the palette.
|
|
13
14
|
|
|
14
15
|
## Implementation pointers
|
|
15
16
|
|
|
16
|
-
- Shell: `apps/web/components/command-menu.tsx`; config **`buildCommandMenuConfig()`** in **`apps/web/lib/command-menu-config.ts`**; optional **`dataGroups`** from **`apps/web/lib/command-menu-search-data.ts`** (e.g. **`getCommandMenuSearchDataGroups()`**), wired in **`apps/web/
|
|
17
|
+
- Shell: `apps/web/components/command-menu.tsx`; config **`buildCommandMenuConfig()`** in **`apps/web/lib/command-menu-config.ts`**; optional **`dataGroups`** from **`apps/web/lib/command-menu-search-data.ts`** (e.g. **`getCommandMenuSearchDataGroups()`**), wired in **`apps/web/src/App.tsx`**. Keep domain mapping out of the shell.
|
|
17
18
|
- Large indexes: set **`searchOnly: true`** on **`CommandMenuGroup`** so **`command-menu.tsx`** skips the group until the user types (avoids listing every row on open; cmdk shows all items when the search string is empty).
|
|
18
19
|
|
|
19
20
|
## See also
|
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
---
|
|
2
|
-
description: Exxat DS — product data tables must use DataTable with search, filters,
|
|
3
|
-
|
|
2
|
+
description: Exxat DS — product data tables must use HubTable/DataTable with search, filters, table properties; no alternate table stacks. Auto-attaches when editing apps/web React files; ask for it explicitly when designing a list/grid surface.
|
|
3
|
+
globs: apps/web/**/*.{tsx,ts}
|
|
4
|
+
alwaysApply: false
|
|
5
|
+
appliesTo: [react]
|
|
4
6
|
---
|
|
5
7
|
|
|
6
8
|
# Exxat DS — data tables (mandatory pattern)
|
|
@@ -17,7 +19,7 @@ For **any app screen that shows a browsable, filterable grid of records** (direc
|
|
|
17
19
|
6. **Table properties:** Always reachable. `HubTable` mounts `TablePropertiesDrawerButton` in `toolbarSlot`; on **`ListPageTemplate`** pages with **table / list / board / dashboard** tabs it **MUST** also receive **`currentView`** and **`onViewChange`** (see **`apps/web/AGENTS.md` §4.2** and **`.cursor/rules/exxat-table-properties-drawer.mdc`**) so Properties matches the selected view.
|
|
18
20
|
7. **Dropdown menus:** `DropdownMenuContent` uses the shared **`@exxatdesignux/ui`** default (**intrinsic `w-max`**, **`min-w-52`**, capped **`max-w`**) for view settings, row ⋯, column menus, and filter pickers — **pure CSS**, no **`ResizeObserver`**. Override only for deliberate narrow/wide rails (e.g. pagination **`w-20`**, account trigger-width, school switcher **`!w-max min-w-72 …`**). See **`docs/data-views-pattern.md`** (“Dropdown menus”).
|
|
19
21
|
8. **Cell renderers MUST come from `@/components/data-views` (`table-cells.tsx`).** The DS ships **`ProgressCell`**, **`CurrencyCell`**, **`NumericCell`**, **`RatingCell`**, **`SignalBarsCell`**, **`BooleanToggleCell`**, **`AttachmentCountCell`**, **`ExternalLinkCell`**, **`RelativeTimeCell`**, **`PeopleAvatarRailCell`**, **`PillCell`**, **`TagListCell`**, and a generic **`RowActionsCell<TRow>`**. A `ColumnDef['cell']` for these patterns is a **one-liner** that calls the named cell. **MUST NOT** inline `Intl.NumberFormat`, raw `<a target="_blank">`, `[1,2,3,4,5].map(s => …)` star loops, paperclip + count chips, custom face-rail `AvatarGroup`s, or per-hub `DropdownMenu` overflow menus inside `cell:` — those are signals you're re-deriving a shipped primitive. Catalog: `apps/web/components/columns-showcase.tsx` (`/columns`). Skill: `.cursor/skills/exxat-token-economy/SKILL.md` §3.
|
|
20
|
-
9. **Add view parity** — **`FULL_HUB_SUPPORTED_VIEWS`** + a real renderer per view — **`.cursor/rules/exxat-hub-supported-views.mdc`**, **`
|
|
22
|
+
9. **Add view parity** — **`FULL_HUB_SUPPORTED_VIEWS`** + a real renderer per view — **`.cursor/rules/exxat-hub-supported-views.mdc`**, **`apps/web/docs/hub-supported-views-pattern.md`**.
|
|
21
23
|
|
|
22
24
|
**Reference implementations:**
|
|
23
25
|
|
|
@@ -1,3 +1,10 @@
|
|
|
1
|
+
---
|
|
2
|
+
description: Dedicated search surfaces — DedicatedSearch* templates, recents storage, landing-vs-results URL composer. Auto-attaches when editing search-related React routes.
|
|
3
|
+
globs: apps/web/{components,app,lib}/**/*.{tsx,ts}
|
|
4
|
+
alwaysApply: false
|
|
5
|
+
appliesTo: [react]
|
|
6
|
+
---
|
|
7
|
+
|
|
1
8
|
# Exxat DS — dedicated search surfaces
|
|
2
9
|
|
|
3
10
|
**Authoritative detail:** **`apps/web/AGENTS.md` §4.8**, **`.cursor/skills/exxat-dedicated-search-surfaces/SKILL.md`**.
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
description: Exxat DS — drawer/sheet vs modal dialog vs route for flows and confirmations.
|
|
3
3
|
alwaysApply: true
|
|
4
|
+
appliesTo: [universal]
|
|
4
5
|
---
|
|
5
6
|
|
|
6
7
|
# Exxat DS — drawer vs dialog
|
|
@@ -19,4 +20,4 @@ alwaysApply: true
|
|
|
19
20
|
## See also
|
|
20
21
|
|
|
21
22
|
- **`docs/drawer-vs-dialog-pattern.md`** · **`.cursor/skills/exxat-drawer-vs-dialog/SKILL.md`**
|
|
22
|
-
- **`exxat-page-vs-drawer.mdc`** (
|
|
23
|
+
- **`exxat-page-vs-drawer.mdc`** (drawer vs **route**)
|
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
---
|
|
2
|
-
description: List-page hubs — FULL_HUB_SUPPORTED_VIEWS, Add view parity, and real renderers (never trimmed allowlists or placeholder list rows)
|
|
3
|
-
|
|
2
|
+
description: List-page hubs — FULL_HUB_SUPPORTED_VIEWS, Add view parity, and real renderers (never trimmed allowlists or placeholder list rows). Auto-attaches when editing hub clients / list-page templates.
|
|
3
|
+
globs: apps/web/components/**/*.{tsx,ts}
|
|
4
|
+
alwaysApply: false
|
|
5
|
+
appliesTo: [react]
|
|
4
6
|
---
|
|
5
7
|
|
|
6
8
|
# Exxat DS — hub supported views (Add view parity)
|
|
@@ -50,5 +52,5 @@ Every **`ListPageTemplate`** + **`HubTable`** hub that mounts a product data gri
|
|
|
50
52
|
## See also
|
|
51
53
|
|
|
52
54
|
- **`.cursor/rules/exxat-data-tables.mdc`**, **`exxat-list-page-connected-views.mdc`**, **`exxat-list-page-view-shells.mdc`**
|
|
53
|
-
- **`
|
|
54
|
-
- **`
|
|
55
|
+
- **`apps/web/docs/hub-supported-views-pattern.md`**
|
|
56
|
+
- **`apps/web/docs/data-views-pattern.md`**
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
description: Exxat DS — show Kbd hints on primary/secondary actions, search, Ask Leo; avoid browser-reserved chords.
|
|
3
3
|
alwaysApply: true
|
|
4
|
+
appliesTo: [universal]
|
|
4
5
|
---
|
|
5
6
|
|
|
6
7
|
# Exxat DS — keyboard shortcuts (`Kbd`)
|
|
@@ -24,7 +25,7 @@ Use `@/components/ui/kbd` (`Kbd` + `KbdGroup`) anywhere users discover actions b
|
|
|
24
25
|
| Inside a `DropdownMenuItem` via `shortcut=` | menu handles it — pass the chord string |
|
|
25
26
|
| Standalone helper text on a surface | **default `tile`** |
|
|
26
27
|
|
|
27
|
-
Glue multi-key chords into **one** bare kbd (`<Kbd variant="bare">⌘⌥K</Kbd>`), not one tile per key. See `new-
|
|
28
|
+
Glue multi-key chords into **one** bare kbd (`<Kbd variant="bare">⌘⌥K</Kbd>`), not one tile per key. See `new-library-item-form.tsx` (Next = `{mod}⏎`, Back = `{mod}{alt}←`) and the primary "Ask Leo" button inside chart insight popovers.
|
|
28
29
|
|
|
29
30
|
1. **Pair hint with behavior** — If `Kbd` shows a chord, implement the same shortcut. **Preferred:** the shared primitives from `@/components/ui/dropdown-menu`:
|
|
30
31
|
|
|
@@ -58,8 +59,8 @@ Use `@/components/ui/kbd` (`Kbd` + `KbdGroup`) anywhere users discover actions b
|
|
|
58
59
|
| Toggle main sidebar | ⌘/Ctrl + **B** (`components/ui/sidebar.tsx`) |
|
|
59
60
|
| Table search | ⌘/Ctrl + **K** (no Alt — `DataTable`) |
|
|
60
61
|
| Ask Leo | ⌘/Ctrl + **⌥/Alt** + **K** |
|
|
61
|
-
| New
|
|
62
|
-
|
|
|
62
|
+
| New record (primary hub header) | ⌘/Ctrl + **⌥/Alt** + **N** |
|
|
63
|
+
| Hub overflow menu (⋯) | ⌘/Ctrl + **⌥/Alt** + **M** |
|
|
63
64
|
| Export | ⌘/Ctrl + **⇧/Shift** + **E** |
|
|
64
65
|
| Hide/Show metric section | ⌘/Ctrl + **⌥/Alt** + **H** |
|
|
65
66
|
| Rename (view, tab) | **F2** |
|
|
@@ -79,14 +80,14 @@ Every **workflow surface** (form, dialog, drawer, sheet, multi-step wizard final
|
|
|
79
80
|
1. **Primary action (submit/commit)** — **Enter** (⏎). Render the `<Kbd>⏎</Kbd>` **inline inside the button** (after the label, inside a `<KbdGroup className="ml-1.5">`) — NOT inside a hover `Tip`. Primary/secondary workflow buttons must expose the shortcut at rest so it is discoverable without hovering. Pair with a `<Shortcut keys="Enter" onInvoke={...}>` mounted while the surface is open. The shared `useShortcut` hook skips events from inputs/textarea/contenteditable, so Enter inside a text field still types normally — it only fires when focus is on the surface chrome.
|
|
80
81
|
2. **Secondary action (Cancel/Dismiss)** — **Esc**. Inline `<Kbd>Esc</Kbd>` inside the Cancel button (same `ml-1.5` pattern). Radix `Dialog` / `Sheet` / `AlertDialog` already bind Esc natively.
|
|
81
82
|
|
|
82
|
-
> Tip-on-hover Kbd hints remain correct for **page-level** actions (e.g. "New
|
|
83
|
+
> Tip-on-hover Kbd hints remain correct for **page-level** actions (e.g. primary "New …" CTA, ⋯ overflow triggers) where the button is part of dense page chrome and a persistent Kbd would crowd the layout. Workflow buttons inside a form/drawer/dialog are spacious enough to render the Kbd inline.
|
|
83
84
|
|
|
84
85
|
**Variant inside a button:** always use `<Kbd variant="bare">` — no background, no border, inherits `currentColor` at 70% opacity. The default tile variant looks like a pasted-on patch on filled primary buttons. Glue multi-key chords into one `<Kbd variant="bare">⌘⌥←</Kbd>` rather than one tile per key.
|
|
85
86
|
3. **Multi-step wizards** — plain **Enter** must NOT submit on intermediate steps (it would auto-close the review/final step when users hit Enter inside an input). Either:
|
|
86
87
|
- Gate `form.onSubmit` on `step === lastStep` (`if (step !== N) { e.preventDefault(); return }`), **or**
|
|
87
88
|
- Remove `type="submit"` on intermediate Next buttons and bind **⌘Enter** to "Next" via `<Shortcut>`.
|
|
88
89
|
On the final step, plain **Enter** submits and the Kbd hint shows **⏎**.
|
|
89
|
-
4. Examples in-app: `new-
|
|
90
|
+
4. Examples in-app: `new-library-item-form.tsx` (Create = Enter on the final step, Back = ⌘⌥←), `export-drawer.tsx` (Export = Enter, Cancel = Esc).
|
|
90
91
|
|
|
91
92
|
## Every action menu MUST carry shortcuts
|
|
92
93
|
|
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
description: KeyMetrics variant flat — transparent band, brand glow only, OKLCH hairlines
|
|
3
3
|
globs: apps/web/components/**/*key-metrics*,apps/web/app/globals.css,apps/web/docs/kpi*.md
|
|
4
4
|
alwaysApply: false
|
|
5
|
+
appliesTo: [react]
|
|
5
6
|
---
|
|
6
7
|
|
|
7
8
|
# Exxat DS — KPI flat band (`variant="flat"`)
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
---
|
|
2
2
|
description: Library library — folder-scoped hub header More menu must expose Customize folder; sheet on hub client
|
|
3
|
-
globs: apps/web/components/library-*.tsx, packages/ui/template/components/library-*.tsx
|
|
3
|
+
globs: apps/web/components/library-*.tsx, packages/ui/template-vite/components/library-*.tsx
|
|
4
4
|
alwaysApply: false
|
|
5
|
+
appliesTo: [react]
|
|
5
6
|
---
|
|
6
7
|
|
|
7
8
|
# Exxat DS — Library hub header (folder scope)
|
|
@@ -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
|
|