@exxatdesignux/ui 0.5.11 → 0.5.13

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.
Files changed (477) hide show
  1. package/CHANGELOG.md +45 -0
  2. package/bin/cli.mjs +70 -1
  3. package/bin/init.mjs +18 -4
  4. package/bin/sync-extras.mjs +28 -4
  5. package/consumer-extras/README.md +41 -5
  6. package/consumer-extras/cursor-rules/exxat-accessibility.mdc +2 -1
  7. package/consumer-extras/cursor-rules/exxat-board-cards.mdc +5 -3
  8. package/consumer-extras/cursor-rules/exxat-breadcrumbs-no-back.mdc +1 -0
  9. package/consumer-extras/cursor-rules/exxat-card-vs-list-rows.mdc +1 -0
  10. package/consumer-extras/cursor-rules/exxat-centralized-list-dataset.mdc +4 -2
  11. package/consumer-extras/cursor-rules/exxat-collaboration-access.mdc +1 -0
  12. package/consumer-extras/cursor-rules/exxat-command-menu.mdc +3 -2
  13. package/consumer-extras/cursor-rules/exxat-data-tables.mdc +5 -3
  14. package/consumer-extras/cursor-rules/exxat-dedicated-search-surfaces.mdc +7 -0
  15. package/consumer-extras/cursor-rules/exxat-drawer-vs-dialog.mdc +2 -1
  16. package/consumer-extras/cursor-rules/exxat-ds-agents.mdc +1 -0
  17. package/consumer-extras/cursor-rules/exxat-fontawesome-icons.mdc +1 -0
  18. package/consumer-extras/cursor-rules/exxat-hub-supported-views.mdc +6 -4
  19. package/consumer-extras/cursor-rules/exxat-kbd-shortcuts.mdc +6 -5
  20. package/consumer-extras/cursor-rules/exxat-kpi-flat-band.mdc +1 -0
  21. package/consumer-extras/cursor-rules/exxat-kpi-max-four.mdc +1 -0
  22. package/consumer-extras/cursor-rules/exxat-kpi-trends.mdc +1 -0
  23. package/consumer-extras/cursor-rules/exxat-library-hub-header.mdc +2 -1
  24. package/consumer-extras/cursor-rules/exxat-list-page-connected-views.mdc +6 -2
  25. package/consumer-extras/cursor-rules/exxat-list-page-view-shells.mdc +2 -1
  26. package/consumer-extras/cursor-rules/exxat-mono-ids.mdc +2 -1
  27. package/consumer-extras/cursor-rules/exxat-nav-single-active.mdc +4 -3
  28. package/consumer-extras/cursor-rules/exxat-no-image-pixel-copy.mdc +25 -14
  29. package/consumer-extras/cursor-rules/exxat-no-slds-leakage.mdc +8 -2
  30. package/consumer-extras/cursor-rules/exxat-no-toast.mdc +1 -0
  31. package/consumer-extras/cursor-rules/exxat-no-vaul.mdc +2 -1
  32. package/consumer-extras/cursor-rules/exxat-page-header-actions.mdc +6 -4
  33. package/consumer-extras/cursor-rules/exxat-page-vs-drawer.mdc +2 -1
  34. package/consumer-extras/cursor-rules/exxat-person-identity-display.mdc +1 -0
  35. package/consumer-extras/cursor-rules/exxat-primary-nav-secondary-panel.mdc +2 -1
  36. package/consumer-extras/cursor-rules/exxat-reuse-before-custom.mdc +1 -0
  37. package/consumer-extras/cursor-rules/exxat-sidebar-shell.mdc +13 -7
  38. package/consumer-extras/cursor-rules/exxat-table-properties-drawer.mdc +5 -3
  39. package/consumer-extras/cursor-rules/exxat-table-row-preview.mdc +1 -0
  40. package/consumer-extras/cursor-rules/exxat-tabs-chrome.mdc +6 -4
  41. package/consumer-extras/cursor-rules/exxat-token-discipline.mdc +6 -0
  42. package/consumer-extras/cursor-rules/exxat-ux-discovery-protocol.mdc +28 -0
  43. package/consumer-extras/cursor-rules/exxat-ux-principles.mdc +1 -0
  44. package/consumer-extras/cursor-skills/exxat-ds-skill/SKILL.md +1 -1
  45. package/consumer-extras/cursor-skills/exxat-kpi-trends/SKILL.md +5 -3
  46. package/consumer-extras/patterns/command-menu-pattern.md +2 -2
  47. package/consumer-extras/patterns/consumer-upgrade-checklist.md +1 -1
  48. package/consumer-extras/patterns/jobs/README.md +1 -1
  49. package/consumer-extras/patterns/perf-memory-pattern.md +115 -150
  50. package/consumer-extras/scripts/dev-guard.mjs +156 -0
  51. package/consumer-extras/templates/README.md +23 -0
  52. package/consumer-extras/templates/handoff.md +190 -0
  53. package/package.json +2 -3
  54. package/{template → template-vite}/.claude/skills/exxat-ds-skill/SKILL.md +184 -23
  55. package/template-vite/.cursor/rules/exxat-accessibility.mdc +40 -0
  56. package/template-vite/.cursor/rules/exxat-board-cards.mdc +28 -0
  57. package/template-vite/.cursor/rules/exxat-breadcrumbs-no-back.mdc +22 -0
  58. package/template-vite/.cursor/rules/exxat-card-vs-list-rows.mdc +22 -0
  59. package/template-vite/.cursor/rules/exxat-centralized-list-dataset.mdc +46 -0
  60. package/template-vite/.cursor/rules/exxat-collaboration-access.mdc +33 -0
  61. package/{template → template-vite}/.cursor/rules/exxat-command-menu.mdc +5 -5
  62. package/template-vite/.cursor/rules/exxat-data-tables.mdc +47 -0
  63. package/template-vite/.cursor/rules/exxat-dedicated-search-surfaces.mdc +32 -0
  64. package/template-vite/.cursor/rules/exxat-drawer-vs-dialog.mdc +23 -0
  65. package/template-vite/.cursor/rules/exxat-ds-agents.mdc +87 -0
  66. package/template-vite/.cursor/rules/exxat-fontawesome-icons.mdc +32 -0
  67. package/template-vite/.cursor/rules/exxat-hub-supported-views.mdc +56 -0
  68. package/{template → template-vite}/.cursor/rules/exxat-kbd-shortcuts.mdc +1 -0
  69. package/template-vite/.cursor/rules/exxat-kpi-flat-band.mdc +29 -0
  70. package/template-vite/.cursor/rules/exxat-kpi-max-four.mdc +22 -0
  71. package/template-vite/.cursor/rules/exxat-kpi-trends.mdc +32 -0
  72. package/template-vite/.cursor/rules/exxat-library-hub-header.mdc +29 -0
  73. package/template-vite/.cursor/rules/exxat-list-page-connected-views.mdc +28 -0
  74. package/template-vite/.cursor/rules/exxat-list-page-view-shells.mdc +32 -0
  75. package/{template → template-vite}/.cursor/rules/exxat-mono-ids.mdc +1 -0
  76. package/template-vite/.cursor/rules/exxat-nav-single-active.mdc +32 -0
  77. package/template-vite/.cursor/rules/exxat-no-image-pixel-copy.mdc +46 -0
  78. package/template-vite/.cursor/rules/exxat-no-slds-leakage.mdc +84 -0
  79. package/{template → template-vite}/.cursor/rules/exxat-no-toast.mdc +2 -2
  80. package/template-vite/.cursor/rules/exxat-no-vaul.mdc +26 -0
  81. package/template-vite/.cursor/rules/exxat-page-header-actions.mdc +33 -0
  82. package/{template → template-vite}/.cursor/rules/exxat-page-vs-drawer.mdc +5 -3
  83. package/template-vite/.cursor/rules/exxat-person-identity-display.mdc +48 -0
  84. package/template-vite/.cursor/rules/exxat-primary-nav-secondary-panel.mdc +53 -0
  85. package/template-vite/.cursor/rules/exxat-reuse-before-custom.mdc +37 -0
  86. package/template-vite/.cursor/rules/exxat-sidebar-shell.mdc +41 -0
  87. package/template-vite/.cursor/rules/exxat-table-properties-drawer.mdc +79 -0
  88. package/template-vite/.cursor/rules/exxat-table-row-preview.mdc +25 -0
  89. package/template-vite/.cursor/rules/exxat-tabs-chrome.mdc +33 -0
  90. package/template-vite/.cursor/rules/exxat-token-discipline.mdc +109 -0
  91. package/template-vite/.cursor/rules/exxat-ux-discovery-protocol.mdc +202 -0
  92. package/template-vite/.cursor/rules/exxat-ux-principles.mdc +187 -0
  93. package/template-vite/.cursor/skills/exxat-accessibility/SKILL.md +282 -0
  94. package/template-vite/.cursor/skills/exxat-board-cards/SKILL.md +68 -0
  95. package/template-vite/.cursor/skills/exxat-card-vs-list-rows/SKILL.md +20 -0
  96. package/template-vite/.cursor/skills/exxat-centralized-list-dataset/SKILL.md +99 -0
  97. package/template-vite/.cursor/skills/exxat-collaboration-access/SKILL.md +35 -0
  98. package/template-vite/.cursor/skills/exxat-dedicated-search-surfaces/SKILL.md +45 -0
  99. package/template-vite/.cursor/skills/exxat-drawer-vs-dialog/SKILL.md +20 -0
  100. package/template-vite/.cursor/skills/exxat-ds-skill/SKILL.md +893 -0
  101. package/template-vite/.cursor/skills/exxat-ds-skill/references/accessibility.md +142 -0
  102. package/template-vite/.cursor/skills/exxat-ds-skill/references/coach-marks.md +169 -0
  103. package/template-vite/.cursor/skills/exxat-ds-skill/references/data-table-pattern.md +392 -0
  104. package/template-vite/.cursor/skills/exxat-fontawesome-icons/SKILL.md +31 -0
  105. package/template-vite/.cursor/skills/exxat-kpi-flat-band/SKILL.md +38 -0
  106. package/template-vite/.cursor/skills/exxat-kpi-max-four/SKILL.md +19 -0
  107. package/template-vite/.cursor/skills/exxat-kpi-trends/SKILL.md +29 -0
  108. package/template-vite/.cursor/skills/exxat-list-page-view-shells/SKILL.md +36 -0
  109. package/template-vite/.cursor/skills/exxat-mono-ids/SKILL.md +56 -0
  110. package/template-vite/.cursor/skills/exxat-primary-nav-secondary-panel/SKILL.md +49 -0
  111. package/template-vite/.cursor/skills/exxat-senior-ux/SKILL.md +198 -0
  112. package/template-vite/.cursor/skills/exxat-token-economy/SKILL.md +287 -0
  113. package/template-vite/.cursor/skills/exxat-ux-audit/SKILL.md +303 -0
  114. package/{template → template-vite}/components/ask-leo-sidebar.tsx +10 -8
  115. package/{template → template-vite}/components/command-menu.tsx +1 -1
  116. package/{template → template-vite}/components/data-views/library-folder-tree-branch.tsx +1 -1
  117. package/{template → template-vite}/components/dedicated-search-recents.tsx +1 -1
  118. package/{template → template-vite}/components/dedicated-search-url-composer.tsx +1 -1
  119. package/{template → template-vite}/components/exxat-product-logo.tsx +3 -3
  120. package/{template → template-vite}/components/library-client.tsx +1 -1
  121. package/{template → template-vite}/components/library-hub-client.tsx +2 -2
  122. package/{template → template-vite}/components/library-secondary-nav.tsx +2 -2
  123. package/{template → template-vite}/components/library-table.tsx +35 -27
  124. package/{template → template-vite}/components/new-library-item-form.tsx +1 -1
  125. package/{template → template-vite}/components/page-breadcrumb-trail.tsx +1 -1
  126. package/{template → template-vite}/components/settings-client.tsx +1 -1
  127. package/{template → template-vite}/components/sidebar/app-sidebar.tsx +2 -2
  128. package/{template → template-vite}/components/sidebar/nav-main.tsx +1 -1
  129. package/{template → template-vite}/components/sidebar/nav-user.tsx +1 -1
  130. package/{template → template-vite}/components/sidebar/secondary-nav.tsx +1 -1
  131. package/{template → template-vite}/components/system-banner-slot.tsx +1 -1
  132. package/{template → template-vite}/components/templates/discovery-hub-template.tsx +2 -2
  133. package/{template → template-vite}/components/templates/new-focus-template.tsx +1 -1
  134. package/{template → template-vite}/components/tokens-secondary-nav.tsx +2 -2
  135. package/{template → template-vite}/components/tokens-themes-client.tsx +1 -1
  136. package/{template → template-vite}/hooks/use-secondary-panel-hub-nav.ts +1 -1
  137. package/template-vite/index.html +49 -0
  138. package/template-vite/lib/next-compat.tsx +98 -0
  139. package/{template → template-vite}/package.json +15 -27
  140. package/template-vite/scripts/port-next-imports.mjs +70 -0
  141. package/template-vite/src/App.tsx +103 -0
  142. package/template-vite/src/main.tsx +50 -0
  143. package/{template/app/(app)/error.tsx → template-vite/src/pages/_error.tsx} +12 -24
  144. package/{template/app/(app)/loading.tsx → template-vite/src/pages/_loading.tsx} +4 -2
  145. package/template-vite/src/pages/_not-found.tsx +17 -0
  146. package/template-vite/src/pages/dashboard.tsx +48 -0
  147. package/{template/app/(app)/help/page.tsx → template-vite/src/pages/help.tsx} +3 -2
  148. package/{template/app/(app)/library/layout.tsx → template-vite/src/pages/library/_layout.tsx} +18 -16
  149. package/{template/app/(app)/library/all/page.tsx → template-vite/src/pages/library/all.tsx} +1 -1
  150. package/{template/app/(app)/library/new/page.tsx → template-vite/src/pages/library/new.tsx} +12 -18
  151. package/template-vite/src/routes.tsx +72 -0
  152. package/template-vite/src/styles/globals.css +25 -0
  153. package/{template → template-vite}/tsconfig.json +5 -14
  154. package/template-vite/vite.config.ts +52 -0
  155. package/consumer-extras/cursor-rules/exxat-dashboard-view-charts.mdc +0 -53
  156. package/template/.agents/skills/shadcn/SKILL.md +0 -242
  157. package/template/.agents/skills/shadcn/agents/openai.yml +0 -5
  158. package/template/.agents/skills/shadcn/assets/shadcn-small.png +0 -0
  159. package/template/.agents/skills/shadcn/assets/shadcn.png +0 -0
  160. package/template/.agents/skills/shadcn/cli.md +0 -257
  161. package/template/.agents/skills/shadcn/customization.md +0 -202
  162. package/template/.agents/skills/shadcn/evals/evals.json +0 -47
  163. package/template/.agents/skills/shadcn/mcp.md +0 -94
  164. package/template/.agents/skills/shadcn/rules/base-vs-radix.md +0 -306
  165. package/template/.agents/skills/shadcn/rules/composition.md +0 -195
  166. package/template/.agents/skills/shadcn/rules/forms.md +0 -192
  167. package/template/.agents/skills/shadcn/rules/icons.md +0 -101
  168. package/template/.agents/skills/shadcn/rules/styling.md +0 -162
  169. package/template/.cursor/rules/exxat-accessibility.mdc +0 -33
  170. package/template/.cursor/rules/exxat-data-tables.mdc +0 -32
  171. package/template/.cursor/rules/exxat-ds-agents.mdc +0 -26
  172. package/template/.cursor/rules/exxat-list-page-connected-views.mdc +0 -16
  173. package/template/.cursor/rules/exxat-table-properties-drawer.mdc +0 -40
  174. package/template/.nvmrc +0 -1
  175. package/template/.prettierignore +0 -7
  176. package/template/Logo/Exxat_Prism.svg +0 -39
  177. package/template/Logo/Exxat_one.svg +0 -36
  178. package/template/app/(app)/dashboard/loading.tsx +0 -18
  179. package/template/app/(app)/dashboard/page.tsx +0 -36
  180. package/template/app/(app)/layout.tsx +0 -77
  181. package/template/app/global-error.tsx +0 -63
  182. package/template/app/globals.css +0 -20
  183. package/template/app/layout.tsx +0 -133
  184. package/template/app/page.tsx +0 -9
  185. package/template/docs/HANDBOOK.md +0 -187
  186. package/template/docs/blueprints/README.md +0 -86
  187. package/template/docs/blueprints/_template.md +0 -91
  188. package/template/docs/blueprints/board-card.md +0 -123
  189. package/template/docs/blueprints/data-table.md +0 -139
  190. package/template/docs/blueprints/key-metrics.md +0 -128
  191. package/template/docs/blueprints/list-page-template.md +0 -123
  192. package/template/docs/blueprints/page-header.md +0 -130
  193. package/template/docs/card-vs-rows-pattern.md +0 -36
  194. package/template/docs/collaboration-access-pattern.md +0 -116
  195. package/template/docs/command-menu-pattern.md +0 -45
  196. package/template/docs/component-selection-guide.md +0 -224
  197. package/template/docs/components-audit-2026-05.md +0 -158
  198. package/template/docs/consumer-upgrade-checklist.md +0 -52
  199. package/template/docs/data-views-pattern.md +0 -185
  200. package/template/docs/drawer-vs-dialog-pattern.md +0 -50
  201. package/template/docs/glossary.md +0 -59
  202. package/template/docs/hub-supported-views-pattern.md +0 -53
  203. package/template/docs/jobs/README.md +0 -59
  204. package/template/docs/jobs/record-detail.md +0 -177
  205. package/template/docs/kpi-flat-band-pattern.md +0 -57
  206. package/template/docs/kpi-strip-max-four-pattern.md +0 -30
  207. package/template/docs/kpi-trend-pattern.md +0 -58
  208. package/template/docs/large-dataset-strategy.md +0 -155
  209. package/template/docs/library-hub-header-pattern.md +0 -25
  210. package/template/docs/migrations/0001-brand-deep-alias-stabilization.md +0 -95
  211. package/template/docs/migrations/0002-exxat-token-namespace.md +0 -154
  212. package/template/docs/migrations/0003-globals-css-canonical.md +0 -110
  213. package/template/docs/migrations/README.md +0 -100
  214. package/template/docs/migrations/_template.md +0 -64
  215. package/template/docs/modern-saas-patterns.md +0 -165
  216. package/template/docs/perf-memory-pattern.md +0 -206
  217. package/template/docs/reference-implementations.md +0 -153
  218. package/template/docs/shell-surface-elevation-pattern.md +0 -52
  219. package/template/docs/token-taxonomy.md +0 -416
  220. package/template/docs/voice-and-tone.md +0 -262
  221. package/template/ecosystem.config.cjs +0 -32
  222. package/template/next.config.mjs +0 -216
  223. package/template/postcss.config.mjs +0 -8
  224. package/template/public/favicon/favicon.ico +0 -0
  225. package/template/tests/setup.ts +0 -26
  226. package/template/vitest.config.ts +0 -18
  227. /package/{template → template-vite}/.cursor/rules/exxat-dashboard-view-charts.mdc +0 -0
  228. /package/{template → template-vite}/.prettierrc +0 -0
  229. /package/{template → template-vite}/AGENTS.md +0 -0
  230. /package/{template → template-vite}/README.md +0 -0
  231. /package/{template → template-vite}/components/.gitkeep +0 -0
  232. /package/{template → template-vite}/components/ask-leo-composer.tsx +0 -0
  233. /package/{template → template-vite}/components/brand-color-picker.tsx +0 -0
  234. /package/{template → template-vite}/components/chart-area-interactive.tsx +0 -0
  235. /package/{template → template-vite}/components/charts-overview.tsx +0 -0
  236. /package/{template → template-vite}/components/collaboration-access-flow.tsx +0 -0
  237. /package/{template → template-vite}/components/columns-client.tsx +0 -0
  238. /package/{template → template-vite}/components/columns-showcase.tsx +0 -0
  239. /package/{template → template-vite}/components/dashboard-promo-banner.tsx +0 -0
  240. /package/{template → template-vite}/components/dashboard-quota-progress-card.tsx +0 -0
  241. /package/{template → template-vite}/components/dashboard-report-charts.tsx +0 -0
  242. /package/{template → template-vite}/components/dashboard-section-heading.tsx +0 -0
  243. /package/{template → template-vite}/components/dashboard-tabs.tsx +0 -0
  244. /package/{template → template-vite}/components/data-table/filter-date-calendar.tsx +0 -0
  245. /package/{template → template-vite}/components/data-table/filter-text-value-input.tsx +0 -0
  246. /package/{template → template-vite}/components/data-table/index.tsx +0 -0
  247. /package/{template → template-vite}/components/data-table/pagination.tsx +0 -0
  248. /package/{template → template-vite}/components/data-table/types.ts +0 -0
  249. /package/{template → template-vite}/components/data-table/use-table-state.test.ts +0 -0
  250. /package/{template → template-vite}/components/data-table/use-table-state.ts +0 -0
  251. /package/{template → template-vite}/components/data-views/board-card-primitives.tsx +0 -0
  252. /package/{template → template-vite}/components/data-views/data-row-list.tsx +0 -0
  253. /package/{template → template-vite}/components/data-views/finder-panel-view.tsx +0 -0
  254. /package/{template → template-vite}/components/data-views/folder-grid-view.tsx +0 -0
  255. /package/{template → template-vite}/components/data-views/hub-table.tsx +0 -0
  256. /package/{template → template-vite}/components/data-views/index.ts +0 -0
  257. /package/{template → template-vite}/components/data-views/list-page-board-card.tsx +0 -0
  258. /package/{template → template-vite}/components/data-views/list-page-board-template.tsx +0 -0
  259. /package/{template → template-vite}/components/data-views/list-page-connected-view-body.tsx +0 -0
  260. /package/{template → template-vite}/components/data-views/list-page-split-details-placeholder.tsx +0 -0
  261. /package/{template → template-vite}/components/data-views/list-page-split-hub-chrome.tsx +0 -0
  262. /package/{template → template-vite}/components/data-views/list-page-split-hub-tokens.ts +0 -0
  263. /package/{template → template-vite}/components/data-views/list-page-tree-column-header.tsx +0 -0
  264. /package/{template → template-vite}/components/data-views/list-page-tree-panel-shell.tsx +0 -0
  265. /package/{template → template-vite}/components/data-views/list-page-view-frame.tsx +0 -0
  266. /package/{template → template-vite}/components/data-views/os-folder-glyph.tsx +0 -0
  267. /package/{template → template-vite}/components/data-views/outline-tree-menu.tsx +0 -0
  268. /package/{template → template-vite}/components/data-views/table-cells.tsx +0 -0
  269. /package/{template → template-vite}/components/dev-chunk-load-recovery.tsx +0 -0
  270. /package/{template → template-vite}/components/export-drawer.test.tsx +0 -0
  271. /package/{template → template-vite}/components/export-drawer.tsx +0 -0
  272. /package/{template → template-vite}/components/folder-details-shell.tsx +0 -0
  273. /package/{template → template-vite}/components/form-layout-01.tsx +0 -0
  274. /package/{template → template-vite}/components/hub-tree-panel-view.tsx +0 -0
  275. /package/{template → template-vite}/components/invite-collaborators-drawer.tsx +0 -0
  276. /package/{template → template-vite}/components/key-metrics-ask-leo-bridge.tsx +0 -0
  277. /package/{template → template-vite}/components/key-metrics.tsx +0 -0
  278. /package/{template → template-vite}/components/leo-insight-indicator.tsx +0 -0
  279. /package/{template → template-vite}/components/leo-typing-dots.tsx +0 -0
  280. /package/{template → template-vite}/components/library-board-view.tsx +0 -0
  281. /package/{template → template-vite}/components/library-dashboard-charts.tsx +0 -0
  282. /package/{template → template-vite}/components/library-favorite-button.tsx +0 -0
  283. /package/{template → template-vite}/components/library-new-folder-sheet.tsx +0 -0
  284. /package/{template → template-vite}/components/library-os-folder-view.tsx +0 -0
  285. /package/{template → template-vite}/components/library-page-header.tsx +0 -0
  286. /package/{template → template-vite}/components/library-panel-activator.tsx +0 -0
  287. /package/{template → template-vite}/components/list-hub-status-badge.tsx +0 -0
  288. /package/{template → template-vite}/components/list-page-dashboard-charts.tsx +0 -0
  289. /package/{template → template-vite}/components/onboarding/getting-started.tsx +0 -0
  290. /package/{template → template-vite}/components/onboarding/index.ts +0 -0
  291. /package/{template → template-vite}/components/onboarding/onboarding-01.tsx +0 -0
  292. /package/{template → template-vite}/components/onboarding/onboarding-02.tsx +0 -0
  293. /package/{template → template-vite}/components/onboarding/onboarding-03.tsx +0 -0
  294. /package/{template → template-vite}/components/onboarding/onboarding-04.tsx +0 -0
  295. /package/{template → template-vite}/components/page-header.tsx +0 -0
  296. /package/{template → template-vite}/components/product-switcher.tsx +0 -0
  297. /package/{template → template-vite}/components/product-wordmark.tsx +0 -0
  298. /package/{template → template-vite}/components/settings-appearance-card.tsx +0 -0
  299. /package/{template → template-vite}/components/settings-form-row.tsx +0 -0
  300. /package/{template → template-vite}/components/sidebar/app-sidebar-dynamic.tsx +0 -0
  301. /package/{template → template-vite}/components/sidebar/index.ts +0 -0
  302. /package/{template → template-vite}/components/sidebar/nav-documents.tsx +0 -0
  303. /package/{template → template-vite}/components/sidebar/nav-secondary.tsx +0 -0
  304. /package/{template → template-vite}/components/sidebar/secondary-panel.tsx +0 -0
  305. /package/{template → template-vite}/components/sidebar/sidebar-auto-collapse.tsx +0 -0
  306. /package/{template → template-vite}/components/sidebar/sidebar-auto-open.tsx +0 -0
  307. /package/{template → template-vite}/components/sidebar/sidebar-shell.tsx +0 -0
  308. /package/{template → template-vite}/components/site-header.tsx +0 -0
  309. /package/{template → template-vite}/components/table-properties/column-row.tsx +0 -0
  310. /package/{template → template-vite}/components/table-properties/draggable-list.ts +0 -0
  311. /package/{template → template-vite}/components/table-properties/drawer-button.tsx +0 -0
  312. /package/{template → template-vite}/components/table-properties/drawer.tsx +0 -0
  313. /package/{template → template-vite}/components/table-properties/filter-card.tsx +0 -0
  314. /package/{template → template-vite}/components/table-properties/index.ts +0 -0
  315. /package/{template → template-vite}/components/table-properties/sort-card.tsx +0 -0
  316. /package/{template → template-vite}/components/table-properties/types.ts +0 -0
  317. /package/{template → template-vite}/components/task-list-panel.tsx +0 -0
  318. /package/{template → template-vite}/components/task-priority-badge.tsx +0 -0
  319. /package/{template → template-vite}/components/templates/dedicated-search-landing-template.tsx +0 -0
  320. /package/{template → template-vite}/components/templates/dedicated-search-results-template.tsx +0 -0
  321. /package/{template → template-vite}/components/templates/list-page.tsx +0 -0
  322. /package/{template → template-vite}/components/templates/nested-secondary-panel-shell.tsx +0 -0
  323. /package/{template → template-vite}/components/templates/primary-page-template.tsx +0 -0
  324. /package/{template → template-vite}/components/templates/secondary-panel-hub-template.tsx +0 -0
  325. /package/{template → template-vite}/components/theme-color-sync.tsx +0 -0
  326. /package/{template → template-vite}/components/theme-provider.tsx +0 -0
  327. /package/{template → template-vite}/components/tinted-icon-disc.tsx +0 -0
  328. /package/{template → template-vite}/components/tokens-hub-auxiliary-views.tsx +0 -0
  329. /package/{template → template-vite}/components/tokens-themes-section.tsx +0 -0
  330. /package/{template → template-vite}/components/ui/accordion.tsx +0 -0
  331. /package/{template → template-vite}/components/ui/ai-thinking-surface.tsx +0 -0
  332. /package/{template → template-vite}/components/ui/alert-dialog.tsx +0 -0
  333. /package/{template → template-vite}/components/ui/avatar.tsx +0 -0
  334. /package/{template → template-vite}/components/ui/badge.tsx +0 -0
  335. /package/{template → template-vite}/components/ui/banner.tsx +0 -0
  336. /package/{template → template-vite}/components/ui/breadcrumb.tsx +0 -0
  337. /package/{template → template-vite}/components/ui/button.tsx +0 -0
  338. /package/{template → template-vite}/components/ui/calendar.tsx +0 -0
  339. /package/{template → template-vite}/components/ui/card.tsx +0 -0
  340. /package/{template → template-vite}/components/ui/chart.tsx +0 -0
  341. /package/{template → template-vite}/components/ui/checkbox.tsx +0 -0
  342. /package/{template → template-vite}/components/ui/coach-mark.tsx +0 -0
  343. /package/{template → template-vite}/components/ui/collapsible.tsx +0 -0
  344. /package/{template → template-vite}/components/ui/command.tsx +0 -0
  345. /package/{template → template-vite}/components/ui/context-menu.tsx +0 -0
  346. /package/{template → template-vite}/components/ui/date-picker-field.tsx +0 -0
  347. /package/{template → template-vite}/components/ui/dialog.tsx +0 -0
  348. /package/{template → template-vite}/components/ui/dot-pattern.tsx +0 -0
  349. /package/{template → template-vite}/components/ui/drag-handle-grip.tsx +0 -0
  350. /package/{template → template-vite}/components/ui/dropdown-menu.tsx +0 -0
  351. /package/{template → template-vite}/components/ui/field.tsx +0 -0
  352. /package/{template → template-vite}/components/ui/form.tsx +0 -0
  353. /package/{template → template-vite}/components/ui/hover-card.tsx +0 -0
  354. /package/{template → template-vite}/components/ui/input-group.tsx +0 -0
  355. /package/{template → template-vite}/components/ui/input-mask.tsx +0 -0
  356. /package/{template → template-vite}/components/ui/input.tsx +0 -0
  357. /package/{template → template-vite}/components/ui/kbd.tsx +0 -0
  358. /package/{template → template-vite}/components/ui/label.tsx +0 -0
  359. /package/{template → template-vite}/components/ui/leo-icon.tsx +0 -0
  360. /package/{template → template-vite}/components/ui/payment-card-fields.tsx +0 -0
  361. /package/{template → template-vite}/components/ui/popover.tsx +0 -0
  362. /package/{template → template-vite}/components/ui/radio-group.tsx +0 -0
  363. /package/{template → template-vite}/components/ui/resizable.tsx +0 -0
  364. /package/{template → template-vite}/components/ui/scroll-area.tsx +0 -0
  365. /package/{template → template-vite}/components/ui/select.tsx +0 -0
  366. /package/{template → template-vite}/components/ui/selection-tile-grid.tsx +0 -0
  367. /package/{template → template-vite}/components/ui/separator.tsx +0 -0
  368. /package/{template → template-vite}/components/ui/sheet.tsx +0 -0
  369. /package/{template → template-vite}/components/ui/sidebar.tsx +0 -0
  370. /package/{template → template-vite}/components/ui/skeleton.tsx +0 -0
  371. /package/{template → template-vite}/components/ui/slider.tsx +0 -0
  372. /package/{template → template-vite}/components/ui/sonner.tsx +0 -0
  373. /package/{template → template-vite}/components/ui/status-badge.tsx +0 -0
  374. /package/{template → template-vite}/components/ui/table.tsx +0 -0
  375. /package/{template → template-vite}/components/ui/tabs.tsx +0 -0
  376. /package/{template → template-vite}/components/ui/textarea.tsx +0 -0
  377. /package/{template → template-vite}/components/ui/tip.tsx +0 -0
  378. /package/{template → template-vite}/components/ui/toggle-group.tsx +0 -0
  379. /package/{template → template-vite}/components/ui/toggle-switch.tsx +0 -0
  380. /package/{template → template-vite}/components/ui/toggle.tsx +0 -0
  381. /package/{template → template-vite}/components/ui/tooltip.tsx +0 -0
  382. /package/{template → template-vite}/components/ui/view-segmented-control.tsx +0 -0
  383. /package/{template → template-vite}/components.json +0 -0
  384. /package/{template → template-vite}/contexts/chart-variant-context.tsx +0 -0
  385. /package/{template → template-vite}/contexts/command-menu-context.tsx +0 -0
  386. /package/{template → template-vite}/contexts/dashboard-view-context.tsx +0 -0
  387. /package/{template → template-vite}/contexts/product-context.tsx +0 -0
  388. /package/{template → template-vite}/contexts/system-banner-context.tsx +0 -0
  389. /package/{template → template-vite}/eslint.config.mjs +0 -0
  390. /package/{template → template-vite}/fontawesome-subset.manifest.json +0 -0
  391. /package/{template → template-vite}/hooks/.gitkeep +0 -0
  392. /package/{template → template-vite}/hooks/use-app-theme.ts +0 -0
  393. /package/{template → template-vite}/hooks/use-coach-mark.ts +0 -0
  394. /package/{template → template-vite}/hooks/use-location-hash.ts +0 -0
  395. /package/{template → template-vite}/hooks/use-mobile.ts +0 -0
  396. /package/{template → template-vite}/hooks/use-mod-key-label.ts +0 -0
  397. /package/{template → template-vite}/hooks/use-sidebar-reflow-zoom.ts +0 -0
  398. /package/{template → template-vite}/lib/.gitkeep +0 -0
  399. /package/{template → template-vite}/lib/ask-leo-route-context.ts +0 -0
  400. /package/{template → template-vite}/lib/chart-keyboard-selection.test.ts +0 -0
  401. /package/{template → template-vite}/lib/chart-keyboard-selection.ts +0 -0
  402. /package/{template → template-vite}/lib/chart-line-dash.ts +0 -0
  403. /package/{template → template-vite}/lib/chunk-load-error.ts +0 -0
  404. /package/{template → template-vite}/lib/coach-mark-registry.ts +0 -0
  405. /package/{template → template-vite}/lib/collaborator-access.ts +0 -0
  406. /package/{template → template-vite}/lib/command-menu-config.ts +0 -0
  407. /package/{template → template-vite}/lib/command-menu-search-data.ts +0 -0
  408. /package/{template → template-vite}/lib/conditional-rule-match.ts +0 -0
  409. /package/{template → template-vite}/lib/dashboard-customize-coach-mark.ts +0 -0
  410. /package/{template → template-vite}/lib/dashboard-layout-merge.ts +0 -0
  411. /package/{template → template-vite}/lib/data-list-display-options.ts +0 -0
  412. /package/{template → template-vite}/lib/data-list-persistence.ts +0 -0
  413. /package/{template → template-vite}/lib/data-list-view-registry.ts +0 -0
  414. /package/{template → template-vite}/lib/data-list-view-surface.ts +0 -0
  415. /package/{template → template-vite}/lib/data-list-view.ts +0 -0
  416. /package/{template → template-vite}/lib/data-view-dashboard-storage.ts +0 -0
  417. /package/{template → template-vite}/lib/date-filter.ts +0 -0
  418. /package/{template → template-vite}/lib/dedicated-search-recents.ts +0 -0
  419. /package/{template → template-vite}/lib/dedicated-search-url.ts +0 -0
  420. /package/{template → template-vite}/lib/dev-log.test.ts +0 -0
  421. /package/{template → template-vite}/lib/dev-log.ts +0 -0
  422. /package/{template → template-vite}/lib/discovery-hub.ts +0 -0
  423. /package/{template → template-vite}/lib/editable-target.ts +0 -0
  424. /package/{template → template-vite}/lib/exxat-palette.json +0 -0
  425. /package/{template → template-vite}/lib/exxat-palette.ts +0 -0
  426. /package/{template → template-vite}/lib/floating-sheet-panel.ts +0 -0
  427. /package/{template → template-vite}/lib/full-hub-supported-views.ts +0 -0
  428. /package/{template → template-vite}/lib/hub-connected-view-renderers.ts +0 -0
  429. /package/{template → template-vite}/lib/initials-from-name.ts +0 -0
  430. /package/{template → template-vite}/lib/library-authoring.ts +0 -0
  431. /package/{template → template-vite}/lib/library-dedicated-search.ts +0 -0
  432. /package/{template → template-vite}/lib/library-hub-search.ts +0 -0
  433. /package/{template → template-vite}/lib/library-nav.ts +0 -0
  434. /package/{template → template-vite}/lib/library-recent-searches.ts +0 -0
  435. /package/{template → template-vite}/lib/library-supported-views.ts +0 -0
  436. /package/{template → template-vite}/lib/list-hub-supported-views.ts +0 -0
  437. /package/{template → template-vite}/lib/list-page-table-properties.ts +0 -0
  438. /package/{template → template-vite}/lib/list-status-badges.ts +0 -0
  439. /package/{template → template-vite}/lib/logo-dev.ts +0 -0
  440. /package/{template → template-vite}/lib/mailto.ts +0 -0
  441. /package/{template → template-vite}/lib/mock/dashboard.ts +0 -0
  442. /package/{template → template-vite}/lib/mock/library-folders.ts +0 -0
  443. /package/{template → template-vite}/lib/mock/library-header-collaborators.ts +0 -0
  444. /package/{template → template-vite}/lib/mock/library-inspector.ts +0 -0
  445. /package/{template → template-vite}/lib/mock/library-kpi.ts +0 -0
  446. /package/{template → template-vite}/lib/mock/library.ts +0 -0
  447. /package/{template → template-vite}/lib/mock/navigation.tsx +0 -0
  448. /package/{template → template-vite}/lib/motion-ui.ts +0 -0
  449. /package/{template → template-vite}/lib/product-brand.ts +0 -0
  450. /package/{template → template-vite}/lib/raf-throttle.ts +0 -0
  451. /package/{template → template-vite}/lib/row-height.ts +0 -0
  452. /package/{template → template-vite}/lib/sidebar-state-cookie.ts +0 -0
  453. /package/{template → template-vite}/lib/stock-portrait.ts +0 -0
  454. /package/{template → template-vite}/lib/table-state-lifecycle.ts +0 -0
  455. /package/{template → template-vite}/lib/utils.test.ts +0 -0
  456. /package/{template → template-vite}/lib/utils.ts +0 -0
  457. /package/{template → template-vite}/public/.gitkeep +0 -0
  458. /package/{template → template-vite}/public/Illustration/Rotation.svg +0 -0
  459. /package/{template → template-vite}/public/avatars/user.svg +0 -0
  460. /package/{template/public → template-vite/public/favicon}/favicon.ico +0 -0
  461. /package/{template/app → template-vite/public}/favicon.ico +0 -0
  462. /package/{template → template-vite}/public/folders/icons8-folder-windows-11.svg +0 -0
  463. /package/{template → template-vite}/public/logos/exxat-one.svg +0 -0
  464. /package/{template → template-vite}/public/logos/exxat-prism.svg +0 -0
  465. /package/{template → template-vite}/public/mock-schools/emory.svg +0 -0
  466. /package/{template → template-vite}/public/mock-schools/rush.svg +0 -0
  467. /package/{template → template-vite}/scripts/fontawesome-subset-audit.mjs +0 -0
  468. /package/{template → template-vite}/scripts/pm2-startup-macos.sh +0 -0
  469. /package/{template → template-vite}/skills-lock.json +0 -0
  470. /package/{template/app/(app)/columns/page.tsx → template-vite/src/pages/columns.tsx} +0 -0
  471. /package/{template/app/(app)/library/find/page.tsx → template-vite/src/pages/library/find.tsx} +0 -0
  472. /package/{template/app/(app)/library/page.tsx → template-vite/src/pages/library/index.tsx} +0 -0
  473. /package/{template/app/(app)/library/list/page.tsx → template-vite/src/pages/library/list.tsx} +0 -0
  474. /package/{template/app/(app)/settings/page.tsx → template-vite/src/pages/settings.tsx} +0 -0
  475. /package/{template/app/(app)/tokens-themes/page.tsx → template-vite/src/pages/tokens-themes.tsx} +0 -0
  476. /package/{template → template-vite}/stores/app-store.ts +0 -0
  477. /package/{template → template-vite}/types/react-payment-inputs.d.ts +0 -0
