@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
|
@@ -0,0 +1,156 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* dev-guard — catches the #1 cause of memory exhaustion before a second
|
|
4
|
+
* dev server boots and lifts total system RSS unnecessarily.
|
|
5
|
+
*
|
|
6
|
+
* Detects Vite parents under the same `pnpm dev` lineage. A single Vite
|
|
7
|
+
* dev server stabilizes at ~250–500 MB; stacking two doubles total RSS,
|
|
8
|
+
* confuses HMR (two ports, two websockets), and creates "which one am I
|
|
9
|
+
* actually viewing?" mistakes when designers compare branches.
|
|
10
|
+
*
|
|
11
|
+
* (History: until PR-6 (May 2026) this guard also detected `next-server`
|
|
12
|
+
* parents because `apps/web` ran on Next + Turbopack. After Next was
|
|
13
|
+
* removed, the Next branch became dead code — this version is Vite-only.)
|
|
14
|
+
*
|
|
15
|
+
* Run as `predev` hook (or any time you want to verify environment health):
|
|
16
|
+
* "predev": "exxat-ui dev-guard"
|
|
17
|
+
*
|
|
18
|
+
* Behavior:
|
|
19
|
+
* - Lists every running `vite` parent.
|
|
20
|
+
* - Exits 0 silently if zero or one is found (the one is *us* — fine).
|
|
21
|
+
* - Prints a guided warning if 2+ are found, names the cwd of each,
|
|
22
|
+
* and asks the user whether to abort or continue.
|
|
23
|
+
* - In CI (`CI=true`) or with `--quiet`, exits 0 without prompting.
|
|
24
|
+
*
|
|
25
|
+
* Tested against macOS / Linux. Windows users: PowerShell `Get-Process` would
|
|
26
|
+
* need a separate branch; not implemented yet because the team is mac/linux.
|
|
27
|
+
*/
|
|
28
|
+
|
|
29
|
+
import { execFileSync } from "node:child_process"
|
|
30
|
+
import { createInterface } from "node:readline/promises"
|
|
31
|
+
|
|
32
|
+
const QUIET = process.argv.includes("--quiet") || process.env.CI === "true"
|
|
33
|
+
|
|
34
|
+
/** @typedef {{ pid: number, cwd: string, rss: number }} ViteProc */
|
|
35
|
+
|
|
36
|
+
/** @returns {ViteProc[]} */
|
|
37
|
+
function listDevServers() {
|
|
38
|
+
let out = ""
|
|
39
|
+
try {
|
|
40
|
+
out = execFileSync(
|
|
41
|
+
"ps",
|
|
42
|
+
["-axo", "pid=,rss=,command="],
|
|
43
|
+
{ encoding: "utf8", stdio: ["ignore", "pipe", "ignore"] },
|
|
44
|
+
)
|
|
45
|
+
} catch {
|
|
46
|
+
// ps unavailable (very unusual). Fail open — better to let dev start.
|
|
47
|
+
return []
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
const matches = []
|
|
51
|
+
for (const line of out.split("\n")) {
|
|
52
|
+
const m = line.match(/^\s*(\d+)\s+(\d+)\s+(.+)$/)
|
|
53
|
+
if (!m) continue
|
|
54
|
+
const [, pid, rss, command] = m
|
|
55
|
+
|
|
56
|
+
// Vite — bin/vite.js or `node ... vite ...` parents. Skip vitest, esbuild
|
|
57
|
+
// children, vite preview workers. We require the literal `vite` token
|
|
58
|
+
// either at end of path (.../bin/vite[.js]) or as a subcommand argv.
|
|
59
|
+
const isViteDev =
|
|
60
|
+
/(\/vite(\.js|\.mjs)?|[\s/]vite\s)\b/.test(command) &&
|
|
61
|
+
!/\bvitest\b/.test(command) &&
|
|
62
|
+
!/\bvite\s+preview\b/.test(command) &&
|
|
63
|
+
!/\besbuild\b/.test(command)
|
|
64
|
+
|
|
65
|
+
if (!isViteDev) continue
|
|
66
|
+
matches.push({
|
|
67
|
+
pid: Number(pid),
|
|
68
|
+
cwd: cwdOfPid(Number(pid)) ?? "(cwd unknown)",
|
|
69
|
+
rss: Number(rss), // KB
|
|
70
|
+
})
|
|
71
|
+
}
|
|
72
|
+
return matches
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
/** Best-effort cwd lookup. macOS has lsof; Linux has /proc/<pid>/cwd. */
|
|
76
|
+
function cwdOfPid(pid) {
|
|
77
|
+
try {
|
|
78
|
+
if (process.platform === "darwin") {
|
|
79
|
+
const out = execFileSync("lsof", ["-p", String(pid), "-d", "cwd", "-Fn"], {
|
|
80
|
+
encoding: "utf8",
|
|
81
|
+
stdio: ["ignore", "pipe", "ignore"],
|
|
82
|
+
})
|
|
83
|
+
const line = out.split("\n").find(l => l.startsWith("n"))
|
|
84
|
+
return line ? line.slice(1) : null
|
|
85
|
+
}
|
|
86
|
+
if (process.platform === "linux") {
|
|
87
|
+
const out = execFileSync("readlink", ["-f", `/proc/${pid}/cwd`], {
|
|
88
|
+
encoding: "utf8",
|
|
89
|
+
stdio: ["ignore", "pipe", "ignore"],
|
|
90
|
+
})
|
|
91
|
+
return out.trim() || null
|
|
92
|
+
}
|
|
93
|
+
} catch {
|
|
94
|
+
return null
|
|
95
|
+
}
|
|
96
|
+
return null
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
function fmtMB(kb) {
|
|
100
|
+
return (kb / 1024).toFixed(0) + " MB"
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
async function main() {
|
|
104
|
+
const servers = listDevServers()
|
|
105
|
+
if (servers.length <= 1) {
|
|
106
|
+
if (!QUIET) {
|
|
107
|
+
console.log(
|
|
108
|
+
servers.length === 0
|
|
109
|
+
? "[dev-guard] No other dev server running. Safe to start."
|
|
110
|
+
: `[dev-guard] One vite already running (pid ${servers[0].pid}, ${fmtMB(servers[0].rss)}). Reusing it.`,
|
|
111
|
+
)
|
|
112
|
+
}
|
|
113
|
+
process.exit(0)
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
// Two or more — this is the bad path.
|
|
117
|
+
console.error("")
|
|
118
|
+
console.error("⚠ dev-guard: multiple Vite dev-server processes detected.")
|
|
119
|
+
console.error("")
|
|
120
|
+
console.error("Two parallel Vite dev servers stabilize at ~500–800 MB combined")
|
|
121
|
+
console.error("and confuse HMR (two ports, two websockets, components from two")
|
|
122
|
+
console.error("workspace roots). Stop the one you're not actively touching.")
|
|
123
|
+
console.error("")
|
|
124
|
+
for (const s of servers) {
|
|
125
|
+
console.error(
|
|
126
|
+
` pid ${String(s.pid).padEnd(6)} ${fmtMB(s.rss).padEnd(8)} ${s.cwd}`,
|
|
127
|
+
)
|
|
128
|
+
}
|
|
129
|
+
console.error("")
|
|
130
|
+
console.error("Recommended: stop the one you're not actively touching.")
|
|
131
|
+
console.error(" • macOS / Linux: kill <pid>")
|
|
132
|
+
console.error(" • pm2 daemon: pm2 stop exxat-ds (or pm2 delete exxat-ds)")
|
|
133
|
+
console.error("")
|
|
134
|
+
|
|
135
|
+
if (QUIET) {
|
|
136
|
+
// CI / quiet mode — don't block, just warn.
|
|
137
|
+
process.exit(0)
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
const rl = createInterface({ input: process.stdin, output: process.stdout })
|
|
141
|
+
const ans = (await rl.question("Continue starting another dev server anyway? [y/N] ")).trim().toLowerCase()
|
|
142
|
+
rl.close()
|
|
143
|
+
|
|
144
|
+
if (ans === "y" || ans === "yes") {
|
|
145
|
+
console.error("[dev-guard] Continuing.")
|
|
146
|
+
process.exit(0)
|
|
147
|
+
}
|
|
148
|
+
console.error("[dev-guard] Aborted. Stop the other server, then re-run dev.")
|
|
149
|
+
process.exit(1)
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
main().catch(err => {
|
|
153
|
+
// Never let a guard bug block dev. Log and pass through.
|
|
154
|
+
console.error("[dev-guard] internal error, allowing dev to start:", err?.message ?? err)
|
|
155
|
+
process.exit(0)
|
|
156
|
+
})
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
# Exxat DS — templates
|
|
2
|
+
|
|
3
|
+
Markdown templates the agent fills in (or copies into a PR / docs folder) at
|
|
4
|
+
specific points of a design task.
|
|
5
|
+
|
|
6
|
+
| File | When the agent emits it |
|
|
7
|
+
|------|------------------------|
|
|
8
|
+
| `handoff.md` | After every design task that creates or rebuilds a surface, before the engineer wires real data. Source of truth for the design → engineering handoff. |
|
|
9
|
+
|
|
10
|
+
These ship via `@exxatdesignux/ui` and are written into the consumer repo at:
|
|
11
|
+
|
|
12
|
+
```
|
|
13
|
+
docs/exxat-ds/templates/<file>
|
|
14
|
+
```
|
|
15
|
+
|
|
16
|
+
…by `exxat-ui sync-extras`.
|
|
17
|
+
|
|
18
|
+
The agent locates the template via the `exxat-ux-discovery-protocol` rule
|
|
19
|
+
(see `.cursor/rules/exxat-ux-discovery-protocol.mdc`) and fills it in as
|
|
20
|
+
the closing artifact of a build.
|
|
21
|
+
|
|
22
|
+
Engineers do not edit these templates by hand. They open the filled-in copy
|
|
23
|
+
attached to a PR / saved at `docs/exxat-ds/handoff/<surface-slug>.md`.
|
|
@@ -0,0 +1,190 @@
|
|
|
1
|
+
# Design → Engineering Handoff
|
|
2
|
+
|
|
3
|
+
This template is the **single artifact** the agent produces at the end of any
|
|
4
|
+
design task that creates or rebuilds a surface (page, hub, detail view,
|
|
5
|
+
wizard, drawer, sheet). It is the contract between the designer who shaped
|
|
6
|
+
the work in the brief and the engineer who ships it.
|
|
7
|
+
|
|
8
|
+
The agent fills this in as part of the `exxat-ux-discovery-protocol` flow.
|
|
9
|
+
The engineer reads it once, runs `exxat-ui audit <file>` against the
|
|
10
|
+
generated files, and is done.
|
|
11
|
+
|
|
12
|
+
---
|
|
13
|
+
|
|
14
|
+
## 1. Job-to-be-done
|
|
15
|
+
|
|
16
|
+
> Single sentence. The decision or action this surface enables for the user.
|
|
17
|
+
> Copy from the design brief — do not invent.
|
|
18
|
+
|
|
19
|
+
(example) *Coordinator identifies and acts on at-risk students before placement.*
|
|
20
|
+
|
|
21
|
+
## 2. Audience & frequency
|
|
22
|
+
|
|
23
|
+
> Persona (admin / coordinator / faculty / student / preceptor) + how often
|
|
24
|
+
> they hit this surface (daily / weekly / occasional).
|
|
25
|
+
|
|
26
|
+
(example) *Program coordinator, daily, keyboard-first.*
|
|
27
|
+
|
|
28
|
+
## 3. Pattern + IA
|
|
29
|
+
|
|
30
|
+
> The DS pattern this surface uses + the information architecture shape.
|
|
31
|
+
> Should match the brief.
|
|
32
|
+
|
|
33
|
+
- **Surface kind**: route | sheet | dialog | inline (one of the four)
|
|
34
|
+
- **Layout**: page-header + ?? (single column / split / data-table grid / …)
|
|
35
|
+
- **Navigation**: breadcrumb? back affordance? anchor sub-nav?
|
|
36
|
+
- **Header tier**: identity, status, KPI, ⋯ overflow, primary CTA
|
|
37
|
+
|
|
38
|
+
## 4. Reference implementations
|
|
39
|
+
|
|
40
|
+
> One **repo** reference + two **modern SaaS** analogues (cite by product
|
|
41
|
+
> name + Mx codes from `docs/exxat-ds/modern-saas-patterns.md`).
|
|
42
|
+
|
|
43
|
+
- **Repo**: `apps/web/components/<file>.tsx`
|
|
44
|
+
- **Modern**: `<Product 1>` (Mx, Mx); `<Product 2>` (Mx, Mx)
|
|
45
|
+
|
|
46
|
+
## 5. Components used (DS inventory)
|
|
47
|
+
|
|
48
|
+
> Every DS primitive consumed. The agent fills this in by inspecting its
|
|
49
|
+
> own diff. No new bespoke widgets unless approved in the brief.
|
|
50
|
+
|
|
51
|
+
| Primitive | From | Why |
|
|
52
|
+
|-----------|------|-----|
|
|
53
|
+
| `PageHeader` | `@exxatdesignux/ui/page-header` | Identity + actions row |
|
|
54
|
+
| `HubTable` | `@/components/data-views` | Rows + filters + properties |
|
|
55
|
+
| … | … | … |
|
|
56
|
+
|
|
57
|
+
## 6. Tokens consumed
|
|
58
|
+
|
|
59
|
+
> Every CSS custom property the agent referenced. No hex literals — see
|
|
60
|
+
> `exxat-token-discipline`.
|
|
61
|
+
|
|
62
|
+
- Colors: `--exxat-color-bg-app`, `--exxat-color-text-primary`, …
|
|
63
|
+
- Spacing: `--exxat-spacing-*`
|
|
64
|
+
- Radii: `--exxat-radius-*`
|
|
65
|
+
- Shadow / elevation: `--exxat-shadow-*`
|
|
66
|
+
|
|
67
|
+
## 7. Icons used
|
|
68
|
+
|
|
69
|
+
> Font Awesome Pro classes. Add to the subset audit (`fa:subset-audit`)
|
|
70
|
+
> if any are new to the kit.
|
|
71
|
+
|
|
72
|
+
- `fa-light fa-graduation-cap` — student identity
|
|
73
|
+
- `fa-light fa-shield-check` — compliance status
|
|
74
|
+
- …
|
|
75
|
+
|
|
76
|
+
## 8. Accessibility floor
|
|
77
|
+
|
|
78
|
+
> Filled by the agent automatically (the universal a11y rule is on). Engineer
|
|
79
|
+
> verifies by running axe / Deque on the deployed surface.
|
|
80
|
+
|
|
81
|
+
- [x] One H1 per page; record name in `PageHeader.title` only
|
|
82
|
+
- [x] Single primary CTA; everything else is outline / ghost / link
|
|
83
|
+
- [x] `Tablist` semantics correct (no buttons inside `role=tablist`)
|
|
84
|
+
- [x] All interactive targets ≥ 24 × 24 CSS px
|
|
85
|
+
- [x] Contrast ≥ 4.5 : 1 for text, ≥ 3 : 1 for UI / focus
|
|
86
|
+
- [x] Every icon has either `aria-hidden` (decorative) or `aria-label` + tooltip (informational)
|
|
87
|
+
- [x] Format hints rendered as `FormDescription`, not placeholder
|
|
88
|
+
- [x] Every primary action has an `Enter` shortcut + visible Kbd hint
|
|
89
|
+
- [x] Every cancel action accepts `Esc`
|
|
90
|
+
|
|
91
|
+
## 9. Data shape
|
|
92
|
+
|
|
93
|
+
> What rows / records / fields this surface reads from. Engineer wires the
|
|
94
|
+
> real API; the agent uses `lib/mock/<entity>.ts` for the demo dataset.
|
|
95
|
+
|
|
96
|
+
- **Mock**: `apps/web/lib/mock/<entity>.ts`
|
|
97
|
+
- **API contract** (when known): `<endpoint>` returns `<RowShape>`
|
|
98
|
+
- **State container**: `useTableState({ data, columns })`
|
|
99
|
+
|
|
100
|
+
## 10. Empty / loading / error
|
|
101
|
+
|
|
102
|
+
> Every list, detail, and action ships all three states. Filled in by the
|
|
103
|
+
> agent; engineer verifies the copy.
|
|
104
|
+
|
|
105
|
+
- **Loading**: skeleton (`<HubTableSkeleton />` or matched shape)
|
|
106
|
+
- **Empty**: copy + primary CTA to start the flow
|
|
107
|
+
- **Error**: copy + retry affordance + Ask Leo entry point
|
|
108
|
+
|
|
109
|
+
## 11. Keyboard map
|
|
110
|
+
|
|
111
|
+
> Every shortcut bound on this surface. The agent must declare these so the
|
|
112
|
+
> engineer can write a Playwright test against them.
|
|
113
|
+
|
|
114
|
+
| Action | Shortcut |
|
|
115
|
+
|--------|----------|
|
|
116
|
+
| Open Add view | `1..9` |
|
|
117
|
+
| Submit primary form | `Enter` |
|
|
118
|
+
| Cancel | `Esc` |
|
|
119
|
+
| Search | `⌘K` / `Ctrl+K` |
|
|
120
|
+
| Ask Leo | `⌘⌥K` / `Ctrl+Alt+K` |
|
|
121
|
+
| New record | `⌘⌥N` |
|
|
122
|
+
|
|
123
|
+
## 12. Deviations from principles
|
|
124
|
+
|
|
125
|
+
> Any P9–P20 principle the design intentionally breaks, and the one-sentence
|
|
126
|
+
> reason. P1–P8 cannot be deviated from. If this section has rows, the
|
|
127
|
+
> engineer must include them in the PR description.
|
|
128
|
+
|
|
129
|
+
| Principle | Reason |
|
|
130
|
+
|-----------|--------|
|
|
131
|
+
| P14 (density) | Mixed audience — added density toggle, default cozy |
|
|
132
|
+
|
|
133
|
+
## 13. Out of scope
|
|
134
|
+
|
|
135
|
+
> What this surface deliberately does **not** do. Helps the engineer decide
|
|
136
|
+
> what tickets *not* to file.
|
|
137
|
+
|
|
138
|
+
(example)
|
|
139
|
+
- Inline editing of student name (v2)
|
|
140
|
+
- Bulk message (lives on the list hub, not on the detail)
|
|
141
|
+
|
|
142
|
+
## 14. Open questions
|
|
143
|
+
|
|
144
|
+
> Things the brief could not answer. Engineer pings the designer or product.
|
|
145
|
+
|
|
146
|
+
- (example) Should the compliance badge link out to the source document or open in a side panel?
|
|
147
|
+
|
|
148
|
+
## 15. Designer-stack → engineering-stack port (delete if same stack)
|
|
149
|
+
|
|
150
|
+
> **Skip this section** if your designer prototype and your production app
|
|
151
|
+
> are on the same framework (both Vite, both Next.js).
|
|
152
|
+
>
|
|
153
|
+
> **Fill this in** if the designer prototyped on the **Vite scaffold**
|
|
154
|
+
> (`create-exxat-app`, the lightweight default) but the production app
|
|
155
|
+
> still runs on **Next.js**. The agent or engineer maps each Vite-specific
|
|
156
|
+
> import to its Next equivalent before merging the work into prod.
|
|
157
|
+
|
|
158
|
+
| Vite scaffold (designer) | Next.js prod (engineer) | Notes |
|
|
159
|
+
|---|---|---|
|
|
160
|
+
| `import { Link } from "@/lib/next-compat"` → `<Link to="…">` | `import Link from "next/link"` → `<Link href="…">` | Drop the shim re-export; rename `to` → `href` |
|
|
161
|
+
| `import { useNavigate } from "react-router-dom"` | `import { useRouter } from "next/navigation"` + `router.push(...)` | One-line swap |
|
|
162
|
+
| `import { useLocation } from "react-router-dom"` → `useLocation().pathname` | `import { usePathname } from "next/navigation"` | Direct equivalent |
|
|
163
|
+
| `import { useSearchParams } from "react-router-dom"` returns `[params, setParams]` | `import { useSearchParams } from "next/navigation"` returns `ReadonlyURLSearchParams` | Drop the destructure, accept readonly shape |
|
|
164
|
+
| `import { Navigate } from "react-router-dom"` (JSX redirect) | `import { redirect } from "next/navigation"` (function call) | Move from JSX to component body |
|
|
165
|
+
| `React.lazy(() => import(...))` + `<Suspense>` | `dynamic(() => import(...), { loading, ssr: false })` | Functionally equivalent — pick whichever the surrounding file already uses |
|
|
166
|
+
| `vite.config.ts` aliases | `next.config.mjs` `experimental.turbopack.resolveAlias` or `tsconfig.json` `paths` | Rare — most aliases live in `tsconfig.json` already |
|
|
167
|
+
| `index.html` `<meta>` tags + `<title>` | `app/layout.tsx` `metadata` export | Move static meta into the route's `metadata`; dynamic meta moves into `generateMetadata` |
|
|
168
|
+
| `document.cookie` reads in client components | `cookies()` from `next/headers` (server) | Most cases are client-only; only swap if the value must be SSR-rendered |
|
|
169
|
+
| `@fontsource-variable/inter` import in `main.tsx` | `Inter()` from `next/font/google` in `app/layout.tsx` | Both produce zero-CLS variable fonts; Next has the edge on hashed asset names |
|
|
170
|
+
|
|
171
|
+
The agent runs this map as a codemod — see
|
|
172
|
+
`packages/ui/template-vite/scripts/port-next-imports.mjs` (template-vite
|
|
173
|
+
internal use) for the inverse direction (Next → Vite, used during PR-2).
|
|
174
|
+
Engineers porting **Vite → Next** can copy that script and reverse the
|
|
175
|
+
regexes; the patterns are symmetric.
|
|
176
|
+
|
|
177
|
+
---
|
|
178
|
+
|
|
179
|
+
## How the engineer uses this file
|
|
180
|
+
|
|
181
|
+
1. Read sections 1–3 to understand intent.
|
|
182
|
+
2. Skim sections 4–7 to confirm the agent reused DS primitives + tokens (no surprises).
|
|
183
|
+
3. Run `npx --package=@exxatdesignux/ui exxat-ui audit <generated-file>.tsx` to validate the floor automatically.
|
|
184
|
+
4. Wire real data per section 9.
|
|
185
|
+
5. Verify section 10 states render with real API data (not just mocks).
|
|
186
|
+
6. Add section 11 shortcuts to the route's e2e test.
|
|
187
|
+
7. Surface section 12 deviations + section 14 open questions in the PR description.
|
|
188
|
+
|
|
189
|
+
If any section is missing or hand-wavy, the handoff is incomplete. Push it
|
|
190
|
+
back to the designer / agent before merging.
|
|
@@ -10,7 +10,7 @@ declare function useAppTheme(): {
|
|
|
10
10
|
brand: Brand;
|
|
11
11
|
setBrand: (b: Brand) => void;
|
|
12
12
|
/** The user's preference: "system" | "normal" | "high" | "windows" */
|
|
13
|
-
contrastPref: "
|
|
13
|
+
contrastPref: "normal" | "high" | "system" | "windows";
|
|
14
14
|
/** The resolved contrast mode actually applied to the DOM. */
|
|
15
15
|
contrast: ContrastMode;
|
|
16
16
|
/** Set the contrast preference. */
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@exxatdesignux/ui",
|
|
3
|
-
"version": "0.5.
|
|
3
|
+
"version": "0.5.12",
|
|
4
4
|
"description": "Exxat shared design system (components, hooks, tokens). Monorepo setup: clone repo then pnpm bootstrap at workspace root — see github.com/ExxatDesign/Exxat-DS-Workspace README.",
|
|
5
5
|
"license": "UNLICENSED",
|
|
6
6
|
"author": "Exxat Design",
|
|
@@ -97,7 +97,7 @@
|
|
|
97
97
|
"dist",
|
|
98
98
|
"src",
|
|
99
99
|
"bin",
|
|
100
|
-
"template",
|
|
100
|
+
"template-vite",
|
|
101
101
|
"consumer-extras",
|
|
102
102
|
"tokens"
|
|
103
103
|
],
|