@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,33 @@
1
+ ---
2
+ description: Exxat DS — Tabs and view toolbars must not stretch full width; use ListPageTemplate for hub views. Auto-attaches when editing React surfaces with tabs or view toolbars.
3
+ globs: apps/web/{components,app}/**/*.{tsx,ts}
4
+ alwaysApply: false
5
+ appliesTo: [react]
6
+ ---
7
+
8
+ # Exxat DS — tabs chrome (no full-width stretch)
9
+
10
+ ## List hubs (All students, Placements, …)
11
+
12
+ **MUST** use **`ListPageTemplate`** view toolbar — `role="toolbar"` + **`w-max`** segmented control (`viewSegmentedToolbarClass`), **not** Radix **`Tabs`** stretched across the page.
13
+
14
+ - Reference: `packages/ui/src/components/templates/list-page.tsx` (views toolbar block).
15
+ - **MUST NOT** build a custom full-width tab bar for “All students · 16” + Add view.
16
+
17
+ ## Entity / record detail (Overview, Academics, Placements, …)
18
+
19
+ **MUST** use **`Tabs`**, **`TabsList`**, **`TabsTrigger`** from `@/components/ui/tabs`:
20
+
21
+ - **`TabsList`** defaults to **`inline-flex w-fit`** — **MUST NOT** pass `className="w-full"` or wrap the list in a full-width flex container that forces triggers to **`flex-1`**.
22
+ - Prefer **`variant="line"`** for record sub-nav under a **`PageHeader`** (`record-home` blueprint).
23
+ - **`TabsTrigger`** may use `flex-1` only inside a **`w-fit`** list with a fixed number of tabs — never inside a bar that spans the content column.
24
+
25
+ ## MUST NOT
26
+
27
+ - A single grey/white bar spanning the entire content width with tabs distributed edge-to-edge.
28
+ - Mix hub **view tabs** (table/list/board) with entity **section tabs** (Overview/Academics) — different patterns.
29
+
30
+ ## See also
31
+
32
+ - **`apps/web/docs/blueprints/page-header.md`** — header never carries view tabs
33
+ - **`apps/web/docs/data-views-pattern.md`** — `ListPageTemplate` view toolbar
@@ -0,0 +1,109 @@
1
+ ---
2
+ description: Token discipline — no hex literals, prefer Exxat L0 tokens (--exxat-color-*, --exxat-radius-*, --exxat-spacing-*), no deprecated tokens. ESLint enforces via @exxatdesignux/eslint-plugin.
3
+ alwaysApply: true
4
+ appliesTo: [universal]
5
+ ---
6
+
7
+ # Exxat DS — token discipline
8
+
9
+ **Authoritative reference:** [`apps/web/docs/token-taxonomy.md`](mdc:apps/web/docs/token-taxonomy.md).
10
+ **Machine-readable index:** [`packages/ui/tokens/hooks-index.json`](mdc:packages/ui/tokens/hooks-index.json) (163 tokens · 36 namespaces; regenerate via `pnpm --filter @exxatdesignux/ui tokens:index`).
11
+ **Enforcement:** [`@exxatdesignux/eslint-plugin`](mdc:packages/eslint-plugin-exxat-ds/README.md) (rules `exxat-ds/no-hex-color`, `exxat-ds/no-deprecated-tokens`).
12
+
13
+ Use this rule when adding **any** color, spacing, radius, shadow, or
14
+ transition value to JSX, CSS, or Tailwind class strings.
15
+
16
+ ## MUST
17
+
18
+ 1. **Prefer the Exxat L0 namespace** for new code — `var(--exxat-color-surface-1)`,
19
+ `bg-surface-1`, `bg-brand-1`, `rounded-2`, `--exxat-spacing-4`, … (taxonomy §2.0).
20
+ L1 shadcn names (`--background`, `bg-brand`, `rounded-md`, …) remain as
21
+ back-compat aliases and continue to work — but new product surfaces should
22
+ read in the canonical brand-prefixed namespace.
23
+ 2. **Reach for a semantic token first.** If the value carries semantic intent
24
+ ("danger", "warning", "muted text", "card surface"), use the matching
25
+ token family from §2 of the taxonomy. Never reinvent semantic colors.
26
+ 3. **Use Tailwind utilities backed by tokens** (e.g. `bg-card`,
27
+ `text-muted-foreground`, `border-border-control`, `ring-ring`,
28
+ `bg-chip-2`, `text-chart-4`, **`bg-surface-1`**, **`bg-brand-1`**,
29
+ **`rounded-2`**). The L2 bridges in `globals.css` already wire
30
+ `--color-*` → `var(--*)` so utilities flip with theme + dark mode.
31
+ 3. **Brand accent comes from `--brand-color` / `bg-brand`** (and its family),
32
+ **not** `--primary` / `bg-primary`. Primary is **neutral charcoal** in
33
+ Exxat — see taxonomy §3.
34
+ 4. **Form-field borders** use `--control-border` (or `border-control-3` /
35
+ `border-control-35`) — never `--border` (which is decorative and < 3:1
36
+ contrast). Taxonomy §6.
37
+ 5. **Status chips and badges** route through
38
+ [`lib/list-status-badges.ts`](mdc:apps/web/lib/list-status-badges.ts)
39
+ (`LIST_HUB_STATUS_TINT_*` + `ListHubStatusBadge`) — not direct
40
+ `bg-green-500` / `bg-red-500` / hex literals.
41
+ 6. **KPI tints** route through `--insight-severity-*` (info / warning) — not
42
+ direct chart-color reuse. Trend polarity is set via
43
+ `MetricItem.trendPolarity` ([`exxat-kpi-trends.mdc`](mdc:.cursor/rules/exxat-kpi-trends.mdc)).
44
+ 7. **Scoped surface tokens stay scoped.** `--dt-*` is `DataTable` only,
45
+ `--key-metrics-*` is `KeyMetrics` only, `--leo-*` is Ask Leo only,
46
+ `--secondary-panel-bg` is the nested panel only. Do **not** reuse these
47
+ tokens outside their owning surface.
48
+ 8. **Adding a new token** — Follow the checklist in
49
+ [`token-taxonomy.md` §4](mdc:apps/web/docs/token-taxonomy.md). Declare
50
+ the primitive in `packages/ui/src/globals.css` (canonical CSS), bridge it in the same file's `@theme inline`
51
+ files when Tailwind utilities are needed, document it in the taxonomy,
52
+ and regenerate `tokens/hooks-index.json`.
53
+
54
+ ## MUST NOT
55
+
56
+ 1. **No raw hex / rgb / hsl color literals** in JSX `className` strings,
57
+ inline `style={{...}}`, or `.css` files outside of `globals.css` /
58
+ `globals.css` / theme overrides. The only places hex is legal are:
59
+ - `--theme-color-chrome` (consumed by `<meta name="theme-color">`)
60
+ - Status icon SVG paths that are part of a vendored asset
61
+ - **Documentation** examples (this rule, blueprints, migrations)
62
+ 2. **No raw `oklch(...)` literals** in component code — those belong in
63
+ `globals.css` theme blocks only. If you need a derived value, use
64
+ `color-mix(in oklch, var(--token) <pct>%, var(--other))` inside a token
65
+ declaration, not at the call site.
66
+ 3. **No deprecated tokens.** Inspect
67
+ [`tokens/hooks-index.json`](mdc:packages/ui/tokens/hooks-index.json) —
68
+ any entry with `"deprecated": true` is removed at the version named in
69
+ `deprecatedMessage`. Migrate before the removal window per
70
+ `apps/web/docs/migrations/`.
71
+ 4. **No ad-hoc Tailwind shades** for product chrome (e.g. `bg-slate-50`,
72
+ `text-zinc-600`, `border-gray-200`) when an Exxat semantic equivalent
73
+ exists. Tailwind shade utilities are reserved for transient prototyping
74
+ only; product code uses the semantic tokens.
75
+ 5. **No `text-primary` for the brand accent.** That maps to neutral charcoal
76
+ (see MUST #3).
77
+ 6. **No utility-class typos that look like tokens.** Examples that look
78
+ right but aren't:
79
+ - `bg-brand-color` — that's the *raw L1 name*; the L2 utility is `bg-brand`.
80
+ - `border-control` — there's no such utility; the field-border alias is `border-control-3` (3:1) or `border-control-35` (3.5:1+), or `border-[var(--control-border)]`.
81
+ - `text-foreground-muted` — the token is `--muted-foreground` (note the order).
82
+ 7. **No SLDS tokens** (`--slds-g-color-*`) — see
83
+ [`exxat-no-slds-leakage.mdc`](mdc:.cursor/rules/exxat-no-slds-leakage.mdc).
84
+
85
+ ## Aliases that ARE official
86
+
87
+ Some L2 bridges intentionally use a **shorter alias** than the L1 primitive
88
+ because the long name would be awkward in Tailwind utilities. Use the alias
89
+ form, but be aware of the underlying primitive:
90
+
91
+ | Alias (use in code) | L0 canonical | L1 primitive | Notes |
92
+ |---|---|---|---|
93
+ | `bg-brand` / `text-brand` | `--exxat-color-brand-1` | `--brand-color` | Brand accent |
94
+ | `bg-brand-deep` / `text-brand-deep` | `--exxat-color-brand-deep` | `--brand-color-deep` | Coach marks, hero callouts |
95
+ | `bg-brand-tint` | `--exxat-color-brand-tint-1` | `--brand-tint` | Sidebar wash |
96
+ | `bg-surface-1` / `text-ink-1` | `--exxat-color-surface-1` / `--exxat-color-ink-1` | `--background` / `--foreground` | Page canvas + primary text — new code SHOULD prefer L0 form |
97
+ | `rounded-1` … `rounded-6` | `--exxat-radius-1` … `--exxat-radius-6` | (no L1 equivalent — L0 is canonical for radius) | Numeric radius scale (4 / 8 / 12 / 16 / 20 / 24 px) |
98
+
99
+ The full alias table is in [`token-taxonomy.md` §2.0](mdc:apps/web/docs/token-taxonomy.md) and [§2.2](mdc:apps/web/docs/token-taxonomy.md).
100
+
101
+ ## See also
102
+
103
+ - [`apps/web/docs/token-taxonomy.md`](mdc:apps/web/docs/token-taxonomy.md) — full namespace + naming rules
104
+ - [`apps/web/docs/migrations/`](mdc:apps/web/docs/migrations) — deprecation index
105
+ - [`packages/ui/tokens/hooks-index.json`](mdc:packages/ui/tokens/hooks-index.json) — machine-readable
106
+ - [`.cursor/rules/exxat-no-slds-leakage.mdc`](mdc:.cursor/rules/exxat-no-slds-leakage.mdc)
107
+ - [`.cursor/rules/exxat-kpi-trends.mdc`](mdc:.cursor/rules/exxat-kpi-trends.mdc)
108
+ - [`.cursor/rules/exxat-kpi-flat-band.mdc`](mdc:.cursor/rules/exxat-kpi-flat-band.mdc)
109
+ - [`.cursor/rules/exxat-no-toast.mdc`](mdc:.cursor/rules/exxat-no-toast.mdc)
@@ -0,0 +1,202 @@
1
+ ---
2
+ description: Exxat DS — STOP before code on any surface design (new, rebuild, redesign, replace); output a design brief and WAIT for user go-ahead
3
+ alwaysApply: true
4
+ appliesTo: [universal]
5
+ ---
6
+
7
+ # Exxat DS — UX discovery protocol
8
+
9
+ ## STOP — read before you write any file
10
+
11
+ If the user's prompt asks you to **design, create, build, rebuild, redesign,
12
+ replace, redo, refresh, modernize, re-imagine, or "make a new version of"**
13
+ any **page, route, screen, hub, detail view, wizard, settings section,
14
+ dashboard, dialog, sheet, drawer, panel, layout, or significant component**:
15
+
16
+ 1. **Do NOT write code, do NOT edit files, do NOT call edit tools yet.**
17
+ 2. **Output the design brief** (template below) in chat.
18
+ 3. **Wait for the user to reply** with `yes` / `proceed` / `ship it` / edits.
19
+ 4. **Only then** move to implementation.
20
+
21
+ If your next tool call would be `write_file`, `str_replace`, `create_file`,
22
+ or any code-mutating action **and** you have not posted a brief and received
23
+ go-ahead, you are violating this rule. **Stop and post the brief.**
24
+
25
+ ## When this gate fires (and when it doesn't)
26
+
27
+ This gate fires on **any task that decides what a surface should look like
28
+ or how it works** — whether the surface exists today or not. Treat
29
+ "replace what we have" and "create from scratch" identically — both need a
30
+ brief, because both make a design decision.
31
+
32
+ **Fires (brief required):**
33
+
34
+ - "Create a new student detail page."
35
+ - "Rebuild the dashboard."
36
+ - "Redesign the settings screen instead of what we have."
37
+ - "Make a new version of the placements table."
38
+ - "Replace the current onboarding flow."
39
+ - "Build a wizard for adding a site."
40
+ - "Design a sheet for inviting collaborators."
41
+ - User attaches a screenshot / mockup / Figma link and asks to "build this".
42
+
43
+ **Does NOT fire (brief not required, edit freely):**
44
+
45
+ - Single-class restyle of an existing surface that already follows DS rules.
46
+ - Copy / label edits.
47
+ - Bug fixes (a11y violation, broken state, wrong data).
48
+ - Dependency bumps, ESLint passes, type fixes, test-only changes.
49
+ - Adding a new column / filter to an *existing* `HubTable` that doesn't
50
+ change the page's IA.
51
+
52
+ When in doubt, ask: **"Am I deciding what this surface should be?"** Yes →
53
+ brief. No → edit.
54
+
55
+ ## MUST
56
+
57
+ 0. **Output the brief, then WAIT.** The brief is a checkpoint, not a
58
+ preamble. Do not bundle the brief and the first file edit in the same
59
+ turn. After posting the brief, end your turn with an explicit
60
+ "Ready to build — confirm or edit." prompt. Resume only on the user's
61
+ next message.
62
+ 1. **No code without a confirmed brief.** "Confirmed" means the user wrote
63
+ `yes`, `proceed`, `ship it`, `LGTM`, `build it`, accepted edits, or asked
64
+ a follow-up that implies acceptance. Silence is not consent.
65
+ 2. **Cite a reference.** Every brief names **one repo reference** + **two
66
+ modern SaaS analogues** (Linear / Notion / Stripe / Figma / Vercel /
67
+ Linear / Airtable / Coda / Height / etc.) that solve the same
68
+ **job-to-be-done**. Cite the SaaS analogues by product name + pattern
69
+ codes from `apps/web/docs/modern-saas-patterns.md` (e.g.
70
+ `Linear issue detail (M1, M4, M7)`).
71
+ 3. **Name principles + breaks.** Brief lists the principles applied
72
+ (`exxat-ux-principles.mdc`) and any deviations with one-sentence reasons.
73
+ **Never-break** principles (P1–P8) cannot be deviated from.
74
+ 4. **One assumption per gap.** If the user can't or won't answer, state the
75
+ assumption inline; never invent silently.
76
+ 5. **Sync the brief to the implementation.** PR / commit message references
77
+ the job doc (`apps/web/docs/jobs/`) and any principle break.
78
+
79
+ ## MUST NOT
80
+
81
+ - **Skip the brief because the prompt sounds like a refactor.** "Rebuild",
82
+ "redesign", "replace", "instead of what we have", and "from scratch" are
83
+ design decisions, not refactors. Brief required.
84
+ - **Post a brief and then write 8 files in the same turn.** That's not a
85
+ brief — that's a press release. End the turn after the brief.
86
+ - Generate files before the brief.
87
+ - Ask more than **3** questions in one batch.
88
+ - Ask questions whose answer is already in the prompt, the file tree, or
89
+ `apps/web/docs/jobs/`.
90
+ - Use uploaded screenshots as the implementation spec
91
+ (`exxat-no-image-pixel-copy.mdc`).
92
+ - Treat a feature list as a job. Ask: *what decision does this enable?*
93
+
94
+ ## Question bank by surface type
95
+
96
+ Pick **at most 3** questions whose answers change the design. Skip the rest.
97
+
98
+ ### Record / entity detail
99
+ 1. Who reads this most — power admin (dense, keyboard-first) or occasional
100
+ user (cozy, guided)?
101
+ 2. How is it reached — list, deep link, notification, search? (Drives
102
+ breadcrumb + back-affordance model.)
103
+ 3. Section tabs needed, or single-scroll page? (Field count > ~20 or rich
104
+ children → tabs.)
105
+
106
+ ### Hub / list page
107
+ 1. Dense comparison (table) or visual browse (board / gallery)?
108
+ 2. Per-record actions, bulk actions, or both?
109
+ 3. Will users filter / sort / customize columns, or is the view fixed?
110
+
111
+ ### Wizard / compose flow
112
+ 1. One screen with sections, or multi-step (>3 decisions)?
113
+ 2. Are intermediate steps savable as drafts?
114
+ 3. Submit is destructive, or always reversible?
115
+
116
+ ### Settings / preferences
117
+ 1. User scope (personal), workspace (shared), or both?
118
+ 2. Search needed (>20 settings) or flat list?
119
+ 3. Apply-on-change or explicit Save?
120
+
121
+ ### Dashboard / analytics
122
+ 1. One critical KPI or a comparison set (≤4)?
123
+ 2. Read at a glance, or drill into details?
124
+ 3. Time range fixed, or user-controlled?
125
+
126
+ ### Overlay (drawer / dialog / sheet)
127
+ 1. Does the user need the hub visible behind them? (Yes → sheet; no → route.)
128
+ 2. Blocking confirmation, or reversible? (Blocking → dialog; reversible → sheet.)
129
+ 3. Will it grow to ≥3 steps? (Yes → consider route instead.)
130
+
131
+ ## Brief template (copy verbatim)
132
+
133
+ ```
134
+ Problem: <one sentence — the user's pain, not the feature>
135
+ User & frequency: <persona, frequency, expertise>
136
+ Job-to-be-done: <the decision or action this enables>
137
+ Pattern: <route | sheet | dialog | inline> + IA shape
138
+ Reference (repo): <file path>
139
+ Reference (modern): <product 1 + Mx>, <product 2 + Mx>
140
+ Principles applied: <P-codes from exxat-ux-principles>
141
+ Deviations: <principle + one-sentence reason, or "none">
142
+ Out of scope: <what this does not do, deliberately>
143
+ Open questions: <max 2; ideally 0>
144
+ ```
145
+
146
+ ## Examples
147
+
148
+ **Good:**
149
+ > Problem: Coordinators can't tell at a glance which students are
150
+ > non-compliant before placement.
151
+ > User & frequency: Program coordinator, daily, keyboard-first.
152
+ > Job-to-be-done: Identify and act on at-risk students in < 30s per record.
153
+ > Pattern: route `/students/[id]` + identity row + status row + 2×2 card grid.
154
+ > Reference (repo): `components/library-table.tsx` for IA cadence.
155
+ > Reference (modern): Linear issue detail (M1, M4, M7); Stripe customer
156
+ > record (M4, M11).
157
+ > Principles applied: P1, P2, P3, P5, P6, P13, P19.
158
+ > Deviations: none.
159
+ > Out of scope: inline editing (v2), bulk message (lives on list).
160
+ > Open questions: none.
161
+
162
+ **Bad (silent generate):**
163
+ > *Agent writes 4 files without explanation.*
164
+
165
+ **Bad (vague prompt accepted):**
166
+ > User: "make a settings page". *Agent writes generic form.* Should have
167
+ > asked: scope (personal/workspace), search needed, apply-on-change vs Save.
168
+
169
+ ## Closing artifact: the design → engineering handoff
170
+
171
+ When the build is complete (files written, surface working in dev), produce
172
+ **one filled-in handoff document** before declaring the task done.
173
+
174
+ **Template** lives at:
175
+
176
+ - Workspace: `apps/web/docs/templates/handoff.md` (or workspace root if not yet copied — copy from `packages/ui/consumer-extras/templates/handoff.md`)
177
+ - Consumer apps (after `exxat-ui sync-extras`): `docs/exxat-ds/templates/handoff.md`
178
+
179
+ **Fill it in** with the actual primitives, tokens, icons, and shortcuts the
180
+ build used. Save the filled copy at:
181
+
182
+ - `apps/web/docs/handoff/<surface-slug>.md` (workspace)
183
+ - `docs/exxat-ds/handoff/<surface-slug>.md` (consumer)
184
+
185
+ Attach the filled handoff to the PR description (or paste inline). The
186
+ engineer reads it once, runs `exxat-ui audit <generated-file>` to verify
187
+ the floor, and is done.
188
+
189
+ **MUST sections:** 1 (job-to-be-done), 3 (pattern + IA), 5 (DS components
190
+ used), 6 (tokens), 8 (a11y checklist — every box ticked), 11 (keyboard map),
191
+ 12 (any deviations from P9–P20).
192
+
193
+ If the handoff is incomplete or hand-wavy, the design task is not finished.
194
+
195
+ ## See also
196
+
197
+ - `.cursor/skills/exxat-senior-ux/SKILL.md` — the persona + full protocol
198
+ - `.cursor/rules/exxat-ux-principles.mdc` — principles + when to break
199
+ - `apps/web/docs/jobs/` — canonical references per job type
200
+ - `apps/web/docs/modern-saas-patterns.md` — pattern codes (M1–M12)
201
+ - `.cursor/rules/exxat-no-image-pixel-copy.mdc` — IA from screenshots only
202
+ - **Closing artifact:** `packages/ui/consumer-extras/templates/handoff.md`
@@ -0,0 +1,187 @@
1
+ ---
2
+ description: Exxat DS UX principles — what to follow, when to break, why
3
+ alwaysApply: true
4
+ appliesTo: [universal]
5
+ ---
6
+
7
+ # Exxat DS — UX principles (and when to break them)
8
+
9
+ Principles are the senior designer's spine. They make most decisions cheap.
10
+ **Break deliberately, not accidentally** — and say so in the design brief
11
+ (`exxat-ux-discovery-protocol.mdc`). If you can't write the deviation reason
12
+ in one sentence, you shouldn't be breaking the principle.
13
+
14
+ Each principle below has: **what it says**, **why**, **when to break**, and
15
+ the **anti-pattern**.
16
+
17
+ ---
18
+
19
+ ## Always-follow (P1–P8) — no exceptions
20
+
21
+ ### P1. Way back is obvious, and exactly once
22
+ Breadcrumb in `SiteHeader` OR explicit back affordance — **never both**.
23
+ - **Why:** Two paths back create cognitive overhead and a redundant UI.
24
+ - **When to break:** Never.
25
+ - **Anti-pattern:** Breadcrumb "Dashboard › Students › Jordan Lee" + a
26
+ separate "Back to roster" button in the body.
27
+ - **Reference:** `exxat-breadcrumbs-no-back.mdc`.
28
+
29
+ ### P2. One H1 per page; no duplicated identity
30
+ The record name appears in exactly one carrier — typically `PageHeader.title`
31
+ + ancestors-only breadcrumb. Not also as an `<h1>` in the body.
32
+ - **Why:** Screen readers and scan-reading rely on a single page title.
33
+ - **When to break:** Never.
34
+ - **Anti-pattern:** Name in breadcrumb leaf + `PageHeader title` + body `<h1>`.
35
+
36
+ ### P3. One primary action per surface
37
+ Exactly one filled `Button`; everything else `outline` / `ghost` / `link`.
38
+ - **Why:** Two primaries = no primary.
39
+ - **When to break:** Never. Symmetric pairs ("Approve" + "Reject") are both
40
+ *outline* — neither is the styled "primary".
41
+ - **Anti-pattern:** Two filled buttons in the header.
42
+
43
+ ### P4. Don't pixel-copy
44
+ Extract IA from screenshots and competitor references; never copy chrome,
45
+ colors, or bespoke widgets.
46
+ - **Why:** Pixels carry decisions made in another product's context.
47
+ - **When to break:** Never.
48
+ - **Reference:** `exxat-no-image-pixel-copy.mdc`.
49
+
50
+ ### P5. Every list / detail / action ships empty + error + loading
51
+ - **Why:** Real users hit all three; afterthoughts ship as bugs.
52
+ - **When to break:** Never.
53
+ - **Anti-pattern:** "Loading…" text and no skeleton; missing 404 / empty.
54
+
55
+ ### P6. Keyboard parity
56
+ Every mouse action has a keyboard equivalent; focus is always visible.
57
+ - **Why:** Power users, motor-disabled users, screen-reader users all rely
58
+ on this.
59
+ - **When to break:** Never.
60
+ - **Reference:** `exxat-kbd-shortcuts.mdc`, `exxat-accessibility.mdc`.
61
+
62
+ ### P7. WCAG 2.1 AA minimum
63
+ Contrast ≥ 4.5:1 (text) / ≥ 3:1 (UI), targets ≥ 24×24, labels on icon-only.
64
+ - **Why:** Floor for shipping. Not negotiable.
65
+ - **When to break:** Never.
66
+ - **Reference:** `exxat-accessibility.mdc`.
67
+
68
+ ### P8. Reuse before invent
69
+ Compose from DS primitives first. New shared primitives require user approval
70
+ after a real, repeated need (≥ 2 use cases).
71
+ - **Why:** Forked stacks divide the team; the DS is the vocabulary.
72
+ - **When to break:** Never silently. Ask the user.
73
+ - **Reference:** `exxat-reuse-before-custom.mdc`.
74
+
75
+ ---
76
+
77
+ ## Default-follow (P9–P20) — break only with stated reason
78
+
79
+ ### P9. Clarity over cleverness
80
+ Direct labels, recognizable patterns. "Save" beats "Persist". "Send" beats
81
+ "Beam".
82
+ - **Why:** Decisions cost less when the label states the action.
83
+ - **Break when:** Intentional brand voice in low-stakes surfaces (onboarding
84
+ celebration, marketing splash). Never in core flows.
85
+ - **Anti-pattern:** "Materialize this configuration" instead of "Save".
86
+
87
+ ### P10. Recognition over recall
88
+ Surface what the user needs; don't make them remember.
89
+ - **Why:** Working memory is the most expensive resource on a screen.
90
+ - **Break when:** Daily power users where keyboard shortcuts replace visible
91
+ chrome (Cron, Linear, Raycast). Provide a discoverable hint.
92
+ - **Anti-pattern:** Hiding a frequent action behind a chord with no UI.
93
+
94
+ ### P11. One job per surface
95
+ A screen optimizes for one primary user decision.
96
+ - **Why:** Splits attention, splits metrics, splits design quality.
97
+ - **Break when:** Workspace surfaces (Notion-style pages, Linear-style issue
98
+ views) deliberately compose multiple jobs. Even then, one job is **primary**.
99
+ - **Anti-pattern:** Settings page that also includes a dashboard.
100
+
101
+ ### P12. Progressive disclosure
102
+ Show core first; depth on demand (popovers, sheets, expand).
103
+ - **Why:** Most users do the common thing most of the time.
104
+ - **Break when:** Compliance / legal / audit surfaces where everything must
105
+ be visible.
106
+ - **Anti-pattern:** 30-field form on first load with no grouping.
107
+
108
+ ### P13. Status visible without scroll
109
+ Status signals that drive decisions (compliance, errors, urgency) appear
110
+ above the fold.
111
+ - **Why:** Status hidden = ignored.
112
+ - **Break when:** Privacy / discretion contexts (e.g. HR records where peer
113
+ visibility is undesirable).
114
+ - **Anti-pattern:** Compliance status on tab #3 of a record detail.
115
+
116
+ ### P14. Density follows frequency
117
+ Daily power users get compact / dense; occasional users get cozy / spacious.
118
+ - **Why:** Different audiences scan differently.
119
+ - **Break when:** Accessibility (low-vision, motor) mandates generous
120
+ spacing. Offer a density toggle if both audiences share a surface.
121
+ - **Anti-pattern:** Sparse table for a coordinator viewing 200 students/day.
122
+
123
+ ### P15. Inline editing where data is read
124
+ Modern SaaS (Notion, Linear, Airtable) edits in place. Don't bounce users
125
+ to a form for a single-field change.
126
+ - **Why:** Mode-switch friction kills throughput.
127
+ - **Break when:** Bulk operations, multi-field validation, audit-logged
128
+ fields, destructive edits — use a focused form / drawer.
129
+ - **Anti-pattern:** "Edit" page just to change a phone number.
130
+
131
+ ### P16. Optimistic UI for low-risk actions
132
+ Favorite, archive, status flip, reorder — feel instant; reconcile on error.
133
+ - **Why:** Speed of feedback is a quality signal.
134
+ - **Break when:** Financial / irreversible / regulated actions — show progress
135
+ and confirmation.
136
+ - **Anti-pattern:** Spinner overlay for a star-favorite toggle.
137
+
138
+ ### P17. Search is global and fast
139
+ `⌘K` opens command + search; everything addressable is searchable.
140
+ - **Why:** Modern users navigate by typing.
141
+ - **Break when:** Never for modern SaaS at this scale.
142
+ - **Reference:** `exxat-command-menu.mdc`.
143
+
144
+ ### P18. Content first, chrome last
145
+ Data is the star. Sidebars collapse to icons. Headers stay ~48–56px.
146
+ Surfaces are generous.
147
+ - **Why:** Chrome competes with the work.
148
+ - **Break when:** Heavily configurable admin consoles where chrome **is** the
149
+ content. Prefer collapsing over crowding.
150
+ - **Anti-pattern:** Purple gradient hero bar above a data table.
151
+
152
+ ### P19. Type carries hierarchy
153
+ Weight, size, color do the heavy lifting before borders, boxes, or color
154
+ tints.
155
+ - **Why:** Ornament dates fast; type ages well.
156
+ - **Break when:** Status surfaces where color is encoding meaning (chips,
157
+ alerts).
158
+ - **Anti-pattern:** Every value wrapped in a tinted card.
159
+
160
+ ### P20. AI is a sidecar, not the primary path
161
+ Ask Leo / inline AI — opt-in, contextual, cancellable. Never auto-runs on a
162
+ record. Never the only way to do something.
163
+ - **Why:** AI is a feature; the core product must work without it.
164
+ - **Break when:** Surfaces explicitly built around AI (e.g. an AI-only
165
+ composer). Even then, expose the deterministic path.
166
+ - **Reference:** `exxat-command-menu.mdc` (⌘K vs ⌘⌥K split).
167
+
168
+ ---
169
+
170
+ ## How to declare a deviation
171
+
172
+ In the design brief, list the broken principle + the reason on one line:
173
+
174
+ ```
175
+ Deviations: P14 (density) — broke "follows frequency" because the primary
176
+ user here is occasional but the same surface also serves daily
177
+ admins; resolved with a density toggle, default cozy.
178
+ ```
179
+
180
+ If the reason doesn't fit on one line, the deviation isn't justified yet.
181
+
182
+ ## See also
183
+
184
+ - `.cursor/skills/exxat-senior-ux/SKILL.md` — the persona
185
+ - `.cursor/rules/exxat-ux-discovery-protocol.mdc` — gating + brief
186
+ - `apps/web/docs/modern-saas-patterns.md` — the modern canon (M1–M12)
187
+ - All `exxat-*.mdc` rules — concrete enforcement per pattern