@@ -0,0 +1,303 @@
1
+ ---
2
+ name: exxat-ux-audit
3
+ description: >-
4
+ Audit an EXISTING Exxat DS surface (route, file, component, customer-app
5
+ path, or screenshot) against the senior-UX principles (P1–P20), modern SaaS
6
+ patterns (M1–M12), and binding DS rules. Produces a structured findings
7
+ report with Blocker / Issue / Nit severity, code citations, and a fix plan
8
+ — and offers to auto-apply text-only Blocker fixes. Load when the user asks
9
+ "audit X", "review the X page", "is this following DS?", "what's wrong with
10
+ this screen", "do a UX review", or pastes a route URL with a problem.
11
+ user-invocable: true
12
+ ---
13
+
14
+ # Exxat DS — UX audit (review existing design)
15
+
16
+ Companion to [`exxat-senior-ux/SKILL.md`](../exxat-senior-ux/SKILL.md). Where
17
+ senior-UX is **forward-looking** (design before code), this skill is
18
+ **backward-looking** (grade what already exists).
19
+
20
+ ## When to load this skill (not senior-UX)
21
+
22
+ | Cue | Use this |
23
+ |-----|----------|
24
+ | "audit `/students/[id]`" / "review this page" / "what's wrong with X" | ✓ |
25
+ | "is this following the DS rules?" / "does this match Library?" | ✓ |
26
+ | User pastes a route URL with a symptom ("duplicate breadcrumb here") | ✓ |
27
+ | "find all the issues on the placements detail" | ✓ |
28
+ | PR review of a hub / detail / wizard already in code | ✓ |
29
+ | **"design a new X"** / "build a settings page" | ✗ — use `exxat-senior-ux` |
30
+
31
+ If both apply (e.g. "audit and rebuild"), do the audit first, then switch.
32
+
33
+ ## The audit protocol (4 phases)
34
+
35
+ ### 1. Locate — find the surface
36
+
37
+ Accept any of:
38
+
39
+ - **Route path:** `/students/[id]` → resolve to `app/(app)/students/[id]/page.tsx` and walk its imported client / component tree.
40
+ - **File path:** `components/student-details.tsx` (relative or absolute, monorepo OR customer app like `../test-9/...`).
41
+ - **Component name:** `StudentDetails` → grep for the export.
42
+ - **Screenshot:** extract IA from the image (per `exxat-no-image-pixel-copy.mdc`), then run the audit against the rendered source if available; otherwise report against the IA alone.
43
+
44
+ State the resolved entry point in the report so the user can verify scope.
45
+
46
+ ### 2. Grade — run the 10-dimension pass
47
+
48
+ Walk all ten in order. Each dimension has concrete grep / Read signals listed
49
+ in §"Grep cheatsheet" below.
50
+
51
+ | # | Dimension | Source of truth |
52
+ |---|-----------|-----------------|
53
+ | 1 | **Navigation integrity** | P1, P2 + `exxat-breadcrumbs-no-back.mdc` |
54
+ | 2 | **Action hierarchy** | P3 + `exxat-page-header-actions.mdc` |
55
+ | 3 | **States (empty / error / loading)** | P5 + M8, M9 |
56
+ | 4 | **Keyboard + a11y** | P6, P7 + `exxat-accessibility.mdc`, `exxat-kbd-shortcuts.mdc` |
57
+ | 5 | **DS composition (no forks)** | P8 + `exxat-reuse-before-custom.mdc`, `exxat-data-tables.mdc`, `exxat-tabs-chrome.mdc`, `exxat-no-vaul.mdc`, `exxat-no-toast.mdc` |
58
+ | 6 | **Modern pattern adherence** | M1–M12 (`modern-saas-patterns.md`) |
59
+ | 7 | **Voice & tone** | `docs/voice-and-tone.md` + P9 |
60
+ | 8 | **Job alignment (IA shape)** | The relevant `docs/jobs/*.md` |
61
+ | 9 | **Token + SLDS discipline** | `exxat-token-discipline.mdc`, `exxat-no-slds-leakage.mdc`, `exxat-no-hex-color` lint rule |
62
+ | 10 | **Hub-specific (only if a hub)** | `exxat-data-tables.mdc`, `exxat-hub-supported-views.mdc`, `exxat-centralized-list-dataset.mdc`, `exxat-list-page-connected-views.mdc` |
63
+
64
+ ### 3. Cite — every finding points at code
65
+
66
+ For each finding, capture:
67
+
68
+ - **Code reference** — file path + line numbers using the CODE REFERENCES
69
+ block format from the editor (see citing_code rules).
70
+ - **Principle / pattern / rule** — `(P1)` or `(M4)` or `(exxat-no-toast.mdc)`.
71
+ - **Why it matters** — one sentence in plain language.
72
+ - **Fix** — concrete suggestion. For Blockers, the exact edit if possible.
73
+
74
+ **Never** report a finding without a code citation or, for screenshots, a
75
+ specific element of the IA. Vague findings ("status is unclear") are useless.
76
+
77
+ ### 4. Report — markdown, in chat, in this exact shape
78
+
79
+ ```
80
+ # UX audit: <entry point>
81
+
82
+ ## Summary
83
+ **Status:** N blockers · N issues · N nits
84
+ **Job match:** <doc name> — ~X% alignment.
85
+ **Scope:** <files walked>
86
+
87
+ ## Blockers (P1–P8 violations — fix before shipping)
88
+ ### B1. <Title> (P<x>)
89
+ - **Where:** `<file>:<lines>`
90
+ - **What:** <one-sentence symptom>
91
+ - **Why:** <one-sentence rationale>
92
+ - **Fix:** <concrete edit>
93
+
94
+ ## Issues (P9–P20 / Mx violations without stated reason)
95
+ ### I1. <Title> (P<x> | M<x> | exxat-<rule>.mdc)
96
+ - **Where:** ...
97
+ - **What:** ...
98
+ - **Fix:** ...
99
+
100
+ ## Nits (preferences / minor modern-anti-pattern signals)
101
+ ### N1. <Title>
102
+ - ...
103
+
104
+ ## What's working
105
+ - <Positive finding with citation>
106
+ - ...
107
+
108
+ ## Fix plan
109
+ 1. <Highest-impact Blocker fix>
110
+ 2. ...
111
+ N. <Lowest-priority Nit>
112
+
113
+ ## Next action
114
+ > Want me to apply the text-only Blocker fixes (B1, B2) now? Issues and Nits
115
+ > I'll leave for you to review.
116
+ ```
117
+
118
+ Always close with the **Next action** line so the user has one click forward.
119
+
120
+ ## Severity rubric — read this before you label anything
121
+
122
+ ### Blocker (B) — violates P1–P8 (always-follow)
123
+ Anything that ships as a bug. Examples:
124
+ - Duplicate way-back (breadcrumb + "Back to" button) — **P1**
125
+ - Record name as breadcrumb leaf + `PageHeader.title` + body `<h1>` — **P2**
126
+ - Two filled CTAs in the header — **P3**
127
+ - Missing `DialogTitle` / `SheetTitle` (even `sr-only`) — **P7**
128
+ - Contrast < 4.5:1 on body text — **P7**
129
+ - Touch target < 24×24 — **P7**
130
+ - Mouse-only action with no keyboard equivalent — **P6**
131
+ - No empty / error / loading state shipped for a list or detail — **P5**
132
+ - New shared primitive forked from `ui/`, `components/data-views/` or `templates/` without proof of ≥ 2 use cases — **P8**
133
+ - Pixel-copy of a competitor screenshot — **P4**
134
+
135
+ ### Issue (I) — violates P9–P20 / Mx without a stated reason
136
+ Costly but not a bug. Examples:
137
+ - `toast()` for product feedback — **`exxat-no-toast.mdc`** / M6
138
+ - `vaul` import — **`exxat-no-vaul.mdc`**
139
+ - `TabsList` stretched full-width — **`exxat-tabs-chrome.mdc`** / M1
140
+ - Centered modal dialog where a `Sheet` would keep context — **M3 / `exxat-drawer-vs-dialog.mdc`**
141
+ - Status only in body, hidden from list / breadcrumb — **M4 / P13**
142
+ - Spinner overlay on initial load instead of `Skeleton` — **M9**
143
+ - Edit-bounces-to-form for a single field — **M5 / P15**
144
+ - Raw `<table>` or third-party data grid on a hub — **`exxat-data-tables.mdc`**
145
+ - Forked allow-list narrower than `FULL_HUB_SUPPORTED_VIEWS` without comment — **`exxat-hub-supported-views.mdc`**
146
+ - KPI strip with > 4 tiles — **`exxat-kpi-max-four.mdc`**
147
+ - `MetricItem` with wrong `trendPolarity` (up arrow on a "lower-is-better" metric) — **`exxat-kpi-trends.mdc`**
148
+
149
+ ### Nit (N) — preferences / minor signals
150
+ Worth noting, not worth blocking. Examples:
151
+ - Missing `<Kbd>` hint on a primary CTA — **`exxat-kbd-shortcuts.mdc`**
152
+ - Color-only status communication without an icon or label — **M4 secondary**
153
+ - Empty-state copy doesn't match `voice-and-tone.md`
154
+ - Sparse density on a daily-power-user surface — **P14**
155
+ - No activity timeline on a record that changes over time — **M7**
156
+
157
+ If you can't decide between two tiers, pick the **lower** severity (Issue over
158
+ Blocker; Nit over Issue) and explain why. Over-flagging Blockers makes the
159
+ report ignorable.
160
+
161
+ ## The 10-dimension grep cheatsheet
162
+
163
+ Use these as starting signals. Read the file before grading — greps surface
164
+ candidates, not verdicts.
165
+
166
+ ### D1 — Navigation integrity
167
+
168
+ | Signal | What it might mean |
169
+ |--------|---------------------|
170
+ | `Back to` near a `SiteHeader.*breadcrumbs` in the same client | **B1: P1** duplicate way-back |
171
+ | `breadcrumbs` array whose last item label equals the `title` prop | **B2: P2** duplicate identity |
172
+ | `<h1>` inside a body component below a `PageHeader` | **B3: P2** duplicate H1 |
173
+
174
+ ### D2 — Action hierarchy
175
+
176
+ | Signal | What it might mean |
177
+ |--------|---------------------|
178
+ | Two adjacent `Button variant="default"` in the actions slot | **B: P3** two primaries |
179
+ | Hand-built `<button>` in `PageHeader.actions` instead of DS `Button` | **I: `exxat-page-header-actions.mdc`** |
180
+
181
+ ### D3 — States
182
+
183
+ | Signal | What it might mean |
184
+ |--------|---------------------|
185
+ | No `Skeleton` / Suspense boundary in a route loading path | **I: M9** spinner-on-load |
186
+ | Hub `renderEmpty` missing on a `ListPageTemplate` | **B: P5** |
187
+ | `<Spinner` / `animate-spin` overlay covering initial load | **I: M9** |
188
+
189
+ ### D4 — Keyboard + a11y
190
+
191
+ | Signal | What it might mean |
192
+ |--------|---------------------|
193
+ | Icon-only `<Button>` without `aria-label` | **B: P7** |
194
+ | `DialogTitle` / `SheetTitle` missing on an overlay | **B: P7** |
195
+ | `role="tablist"` containing `role="button"` / `aria-haspopup` children | **B: `exxat-accessibility.mdc`** |
196
+ | Workflow primary button without `Kbd` + `Shortcut` (form/sheet/dialog) | **I: `exxat-kbd-shortcuts.mdc`** |
197
+ | Bare `<table>` in product hub | **B: `exxat-data-tables.mdc`** + **P7** (scope/headers) |
198
+
199
+ ### D5 — DS composition (no forks)
200
+
201
+ | Signal | What it might mean |
202
+ |--------|---------------------|
203
+ | `import.*from ['"]sonner` or `toast(` call | **I: `exxat-no-toast.mdc`** |
204
+ | `import.*from ['"]vaul` or local `components/ui/drawer` | **I: `exxat-no-vaul.mdc`** |
205
+ | `TabsList.*className=['"].*w-full` | **I: `exxat-tabs-chrome.mdc`** |
206
+ | `slds-` class names / `<lightning-` elements | **B: `exxat-no-slds-leakage.mdc`** |
207
+ | New `ProfileHero` / `RecordHeader` / `EntityHead` component duplicating `PageHeader` | **B: P8** |
208
+ | Custom face-rail / avatar group beside `PageHeader collaboration` | **I: `exxat-collaboration-access.mdc`** |
209
+
210
+ ### D6 — Modern pattern adherence
211
+
212
+ | Signal | What it might mean |
213
+ |--------|---------------------|
214
+ | Centered `Dialog` for export / properties / invite | **I: M3** (use Sheet) |
215
+ | Edit-via-route for single field | **I: M5** (inline edit) |
216
+ | Status only on detail (missing from row / board card) | **I: M4** |
217
+ | Multi-step compose flow inside a Dialog | **I: M3** (use route at ≥ 3 steps) |
218
+ | AI feature auto-runs on record open | **I: M12** |
219
+
220
+ ### D7 — Voice & tone
221
+
222
+ | Signal | What it might mean |
223
+ |--------|---------------------|
224
+ | "Persist", "Materialize", "Submit" where "Save" / "Send" fits | **N: P9** |
225
+ | Empty state wall-of-text + multiple CTAs | **I: M8** |
226
+ | Apologetic / passive copy in errors | **N: voice-and-tone.md** |
227
+
228
+ ### D8 — Job alignment
229
+
230
+ Read the relevant `docs/jobs/*.md` and grade the IA shape against it:
231
+
232
+ - **Record detail** → identity → status → 2-col card grid → activity. Tabs only if ≥ 4 sections / 20+ fields.
233
+ - **List hub** → toolbar / view tabs / `DataTable` / centralized `useTableState`.
234
+ - ...
235
+
236
+ Cite the section number in `jobs/*.md` for any mismatch.
237
+
238
+ ### D9 — Token + SLDS discipline
239
+
240
+ | Signal | What it might mean |
241
+ |--------|---------------------|
242
+ | `#[0-9a-fA-F]{3,8}` hex literal in app code | **B: `exxat-token-discipline.mdc`** + ESLint `exxat-ds/no-hex-color` |
243
+ | `--slds-*` / `var(--slds-*)` | **B: `exxat-no-slds-leakage.mdc`** |
244
+ | `--deprecated-*` or any token marked `deprecated: true` in `tokens/hooks-index.json` | **I: token taxonomy** |
245
+
246
+ ### D10 — Hub-specific (only if the surface IS a hub)
247
+
248
+ | Signal | What it might mean |
249
+ |--------|---------------------|
250
+ | `<DataTable>` mounted in `ListPageTemplate.renderContent` instead of `<HubTable>` | **I: `exxat-data-tables.mdc`** |
251
+ | Forked mock array per view (table mock + tree mock + board mock) | **I: `exxat-centralized-list-dataset.mdc`** |
252
+ | `supportedViewTypes={["table"]}` on a primary hub | **I: `exxat-hub-supported-views.mdc`** |
253
+ | `KEY_METRICS_KPI_COUNT_MAX` exceeded (>4 KPIs) | **I: `exxat-kpi-max-four.mdc`** |
254
+ | `MetricItem` without `trendPolarity` on lower-is-better metric | **I: `exxat-kpi-trends.mdc`** |
255
+
256
+ ## Auto-fix policy
257
+
258
+ After the report, propose a **Next action** at the bottom. The default offers
259
+ auto-fix on **Blockers** that meet ALL of:
260
+
261
+ - Edit is **text-only** (no architectural change).
262
+ - Edit is **single-file** OR **≤ 3 files** that move in lock-step (e.g. remove
263
+ body Back button + trim breadcrumb array in the client).
264
+ - Edit doesn't change **route shape** / **API contract** / **component
265
+ hierarchy**.
266
+
267
+ Examples of auto-fixable Blockers:
268
+
269
+ - Remove a redundant "Back to <parent>" button.
270
+ - Trim the `breadcrumbs` array to ancestors-only.
271
+ - Demote one of two filled CTAs to `variant="outline"`.
272
+ - Add a missing `sr-only` `DialogTitle` / `SheetTitle`.
273
+ - Replace `<button>` with `<Button>` in a header.
274
+
275
+ Examples that are **NOT** auto-fixable (propose only, ask first):
276
+
277
+ - Modal → Sheet conversion (M3) — touches overlay primitives + URL state.
278
+ - Route → Sheet conversion (or vice versa) — IA change.
279
+ - New job-doc creation when none matches.
280
+ - KPI architecture refactor (>4 tiles → flat band + secondary stats).
281
+ - Replacing a forked primitive with composition — needs design review.
282
+ - Anything that touches > 3 files.
283
+
284
+ Always wait for a "yes" before applying.
285
+
286
+ ## Push back (same posture as senior-UX)
287
+
288
+ - Refuse to audit "everything in the repo at once" — request a single surface.
289
+ - Don't grade a screenshot as if it were code unless source is provided too.
290
+ - Don't over-flag Blockers; lean toward Issue when in doubt.
291
+ - If the user wants the **fix plan** without seeing the report, still output
292
+ the report — the report IS the plan's audit trail.
293
+
294
+ ## See also
295
+
296
+ - [`exxat-senior-ux/SKILL.md`](../exxat-senior-ux/SKILL.md) — the forward
297
+ persona (the §5 self-audit is the seed of this skill)
298
+ - [`exxat-ux-principles.mdc`](../../rules/exxat-ux-principles.mdc) — P1–P20
299
+ - [`exxat-ux-discovery-protocol.mdc`](../../rules/exxat-ux-discovery-protocol.mdc) — brief gate
300
+ - [`modern-saas-patterns.md`](../../../apps/web/docs/modern-saas-patterns.md) — M1–M12
301
+ - [`docs/jobs/`](../../../apps/web/docs/jobs/) — job IA references
302
+ - [`exxat-token-economy/SKILL.md`](../exxat-token-economy/SKILL.md) — minimum file set per task
303
+ - All `exxat-*.mdc` rules — concrete enforcement per pattern
@@ -7,8 +7,7 @@
7
7
  */
8
8
 
9
9
  import * as React from "react"
10
- import dynamic from "next/dynamic"
11
- import { usePathname } from "next/navigation"
10
+ import { usePathname } from "@/lib/next-compat"
12
11
  import { AnimatePresence, motion } from "motion/react"
13
12
  import { cn } from "@/lib/utils"
14
13
  import { Avatar, AvatarFallback, AvatarImage, AvatarLeoAssistant } from "@/components/ui/avatar"
@@ -26,13 +25,16 @@ import { StatusBadge } from "@/components/ui/status-badge"
26
25
  import { AiThinkingOverlay } from "@/components/ui/ai-thinking-surface"
27
26
  import { LeoTypingDots } from "@/components/leo-typing-dots"
28
27
 
29
- const LeoIcon = dynamic(
30
- () => import("@/components/ui/leo-icon").then(m => m.LeoIcon),
31
- {
32
- ssr: false,
33
- loading: () => <div className="size-20" aria-hidden="true" />,
34
- },
28
+ const LeoIconLazy = React.lazy(() =>
29
+ import("@/components/ui/leo-icon").then(m => ({ default: m.LeoIcon })),
35
30
  )
31
+ function LeoIcon(props: React.ComponentProps<typeof LeoIconLazy>) {
32
+ return (
33
+ <React.Suspense fallback={<div className="size-20" aria-hidden="true" />}>
34
+ <LeoIconLazy {...props} />
35
+ </React.Suspense>
36
+ )
37
+ }
36
38
  import { useAltKeyLabel, useModKeyLabel } from "@/hooks/use-mod-key-label"
37
39
  import { ASK_LEO_GENERIC_SUGGESTIONS, getAskLeoRouteContext } from "@/lib/ask-leo-route-context"
38
40
  import { isEditableTarget } from "@/lib/editable-target"
@@ -5,7 +5,7 @@
5
5
  * (`lib/command-menu-config.ts`); no hard-coded nav or copy here.
6
6
  */
7
7
 
8
- import { useRouter } from "next/navigation"
8
+ import { useRouter } from "@/lib/next-compat"
9
9
  import { useCallback, useEffect, useRef, useState } from "react"
10
10
  import {
11
11
  Command,
@@ -6,7 +6,7 @@
6
6
  */
7
7
 
8
8
  import * as React from "react"
9
- import Link from "next/link"
9
+ import { Link } from "@/lib/next-compat"
10
10
  import { Collapsible, CollapsibleTrigger } from "@/components/ui/collapsible"
11
11
  import { Button } from "@/components/ui/button"
12
12
  import {
@@ -1,7 +1,7 @@
1
1
  "use client"
2
2
 
3
3
  import * as React from "react"
4
- import { useRouter } from "next/navigation"
4
+ import { useRouter } from "@/lib/next-compat"
5
5
 
6
6
  import { Button } from "@/components/ui/button"
7
7
  import { Tip } from "@/components/ui/tip"
@@ -1,7 +1,7 @@
1
1
  "use client"
2
2
 
3
3
  import * as React from "react"
4
- import { useRouter } from "next/navigation"
4
+ import { useRouter } from "@/lib/next-compat"
5
5
 
6
6
  import { AskLeoComposer } from "@/components/ask-leo-composer"
7
7
  import { cn } from "@/lib/utils"
@@ -21,9 +21,9 @@
21
21
  * removes both classes of issue.
22
22
  *
23
23
  * **Reference paths:** the mark + "Exxat" path data is the same `d=…` source
24
- * used by the original `ExxatOneLogo` in `packages/ui/template/components/
25
- * exxat-product-logo.tsx` (the pre-text-route baseline). Only the gradient
26
- * colours are pulled from the brand registry so new brands recolour the mark.
24
+ * used by the historical `ExxatOneLogo` (the pre-text-route baseline). Only
25
+ * the gradient colours are pulled from the brand registry so new brands
26
+ * recolour the mark.
27
27
  */
28
28
 
29
29
  import * as React from "react"
@@ -7,7 +7,7 @@
7
7
  */
8
8
 
9
9
  import * as React from "react"
10
- import { useRouter, useSearchParams } from "next/navigation"
10
+ import { useRouter, useSearchParams } from "@/lib/next-compat"
11
11
  import {
12
12
  ListPageTemplate,
13
13
  type ViewTab,
@@ -1,8 +1,8 @@
1
1
  "use client"
2
2
 
3
3
  import * as React from "react"
4
- import Link from "next/link"
5
- import { useRouter } from "next/navigation"
4
+ import { Link } from "@/lib/next-compat"
5
+ import { useRouter } from "@/lib/next-compat"
6
6
 
7
7
  import { OsFolderGlyph } from "@/components/data-views/os-folder-glyph"
8
8
  import { AskLeoComposer } from "@/components/ask-leo-composer"
@@ -6,8 +6,8 @@
6
6
  */
7
7
 
8
8
  import * as React from "react"
9
- import Link from "next/link"
10
- import { usePathname, useRouter, useSearchParams } from "next/navigation"
9
+ import { Link } from "@/lib/next-compat"
10
+ import { usePathname, useRouter, useSearchParams } from "@/lib/next-compat"
11
11
  import { Button } from "@/components/ui/button"
12
12
  import {
13
13
  Dialog,
@@ -11,7 +11,6 @@
11
11
  */
12
12
 
13
13
  import * as React from "react"
14
- import dynamic from "next/dynamic"
15
14
  import { mailtoHref } from "@/lib/mailto"
16
15
  import type { DataListViewType } from "@/lib/data-list-view"
17
16
  import type { ColumnDef } from "@/components/data-table/types"
@@ -81,35 +80,44 @@ import {
81
80
 
82
81
  // ─── Dynamic dashboard charts section ────────────────────────────────────────
83
82
 
84
- const LibraryDashboardChartsSection = dynamic(
85
- () =>
86
- import("@/components/library-dashboard-charts").then(mod => ({
87
- default: mod.LibraryDashboardChartsSection,
88
- })),
89
- {
90
- ssr: false,
91
- loading: () => (
92
- <div className="flex min-h-0 flex-1 flex-col gap-4 pb-6">
93
- <div className="grid gap-3 sm:grid-cols-2 lg:grid-cols-4">
94
- <Skeleton className="h-20 w-full rounded-lg" />
95
- <Skeleton className="h-20 w-full rounded-lg" />
96
- <Skeleton className="h-20 w-full rounded-lg" />
97
- <Skeleton className="h-20 w-full rounded-lg" />
83
+ const LibraryDashboardChartsSectionLazy = React.lazy(() =>
84
+ import("@/components/library-dashboard-charts").then(mod => ({
85
+ default: mod.LibraryDashboardChartsSection,
86
+ })),
87
+ )
88
+
89
+ function LibraryDashboardChartsSectionFallback() {
90
+ return (
91
+ <div className="flex min-h-0 flex-1 flex-col gap-4 pb-6">
92
+ <div className="grid gap-3 sm:grid-cols-2 lg:grid-cols-4">
93
+ <Skeleton className="h-20 w-full rounded-lg" />
94
+ <Skeleton className="h-20 w-full rounded-lg" />
95
+ <Skeleton className="h-20 w-full rounded-lg" />
96
+ <Skeleton className="h-20 w-full rounded-lg" />
97
+ </div>
98
+ <div className="grid grid-cols-1 gap-4 lg:grid-cols-2">
99
+ <div className="flex flex-col gap-3 rounded-xl border border-border p-4">
100
+ <Skeleton className="h-5 w-32" />
101
+ <Skeleton className="min-h-[220px] w-full rounded-lg" />
98
102
  </div>
99
- <div className="grid grid-cols-1 gap-4 lg:grid-cols-2">
100
- <div className="flex flex-col gap-3 rounded-xl border border-border p-4">
101
- <Skeleton className="h-5 w-32" />
102
- <Skeleton className="min-h-[220px] w-full rounded-lg" />
103
- </div>
104
- <div className="flex flex-col gap-3 rounded-xl border border-border p-4">
105
- <Skeleton className="h-5 w-28" />
106
- <Skeleton className="min-h-[220px] w-full rounded-lg" />
107
- </div>
103
+ <div className="flex flex-col gap-3 rounded-xl border border-border p-4">
104
+ <Skeleton className="h-5 w-28" />
105
+ <Skeleton className="min-h-[220px] w-full rounded-lg" />
108
106
  </div>
109
107
  </div>
110
- ),
111
- },
112
- )
108
+ </div>
109
+ )
110
+ }
111
+
112
+ function LibraryDashboardChartsSection(
113
+ props: React.ComponentProps<typeof LibraryDashboardChartsSectionLazy>,
114
+ ) {
115
+ return (
116
+ <React.Suspense fallback={<LibraryDashboardChartsSectionFallback />}>
117
+ <LibraryDashboardChartsSectionLazy {...props} />
118
+ </React.Suspense>
119
+ )
120
+ }
113
121
 
114
122
  // ─── Constants ───────────────────────────────────────────────────────────────
115
123
 
@@ -35,7 +35,7 @@
35
35
  */
36
36
 
37
37
  import * as React from "react"
38
- import { useRouter } from "next/navigation"
38
+ import { useRouter } from "@/lib/next-compat"
39
39
  import { useForm, useWatch, type Resolver } from "react-hook-form"
40
40
  import { zodResolver } from "@hookform/resolvers/zod"
41
41
  import { z } from "zod"
@@ -1,7 +1,7 @@
1
1
  "use client"
2
2
 
3
3
  import * as React from "react"
4
- import Link from "next/link"
4
+ import { Link } from "@/lib/next-compat"
5
5
 
6
6
  import { cn } from "@/lib/utils"
7
7
  import {
@@ -9,7 +9,7 @@
9
9
  */
10
10
 
11
11
  import * as React from "react"
12
- import { useRouter } from "next/navigation"
12
+ import { useRouter } from "@/lib/next-compat"
13
13
  import { Button } from "@/components/ui/button"
14
14
  import { Badge } from "@/components/ui/badge"
15
15
  import { Input } from "@/components/ui/input"
@@ -10,8 +10,8 @@
10
10
  */
11
11
 
12
12
  import * as React from "react"
13
- import Link from "next/link"
14
- import { usePathname } from "next/navigation"
13
+ import { Link } from "@/lib/next-compat"
14
+ import { usePathname } from "@/lib/next-compat"
15
15
  import { motion, useReducedMotion } from "motion/react"
16
16
 
17
17
  import {
@@ -1,6 +1,6 @@
1
1
  "use client"
2
2
 
3
- import { usePathname } from "next/navigation"
3
+ import { usePathname } from "@/lib/next-compat"
4
4
  import {
5
5
  SidebarGroup,
6
6
  SidebarGroupContent,
@@ -14,7 +14,7 @@
14
14
  */
15
15
 
16
16
  import { useTheme } from "next-themes"
17
- import Link from "next/link"
17
+ import { Link } from "@/lib/next-compat"
18
18
 
19
19
  import {
20
20
  Avatar,
@@ -24,7 +24,7 @@
24
24
  */
25
25
 
26
26
  import * as React from "react"
27
- import { usePathname } from "next/navigation"
27
+ import { usePathname } from "@/lib/next-compat"
28
28
  import { cn } from "@/lib/utils"
29
29
  import { resolveActiveNavHref } from "@exxatdesignux/ui/lib/nav-active"
30
30
  import {
@@ -7,7 +7,7 @@
7
7
  */
8
8
 
9
9
  import * as React from "react"
10
- import Link from "next/link"
10
+ import { Link } from "@/lib/next-compat"
11
11
  import { SystemBanner } from "@/components/ui/banner"
12
12
  import { AiThinkingOverlay } from "@/components/ui/ai-thinking-surface"
13
13
  import { useSystemBanner } from "@/contexts/system-banner-context"
@@ -1,8 +1,8 @@
1
1
  "use client"
2
2
 
3
3
  import * as React from "react"
4
- import Link from "next/link"
5
- import { useRouter } from "next/navigation"
4
+ import { Link } from "@/lib/next-compat"
5
+ import { useRouter } from "@/lib/next-compat"
6
6
 
7
7
  import { useAskLeo } from "@/components/ask-leo-sidebar"
8
8
  import { PrimaryPageTemplate, type PrimaryPageTemplateProps } from "@/components/templates/primary-page-template"
@@ -58,7 +58,7 @@
58
58
  */
59
59
 
60
60
  import * as React from "react"
61
- import Link from "next/link"
61
+ import { Link } from "@/lib/next-compat"
62
62
 
63
63
  import { cn } from "@/lib/utils"
64
64
  import { Button } from "@/components/ui/button"
@@ -13,8 +13,8 @@
13
13
  */
14
14
 
15
15
  import * as React from "react"
16
- import Link from "next/link"
17
- import { usePathname, useSearchParams } from "next/navigation"
16
+ import { Link } from "@/lib/next-compat"
17
+ import { usePathname, useSearchParams } from "@/lib/next-compat"
18
18
 
19
19
  import { Tip } from "@/components/ui/tip"
20
20
  import { cn } from "@/lib/utils"
@@ -23,7 +23,7 @@
23
23
  */
24
24
 
25
25
  import * as React from "react"
26
- import { useRouter, useSearchParams } from "next/navigation"
26
+ import { useRouter, useSearchParams } from "@/lib/next-compat"
27
27
 
28
28
  import { PrimaryPageTemplate } from "@/components/templates/primary-page-template"
29
29
  import { PageHeader } from "@/components/page-header"
@@ -1,7 +1,7 @@
1
1
  "use client"
2
2
 
3
3
  import * as React from "react"
4
- import { usePathname, useRouter, useSearchParams } from "next/navigation"
4
+ import { usePathname, useRouter, useSearchParams } from "@/lib/next-compat"
5
5
 
6
6
  import { useSecondaryPanel } from "@/components/sidebar"
7
7
  import { LIBRARY_HUB_FIND_PATH, LIBRARY_ALL_PATH, LIBRARY_LIST_PATH } from "@/lib/library-nav"