@exxatdesignux/ui 0.2.19 → 0.3.0

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 (688) hide show
  1. package/CHANGELOG.md +60 -7
  2. package/bin/sync-extras.mjs +116 -29
  3. package/consumer-extras/README.md +42 -7
  4. package/consumer-extras/cursor-rules/exxat-accessibility.mdc +39 -0
  5. package/consumer-extras/cursor-rules/exxat-board-cards.mdc +26 -0
  6. package/consumer-extras/cursor-rules/exxat-breadcrumbs-no-back.mdc +21 -0
  7. package/consumer-extras/cursor-rules/exxat-card-vs-list-rows.mdc +21 -0
  8. package/consumer-extras/cursor-rules/exxat-centralized-list-dataset.mdc +44 -0
  9. package/consumer-extras/cursor-rules/exxat-collaboration-access.mdc +32 -0
  10. package/consumer-extras/cursor-rules/exxat-command-menu.mdc +22 -0
  11. package/consumer-extras/cursor-rules/exxat-dashboard-view-charts.mdc +53 -0
  12. package/consumer-extras/cursor-rules/exxat-data-tables.mdc +41 -0
  13. package/consumer-extras/cursor-rules/exxat-dedicated-search-surfaces.mdc +25 -0
  14. package/consumer-extras/cursor-rules/exxat-drawer-vs-dialog.mdc +22 -0
  15. package/consumer-extras/cursor-rules/exxat-ds-agents.mdc +56 -0
  16. package/consumer-extras/cursor-rules/exxat-fontawesome-icons.mdc +31 -0
  17. package/consumer-extras/cursor-rules/exxat-kbd-shortcuts.mdc +100 -0
  18. package/consumer-extras/cursor-rules/exxat-kpi-flat-band.mdc +28 -0
  19. package/consumer-extras/cursor-rules/exxat-kpi-max-four.mdc +21 -0
  20. package/consumer-extras/cursor-rules/exxat-kpi-trends.mdc +31 -0
  21. package/consumer-extras/cursor-rules/exxat-list-page-connected-views.mdc +24 -0
  22. package/consumer-extras/cursor-rules/exxat-list-page-view-shells.mdc +31 -0
  23. package/consumer-extras/cursor-rules/exxat-mono-ids.mdc +30 -0
  24. package/consumer-extras/cursor-rules/exxat-no-slds-leakage.mdc +78 -0
  25. package/consumer-extras/cursor-rules/exxat-no-toast.mdc +25 -0
  26. package/consumer-extras/cursor-rules/exxat-page-vs-drawer.mdc +23 -0
  27. package/consumer-extras/cursor-rules/exxat-person-identity-display.mdc +47 -0
  28. package/consumer-extras/cursor-rules/exxat-primary-nav-secondary-panel.mdc +52 -0
  29. package/consumer-extras/cursor-rules/exxat-question-bank-hub-header.mdc +28 -0
  30. package/consumer-extras/cursor-rules/exxat-reuse-before-custom.mdc +34 -0
  31. package/consumer-extras/cursor-rules/exxat-table-properties-drawer.mdc +77 -0
  32. package/consumer-extras/cursor-rules/exxat-token-discipline.mdc +103 -0
  33. package/consumer-extras/cursor-skills/exxat-accessibility/SKILL.md +1 -1
  34. package/consumer-extras/cursor-skills/exxat-board-cards/SKILL.md +2 -2
  35. package/consumer-extras/cursor-skills/exxat-centralized-list-dataset/SKILL.md +4 -15
  36. package/consumer-extras/cursor-skills/exxat-ds-skill/SKILL.md +13 -28
  37. package/consumer-extras/cursor-skills/exxat-ds-skill/references/data-table-pattern.md +1 -1
  38. package/consumer-extras/cursor-skills/exxat-primary-nav-secondary-panel/SKILL.md +2 -4
  39. package/consumer-extras/handbook/HANDBOOK.md +185 -0
  40. package/consumer-extras/handbook/glossary.md +57 -0
  41. package/consumer-extras/handbook/reference-implementations.md +126 -0
  42. package/consumer-extras/handbook/voice-and-tone.md +262 -0
  43. package/consumer-extras/patterns/command-menu-pattern.md +1 -1
  44. package/consumer-extras/patterns/consumer-upgrade-checklist.md +0 -20
  45. package/consumer-extras/patterns/data-views-pattern.md +17 -54
  46. package/consumer-extras/patterns/shell-surface-elevation-pattern.md +3 -5
  47. package/dist/components/data-table/filter-date-calendar.d.ts +10 -0
  48. package/dist/components/data-table/filter-date-calendar.js +280 -0
  49. package/dist/components/data-table/filter-date-calendar.js.map +1 -0
  50. package/dist/components/data-table/filter-text-value-input.d.ts +15 -0
  51. package/dist/components/data-table/filter-text-value-input.js +561 -0
  52. package/dist/components/data-table/filter-text-value-input.js.map +1 -0
  53. package/dist/components/data-table/index.d.ts +45 -0
  54. package/dist/components/data-table/index.js +3085 -0
  55. package/dist/components/data-table/index.js.map +1 -0
  56. package/dist/components/data-table/pagination.d.ts +28 -0
  57. package/dist/components/data-table/pagination.js +3264 -0
  58. package/dist/components/data-table/pagination.js.map +1 -0
  59. package/dist/components/data-table/types.d.ts +84 -0
  60. package/dist/components/data-table/types.js +3 -0
  61. package/dist/components/data-table/types.js.map +1 -0
  62. package/dist/components/data-table/use-table-state.d.ts +116 -0
  63. package/dist/components/data-table/use-table-state.js +670 -0
  64. package/dist/components/data-table/use-table-state.js.map +1 -0
  65. package/dist/components/data-views/board-card-primitives.d.ts +22 -0
  66. package/dist/components/data-views/board-card-primitives.js +84 -0
  67. package/dist/components/data-views/board-card-primitives.js.map +1 -0
  68. package/dist/components/data-views/data-row-list.d.ts +33 -0
  69. package/dist/components/data-views/data-row-list.js +106 -0
  70. package/dist/components/data-views/data-row-list.js.map +1 -0
  71. package/dist/components/data-views/finder-panel-view.d.ts +54 -0
  72. package/dist/components/data-views/finder-panel-view.js +388 -0
  73. package/dist/components/data-views/finder-panel-view.js.map +1 -0
  74. package/dist/components/data-views/folder-grid-view.d.ts +22 -0
  75. package/dist/components/data-views/folder-grid-view.js +58 -0
  76. package/dist/components/data-views/folder-grid-view.js.map +1 -0
  77. package/dist/components/data-views/hub-table.d.ts +167 -0
  78. package/dist/components/data-views/hub-table.js +5561 -0
  79. package/dist/components/data-views/hub-table.js.map +1 -0
  80. package/dist/components/data-views/index.d.ts +27 -0
  81. package/dist/components/data-views/index.js +6575 -0
  82. package/dist/components/data-views/index.js.map +1 -0
  83. package/dist/components/data-views/list-page-board-card.d.ts +72 -0
  84. package/dist/components/data-views/list-page-board-card.js +264 -0
  85. package/dist/components/data-views/list-page-board-card.js.map +1 -0
  86. package/dist/components/data-views/list-page-board-template.d.ts +24 -0
  87. package/dist/components/data-views/list-page-board-template.js +137 -0
  88. package/dist/components/data-views/list-page-board-template.js.map +1 -0
  89. package/dist/components/data-views/list-page-connected-view-body.d.ts +19 -0
  90. package/dist/components/data-views/list-page-connected-view-body.js +116 -0
  91. package/dist/components/data-views/list-page-connected-view-body.js.map +1 -0
  92. package/dist/components/data-views/list-page-split-details-placeholder.d.ts +14 -0
  93. package/dist/components/data-views/list-page-split-details-placeholder.js +38 -0
  94. package/dist/components/data-views/list-page-split-details-placeholder.js.map +1 -0
  95. package/dist/components/data-views/list-page-split-hub-chrome.d.ts +17 -0
  96. package/dist/components/data-views/list-page-split-hub-chrome.js +54 -0
  97. package/dist/components/data-views/list-page-split-hub-chrome.js.map +1 -0
  98. package/dist/components/data-views/list-page-split-hub-tokens.d.ts +12 -0
  99. package/dist/components/data-views/list-page-split-hub-tokens.js +8 -0
  100. package/dist/components/data-views/list-page-split-hub-tokens.js.map +1 -0
  101. package/dist/components/data-views/list-page-tree-column-header.d.ts +15 -0
  102. package/dist/components/data-views/list-page-tree-column-header.js +22 -0
  103. package/dist/components/data-views/list-page-tree-column-header.js.map +1 -0
  104. package/dist/components/data-views/list-page-tree-panel-shell.d.ts +25 -0
  105. package/dist/components/data-views/list-page-tree-panel-shell.js +146 -0
  106. package/dist/components/data-views/list-page-tree-panel-shell.js.map +1 -0
  107. package/dist/components/data-views/os-folder-glyph.d.ts +35 -0
  108. package/dist/components/data-views/os-folder-glyph.js +104 -0
  109. package/dist/components/data-views/os-folder-glyph.js.map +1 -0
  110. package/dist/components/data-views/outline-tree-menu.d.ts +36 -0
  111. package/dist/components/data-views/outline-tree-menu.js +131 -0
  112. package/dist/components/data-views/outline-tree-menu.js.map +1 -0
  113. package/dist/components/table-properties/column-row.d.ts +22 -0
  114. package/dist/components/table-properties/column-row.js +153 -0
  115. package/dist/components/table-properties/column-row.js.map +1 -0
  116. package/dist/components/table-properties/draggable-list.d.ts +24 -0
  117. package/dist/components/table-properties/draggable-list.js +53 -0
  118. package/dist/components/table-properties/draggable-list.js.map +1 -0
  119. package/dist/components/table-properties/drawer-button.d.ts +110 -0
  120. package/dist/components/table-properties/drawer-button.js +2748 -0
  121. package/dist/components/table-properties/drawer-button.js.map +1 -0
  122. package/dist/components/table-properties/drawer.d.ts +100 -0
  123. package/dist/components/table-properties/drawer.js +2595 -0
  124. package/dist/components/table-properties/drawer.js.map +1 -0
  125. package/dist/components/table-properties/filter-card.d.ts +24 -0
  126. package/dist/components/table-properties/filter-card.js +854 -0
  127. package/dist/components/table-properties/filter-card.js.map +1 -0
  128. package/dist/components/table-properties/index.d.ts +14 -0
  129. package/dist/components/table-properties/index.js +2768 -0
  130. package/dist/components/table-properties/index.js.map +1 -0
  131. package/dist/components/table-properties/sort-card.d.ts +20 -0
  132. package/dist/components/table-properties/sort-card.js +102 -0
  133. package/dist/components/table-properties/sort-card.js.map +1 -0
  134. package/dist/components/templates/dedicated-search-landing-template.d.ts +21 -0
  135. package/dist/components/templates/dedicated-search-landing-template.js +254 -0
  136. package/dist/components/templates/dedicated-search-landing-template.js.map +1 -0
  137. package/dist/components/templates/dedicated-search-results-template.d.ts +15 -0
  138. package/dist/components/templates/dedicated-search-results-template.js +16 -0
  139. package/dist/components/templates/dedicated-search-results-template.js.map +1 -0
  140. package/dist/components/templates/index.d.ts +9 -0
  141. package/dist/components/templates/index.js +2720 -0
  142. package/dist/components/templates/index.js.map +1 -0
  143. package/dist/components/templates/list-page.d.ts +83 -0
  144. package/dist/components/templates/list-page.js +2433 -0
  145. package/dist/components/templates/list-page.js.map +1 -0
  146. package/dist/components/templates/nested-secondary-panel-shell.d.ts +20 -0
  147. package/dist/components/templates/nested-secondary-panel-shell.js +54 -0
  148. package/dist/components/templates/nested-secondary-panel-shell.js.map +1 -0
  149. package/dist/components/ui/accordion.d.ts +10 -0
  150. package/dist/components/ui/accordion.js +74 -0
  151. package/dist/components/ui/accordion.js.map +1 -0
  152. package/dist/components/ui/alert-dialog.d.ts +37 -0
  153. package/dist/components/ui/alert-dialog.js +201 -0
  154. package/dist/components/ui/alert-dialog.js.map +1 -0
  155. package/dist/components/ui/avatar.d.ts +84 -0
  156. package/dist/components/ui/avatar.js +328 -0
  157. package/dist/components/ui/avatar.js.map +1 -0
  158. package/dist/components/ui/badge.d.ts +13 -0
  159. package/dist/components/ui/badge.js +49 -0
  160. package/dist/components/ui/badge.js.map +1 -0
  161. package/dist/components/ui/banner.d.ts +62 -0
  162. package/dist/components/ui/banner.js +364 -0
  163. package/dist/components/ui/banner.js.map +1 -0
  164. package/dist/components/ui/breadcrumb.d.ts +14 -0
  165. package/dist/components/ui/breadcrumb.js +114 -0
  166. package/dist/components/ui/breadcrumb.js.map +1 -0
  167. package/dist/components/ui/button.d.ts +16 -0
  168. package/dist/components/ui/button.js +59 -0
  169. package/dist/components/ui/button.js.map +1 -0
  170. package/dist/components/ui/calendar.d.ts +13 -0
  171. package/dist/components/ui/calendar.js +238 -0
  172. package/dist/components/ui/calendar.js.map +1 -0
  173. package/dist/components/ui/card.d.ts +14 -0
  174. package/dist/components/ui/card.js +102 -0
  175. package/dist/components/ui/card.js.map +1 -0
  176. package/dist/components/ui/chart.d.ts +58 -0
  177. package/dist/components/ui/chart.js +292 -0
  178. package/dist/components/ui/chart.js.map +1 -0
  179. package/dist/components/ui/checkbox.d.ts +23 -0
  180. package/dist/components/ui/checkbox.js +155 -0
  181. package/dist/components/ui/checkbox.js.map +1 -0
  182. package/dist/components/ui/coach-mark.d.ts +27 -0
  183. package/dist/components/ui/coach-mark.js +306 -0
  184. package/dist/components/ui/coach-mark.js.map +1 -0
  185. package/dist/components/ui/collapsible.d.ts +8 -0
  186. package/dist/components/ui/collapsible.js +35 -0
  187. package/dist/components/ui/collapsible.js.map +1 -0
  188. package/dist/components/ui/command.d.ts +36 -0
  189. package/dist/components/ui/command.js +274 -0
  190. package/dist/components/ui/command.js.map +1 -0
  191. package/dist/components/ui/context-menu.d.ts +32 -0
  192. package/dist/components/ui/context-menu.js +245 -0
  193. package/dist/components/ui/context-menu.js.map +1 -0
  194. package/dist/components/ui/date-picker-field.d.ts +38 -0
  195. package/dist/components/ui/date-picker-field.js +550 -0
  196. package/dist/components/ui/date-picker-field.js.map +1 -0
  197. package/dist/components/ui/dialog.d.ts +22 -0
  198. package/dist/components/ui/dialog.js +200 -0
  199. package/dist/components/ui/dialog.js.map +1 -0
  200. package/dist/components/ui/dot-pattern.d.ts +21 -0
  201. package/dist/components/ui/dot-pattern.js +139 -0
  202. package/dist/components/ui/dot-pattern.js.map +1 -0
  203. package/dist/components/ui/drag-handle-grip.d.ts +10 -0
  204. package/dist/components/ui/drag-handle-grip.js +15 -0
  205. package/dist/components/ui/drag-handle-grip.js.map +1 -0
  206. package/dist/components/ui/drawer.d.ts +16 -0
  207. package/dist/components/ui/drawer.js +125 -0
  208. package/dist/components/ui/drawer.js.map +1 -0
  209. package/dist/components/ui/dropdown-menu.d.ts +45 -0
  210. package/dist/components/ui/dropdown-menu.js +353 -0
  211. package/dist/components/ui/dropdown-menu.js.map +1 -0
  212. package/dist/components/ui/export-drawer.d.ts +11 -0
  213. package/dist/components/ui/export-drawer.js +1658 -0
  214. package/dist/components/ui/export-drawer.js.map +1 -0
  215. package/dist/components/ui/field.d.ts +30 -0
  216. package/dist/components/ui/field.js +249 -0
  217. package/dist/components/ui/field.js.map +1 -0
  218. package/dist/components/ui/form.d.ts +28 -0
  219. package/dist/components/ui/form.js +110 -0
  220. package/dist/components/ui/form.js.map +1 -0
  221. package/dist/components/ui/hover-card.d.ts +9 -0
  222. package/dist/components/ui/hover-card.js +43 -0
  223. package/dist/components/ui/hover-card.js.map +1 -0
  224. package/dist/components/ui/input-group.d.ts +20 -0
  225. package/dist/components/ui/input-group.js +219 -0
  226. package/dist/components/ui/input-group.js.map +1 -0
  227. package/dist/components/ui/input-mask.d.ts +39 -0
  228. package/dist/components/ui/input-mask.js +118 -0
  229. package/dist/components/ui/input-mask.js.map +1 -0
  230. package/dist/components/ui/input.d.ts +5 -0
  231. package/dist/components/ui/input.js +30 -0
  232. package/dist/components/ui/input.js.map +1 -0
  233. package/dist/components/ui/kbd.d.ts +20 -0
  234. package/dist/components/ui/kbd.js +45 -0
  235. package/dist/components/ui/kbd.js.map +1 -0
  236. package/dist/components/ui/key-metrics-context.d.ts +19 -0
  237. package/dist/components/ui/key-metrics-context.js +26 -0
  238. package/dist/components/ui/key-metrics-context.js.map +1 -0
  239. package/dist/components/ui/key-metrics.d.ts +131 -0
  240. package/dist/components/ui/key-metrics.js +1015 -0
  241. package/dist/components/ui/key-metrics.js.map +1 -0
  242. package/dist/components/ui/label.d.ts +6 -0
  243. package/dist/components/ui/label.js +28 -0
  244. package/dist/components/ui/label.js.map +1 -0
  245. package/dist/components/ui/list-page-view-frame.d.ts +22 -0
  246. package/dist/components/ui/list-page-view-frame.js +24 -0
  247. package/dist/components/ui/list-page-view-frame.js.map +1 -0
  248. package/dist/components/ui/page-header.d.ts +51 -0
  249. package/dist/components/ui/page-header.js +372 -0
  250. package/dist/components/ui/page-header.js.map +1 -0
  251. package/dist/components/ui/payment-card-fields.d.ts +10 -0
  252. package/dist/components/ui/payment-card-fields.js +80 -0
  253. package/dist/components/ui/payment-card-fields.js.map +1 -0
  254. package/dist/components/ui/popover.d.ts +10 -0
  255. package/dist/components/ui/popover.js +47 -0
  256. package/dist/components/ui/popover.js.map +1 -0
  257. package/dist/components/ui/radio-group.d.ts +29 -0
  258. package/dist/components/ui/radio-group.js +190 -0
  259. package/dist/components/ui/radio-group.js.map +1 -0
  260. package/dist/components/ui/resizable.d.ts +16 -0
  261. package/dist/components/ui/resizable.js +51 -0
  262. package/dist/components/ui/resizable.js.map +1 -0
  263. package/dist/components/ui/scroll-area.d.ts +8 -0
  264. package/dist/components/ui/scroll-area.js +66 -0
  265. package/dist/components/ui/scroll-area.js.map +1 -0
  266. package/dist/components/ui/select.d.ts +18 -0
  267. package/dist/components/ui/select.js +186 -0
  268. package/dist/components/ui/select.js.map +1 -0
  269. package/dist/components/ui/selection-tile-grid.d.ts +52 -0
  270. package/dist/components/ui/selection-tile-grid.js +347 -0
  271. package/dist/components/ui/selection-tile-grid.js.map +1 -0
  272. package/dist/components/ui/separator.d.ts +7 -0
  273. package/dist/components/ui/separator.js +33 -0
  274. package/dist/components/ui/separator.js.map +1 -0
  275. package/dist/components/ui/sheet.d.ts +18 -0
  276. package/dist/components/ui/sheet.js +181 -0
  277. package/dist/components/ui/sheet.js.map +1 -0
  278. package/dist/components/ui/sidebar.d.ts +94 -0
  279. package/dist/components/ui/sidebar.js +805 -0
  280. package/dist/components/ui/sidebar.js.map +1 -0
  281. package/dist/components/ui/skeleton.d.ts +5 -0
  282. package/dist/components/ui/skeleton.js +22 -0
  283. package/dist/components/ui/skeleton.js.map +1 -0
  284. package/dist/components/ui/slider.d.ts +7 -0
  285. package/dist/components/ui/slider.js +66 -0
  286. package/dist/components/ui/slider.js.map +1 -0
  287. package/dist/components/ui/sonner.d.ts +6 -0
  288. package/dist/components/ui/sonner.js +38 -0
  289. package/dist/components/ui/sonner.js.map +1 -0
  290. package/dist/components/ui/status-badge.d.ts +38 -0
  291. package/dist/components/ui/status-badge.js +77 -0
  292. package/dist/components/ui/status-badge.js.map +1 -0
  293. package/dist/components/ui/table.d.ts +13 -0
  294. package/dist/components/ui/table.js +115 -0
  295. package/dist/components/ui/table.js.map +1 -0
  296. package/dist/components/ui/tabs.d.ts +15 -0
  297. package/dist/components/ui/tabs.js +93 -0
  298. package/dist/components/ui/tabs.js.map +1 -0
  299. package/dist/components/ui/textarea.d.ts +6 -0
  300. package/dist/components/ui/textarea.js +25 -0
  301. package/dist/components/ui/textarea.js.map +1 -0
  302. package/dist/components/ui/tip.d.ts +12 -0
  303. package/dist/components/ui/tip.js +61 -0
  304. package/dist/components/ui/tip.js.map +1 -0
  305. package/dist/components/ui/toggle-group.d.ts +14 -0
  306. package/dist/components/ui/toggle-group.js +104 -0
  307. package/dist/components/ui/toggle-group.js.map +1 -0
  308. package/dist/components/ui/toggle-switch.d.ts +10 -0
  309. package/dist/components/ui/toggle-switch.js +33 -0
  310. package/dist/components/ui/toggle-switch.js.map +1 -0
  311. package/dist/components/ui/toggle.d.ts +13 -0
  312. package/dist/components/ui/toggle.js +51 -0
  313. package/dist/components/ui/toggle.js.map +1 -0
  314. package/dist/components/ui/tooltip.d.ts +10 -0
  315. package/dist/components/ui/tooltip.js +68 -0
  316. package/dist/components/ui/tooltip.js.map +1 -0
  317. package/dist/components/ui/view-segmented-control.d.ts +31 -0
  318. package/dist/components/ui/view-segmented-control.js +167 -0
  319. package/dist/components/ui/view-segmented-control.js.map +1 -0
  320. package/dist/data-list-view-registry-CyBoBML4.d.ts +73 -0
  321. package/dist/hooks/use-app-theme.d.ts +24 -0
  322. package/dist/hooks/use-app-theme.js +286 -0
  323. package/dist/hooks/use-app-theme.js.map +1 -0
  324. package/dist/hooks/use-coach-mark.d.ts +86 -0
  325. package/dist/hooks/use-coach-mark.js +218 -0
  326. package/dist/hooks/use-coach-mark.js.map +1 -0
  327. package/dist/hooks/use-mobile.d.ts +3 -0
  328. package/dist/hooks/use-mobile.js +29 -0
  329. package/dist/hooks/use-mobile.js.map +1 -0
  330. package/dist/hooks/use-mod-key-label.d.ts +6 -0
  331. package/dist/hooks/use-mod-key-label.js +25 -0
  332. package/dist/hooks/use-mod-key-label.js.map +1 -0
  333. package/dist/index.d.ts +120 -0
  334. package/dist/index.js +13324 -0
  335. package/dist/index.js.map +1 -0
  336. package/dist/lib/compose-refs.d.ts +6 -0
  337. package/dist/lib/compose-refs.js +17 -0
  338. package/dist/lib/compose-refs.js.map +1 -0
  339. package/dist/lib/conditional-rule-match.d.ts +30 -0
  340. package/dist/lib/conditional-rule-match.js +66 -0
  341. package/dist/lib/conditional-rule-match.js.map +1 -0
  342. package/dist/lib/data-list-display-options.d.ts +26 -0
  343. package/dist/lib/data-list-display-options.js +14 -0
  344. package/dist/lib/data-list-display-options.js.map +1 -0
  345. package/dist/lib/data-list-view-registry.d.ts +2 -0
  346. package/dist/lib/data-list-view-registry.js +102 -0
  347. package/dist/lib/data-list-view-registry.js.map +1 -0
  348. package/dist/lib/data-list-view-surface.d.ts +2 -0
  349. package/dist/lib/data-list-view-surface.js +80 -0
  350. package/dist/lib/data-list-view-surface.js.map +1 -0
  351. package/dist/lib/data-list-view.d.ts +21 -0
  352. package/dist/lib/data-list-view.js +25 -0
  353. package/dist/lib/data-list-view.js.map +1 -0
  354. package/dist/lib/date-filter.d.ts +22 -0
  355. package/dist/lib/date-filter.js +61 -0
  356. package/dist/lib/date-filter.js.map +1 -0
  357. package/dist/lib/dev-log.d.ts +8 -0
  358. package/dist/lib/dev-log.js +10 -0
  359. package/dist/lib/dev-log.js.map +1 -0
  360. package/dist/lib/dropdown-menu-surface.d.ts +14 -0
  361. package/dist/lib/dropdown-menu-surface.js +6 -0
  362. package/dist/lib/dropdown-menu-surface.js.map +1 -0
  363. package/dist/lib/editable-target.d.ts +12 -0
  364. package/dist/lib/editable-target.js +12 -0
  365. package/dist/lib/editable-target.js.map +1 -0
  366. package/dist/lib/list-page-table-properties.d.ts +35 -0
  367. package/dist/lib/list-page-table-properties.js +81 -0
  368. package/dist/lib/list-page-table-properties.js.map +1 -0
  369. package/dist/lib/raf-throttle.d.ts +23 -0
  370. package/dist/lib/raf-throttle.js +27 -0
  371. package/dist/lib/raf-throttle.js.map +1 -0
  372. package/dist/lib/row-height.d.ts +16 -0
  373. package/dist/lib/row-height.js +10 -0
  374. package/dist/lib/row-height.js.map +1 -0
  375. package/dist/lib/table-properties-types.d.ts +83 -0
  376. package/dist/lib/table-properties-types.js +19 -0
  377. package/dist/lib/table-properties-types.js.map +1 -0
  378. package/dist/lib/utils.d.ts +5 -0
  379. package/dist/lib/utils.js +11 -0
  380. package/dist/lib/utils.js.map +1 -0
  381. package/package.json +83 -19
  382. package/src/components/data-table/filter-date-calendar.tsx +38 -0
  383. package/src/components/data-table/filter-text-value-input.tsx +77 -0
  384. package/src/components/data-table/index.tsx +1678 -0
  385. package/src/components/data-table/pagination.tsx +255 -0
  386. package/src/components/data-table/types.ts +96 -0
  387. package/src/components/data-table/use-table-state.ts +767 -0
  388. package/src/components/data-views/board-card-primitives.tsx +93 -0
  389. package/src/components/data-views/data-row-list.tsx +183 -0
  390. package/src/components/data-views/finder-panel-view.tsx +405 -0
  391. package/src/components/data-views/folder-grid-view.tsx +86 -0
  392. package/src/components/data-views/hub-table.tsx +498 -0
  393. package/src/components/data-views/index.ts +28 -0
  394. package/src/components/data-views/list-page-board-card.tsx +192 -0
  395. package/src/components/data-views/list-page-board-template.tsx +122 -0
  396. package/src/components/data-views/list-page-connected-view-body.tsx +66 -0
  397. package/src/components/data-views/list-page-split-details-placeholder.tsx +39 -0
  398. package/src/components/data-views/list-page-split-hub-chrome.tsx +60 -0
  399. package/src/components/data-views/list-page-split-hub-tokens.ts +16 -0
  400. package/src/components/data-views/list-page-tree-column-header.tsx +31 -0
  401. package/src/components/data-views/list-page-tree-panel-shell.tsx +91 -0
  402. package/src/components/data-views/os-folder-glyph.tsx +141 -0
  403. package/src/components/data-views/outline-tree-menu.tsx +157 -0
  404. package/src/components/table-properties/column-row.tsx +90 -0
  405. package/src/components/table-properties/draggable-list.ts +54 -0
  406. package/src/components/table-properties/drawer-button.tsx +300 -0
  407. package/src/components/table-properties/drawer.tsx +1148 -0
  408. package/src/components/table-properties/filter-card.tsx +251 -0
  409. package/src/components/table-properties/index.ts +36 -0
  410. package/src/components/table-properties/sort-card.tsx +63 -0
  411. package/src/components/templates/dedicated-search-landing-template.tsx +124 -0
  412. package/src/components/templates/dedicated-search-results-template.tsx +19 -0
  413. package/src/components/templates/index.ts +33 -0
  414. package/src/components/templates/list-page.tsx +602 -0
  415. package/src/components/templates/nested-secondary-panel-shell.tsx +70 -0
  416. package/src/components/ui/accordion.tsx +92 -0
  417. package/src/components/ui/alert-dialog.tsx +221 -0
  418. package/src/components/ui/avatar.tsx +13 -2
  419. package/src/components/ui/banner.tsx +2 -2
  420. package/src/components/ui/button.tsx +4 -4
  421. package/src/components/ui/calendar.tsx +1 -1
  422. package/src/components/ui/coach-mark.tsx +1 -1
  423. package/src/components/ui/context-menu.tsx +291 -0
  424. package/src/components/ui/date-picker-field.tsx +2 -2
  425. package/src/components/ui/dot-pattern.tsx +183 -0
  426. package/src/components/ui/export-drawer.tsx +375 -0
  427. package/src/components/ui/hover-card.tsx +66 -0
  428. package/src/components/ui/key-metrics-context.tsx +78 -0
  429. package/src/components/ui/key-metrics.tsx +1133 -0
  430. package/src/components/ui/list-page-view-frame.tsx +64 -0
  431. package/src/components/ui/page-header.tsx +244 -0
  432. package/src/components/ui/payment-card-fields.tsx +2 -2
  433. package/src/components/ui/resizable.tsx +68 -0
  434. package/src/components/ui/scroll-area.tsx +72 -0
  435. package/src/components/ui/selection-tile-grid.tsx +9 -2
  436. package/src/components/ui/sidebar.tsx +84 -12
  437. package/src/components/ui/slider.tsx +83 -0
  438. package/src/globals.css +2201 -7
  439. package/src/globals.d.ts +20 -0
  440. package/src/index.ts +68 -1
  441. package/src/lib/conditional-rule-match.ts +119 -0
  442. package/src/lib/data-list-display-options.ts +35 -0
  443. package/src/lib/data-list-view-registry.ts +104 -0
  444. package/src/lib/data-list-view-surface.ts +83 -0
  445. package/src/lib/data-list-view.ts +47 -0
  446. package/src/lib/dev-log.ts +10 -0
  447. package/src/lib/editable-target.ts +20 -0
  448. package/src/lib/list-page-table-properties.ts +48 -0
  449. package/src/lib/raf-throttle.ts +45 -0
  450. package/src/lib/row-height.ts +19 -0
  451. package/src/lib/table-properties-types.ts +98 -0
  452. package/template/.cursor/rules/exxat-command-menu.mdc +1 -1
  453. package/template/.cursor/rules/exxat-dashboard-view-charts.mdc +3 -3
  454. package/template/.cursor/rules/exxat-data-tables.mdc +1 -1
  455. package/template/.cursor/rules/exxat-ds-agents.mdc +2 -2
  456. package/template/.cursor/rules/exxat-kbd-shortcuts.mdc +2 -2
  457. package/template/.cursor/rules/exxat-table-properties-drawer.mdc +1 -1
  458. package/template/AGENTS.md +104 -78
  459. package/template/app/(app)/dashboard/loading.tsx +15 -3
  460. package/template/app/(app)/dashboard/page.tsx +14 -2
  461. package/template/app/(app)/examples/page.tsx +0 -2
  462. package/template/app/(app)/layout.tsx +17 -4
  463. package/template/app/(app)/loading.tsx +18 -1
  464. package/template/app/(app)/question-bank/find/page.tsx +1 -2
  465. package/template/app/(app)/question-bank/layout.tsx +1 -1
  466. package/template/app/(app)/question-bank/library/page.tsx +1 -2
  467. package/template/app/(app)/question-bank/list/page.tsx +1 -2
  468. package/template/app/(app)/question-bank/new/page.tsx +15 -20
  469. package/template/app/(app)/question-bank/page.tsx +1 -2
  470. package/template/app/(app)/settings/page.tsx +5 -4
  471. package/template/app/globals.css +14 -16
  472. package/template/components/ask-leo-sidebar.tsx +5 -1
  473. package/template/components/brand-color-picker.tsx +2 -2
  474. package/template/components/charts-overview.tsx +1 -1
  475. package/template/components/compliance-board-view.tsx +142 -0
  476. package/template/components/compliance-client.tsx +92 -0
  477. package/template/components/compliance-page-header.tsx +89 -0
  478. package/template/components/compliance-table.tsx +468 -0
  479. package/template/components/dashboard-report-charts.tsx +1 -1
  480. package/template/components/dashboard-tabs.tsx +1 -1
  481. package/template/components/data-table/filter-date-calendar.tsx +1 -38
  482. package/template/components/data-table/filter-text-value-input.tsx +1 -77
  483. package/template/components/data-table/index.tsx +1 -1634
  484. package/template/components/data-table/pagination.tsx +1 -255
  485. package/template/components/data-table/types.ts +1 -94
  486. package/template/components/data-table/use-table-state.test.ts +420 -0
  487. package/template/components/data-table/use-table-state.ts +1 -758
  488. package/template/components/data-view-dashboard-charts-compliance.tsx +963 -0
  489. package/template/components/data-view-dashboard-charts-team.tsx +971 -0
  490. package/template/components/data-view-dashboard-charts.tsx +1503 -0
  491. package/template/components/data-views/board-card-primitives.tsx +1 -93
  492. package/template/components/data-views/data-row-list.tsx +1 -183
  493. package/template/components/data-views/finder-panel-view.tsx +1 -405
  494. package/template/components/data-views/folder-grid-view.tsx +1 -86
  495. package/template/components/data-views/hub-table.tsx +1 -0
  496. package/template/components/data-views/index.ts +50 -37
  497. package/template/components/data-views/list-page-board-card.tsx +1 -192
  498. package/template/components/data-views/list-page-board-template.tsx +1 -122
  499. package/template/components/data-views/list-page-connected-view-body.tsx +1 -66
  500. package/template/components/data-views/list-page-split-details-placeholder.tsx +1 -39
  501. package/template/components/data-views/list-page-split-hub-chrome.tsx +1 -68
  502. package/template/components/data-views/list-page-split-hub-tokens.ts +1 -16
  503. package/template/components/data-views/list-page-tree-column-header.tsx +1 -31
  504. package/template/components/data-views/list-page-tree-panel-shell.tsx +1 -91
  505. package/template/components/data-views/list-page-view-frame.tsx +5 -53
  506. package/template/components/data-views/os-folder-glyph.tsx +1 -129
  507. package/template/components/data-views/outline-tree-menu.tsx +1 -157
  508. package/template/components/export-drawer.test.tsx +71 -0
  509. package/template/components/export-drawer.tsx +1 -375
  510. package/template/components/exxat-product-logo.tsx +5 -5
  511. package/template/components/hub-tree-panel-view.tsx +2 -2
  512. package/template/components/invite-collaborators-drawer.tsx +3 -3
  513. package/template/components/key-metrics-ask-leo-bridge.tsx +40 -0
  514. package/template/components/key-metrics.tsx +1 -1063
  515. package/template/components/leo-insight-indicator.tsx +2 -2
  516. package/template/components/new-placement-back-btn.tsx +28 -0
  517. package/template/components/new-placement-form.tsx +942 -0
  518. package/template/components/new-question-composer.tsx +456 -408
  519. package/template/components/onboarding/index.ts +9 -0
  520. package/template/components/onboarding/onboarding-01.tsx +1 -1
  521. package/template/components/onboarding/onboarding-02.tsx +1 -1
  522. package/template/components/onboarding/onboarding-03.tsx +1 -1
  523. package/template/components/onboarding/onboarding-04.tsx +1 -1
  524. package/template/components/page-header.tsx +8 -226
  525. package/template/components/placement-board-card.tsx +250 -0
  526. package/template/components/placement-detail.tsx +438 -0
  527. package/template/components/placements-board-view.tsx +397 -0
  528. package/template/components/placements-client.tsx +220 -0
  529. package/template/components/placements-list-view.tsx +124 -0
  530. package/template/components/placements-page-header.tsx +166 -0
  531. package/template/components/placements-table-cells.test.tsx +22 -0
  532. package/template/components/placements-table-cells.tsx +173 -0
  533. package/template/components/placements-table-columns.tsx +210 -0
  534. package/template/components/placements-table.tsx +934 -0
  535. package/template/components/product-switcher.tsx +3 -4
  536. package/template/components/product-wordmark.tsx +2 -1
  537. package/template/components/question-bank-client.tsx +5 -5
  538. package/template/components/question-bank-hub-client.tsx +1 -1
  539. package/template/components/question-bank-new-folder-sheet.tsx +2 -2
  540. package/template/components/question-bank-secondary-nav.tsx +3 -3
  541. package/template/components/question-bank-table.tsx +541 -431
  542. package/template/components/rotations-empty-state.tsx +50 -0
  543. package/template/components/rotations-panel-activator.tsx +8 -0
  544. package/template/components/settings-appearance-card.tsx +3 -4
  545. package/template/components/settings-client.tsx +15 -59
  546. package/template/components/settings-form-row.tsx +4 -9
  547. package/template/components/{app-sidebar-dynamic.tsx → sidebar/app-sidebar-dynamic.tsx} +1 -1
  548. package/template/components/{app-sidebar.tsx → sidebar/app-sidebar.tsx} +59 -74
  549. package/template/components/sidebar/index.ts +16 -0
  550. package/template/components/{secondary-nav.tsx → sidebar/secondary-nav.tsx} +2 -2
  551. package/template/components/{secondary-panel.tsx → sidebar/secondary-panel.tsx} +50 -7
  552. package/template/components/{sidebar-auto-collapse.tsx → sidebar/sidebar-auto-collapse.tsx} +6 -2
  553. package/template/components/{sidebar-shell.tsx → sidebar/sidebar-shell.tsx} +1 -1
  554. package/template/components/site-header.tsx +1 -1
  555. package/template/components/sites-board-view.tsx +67 -0
  556. package/template/components/sites-client.tsx +154 -0
  557. package/template/components/sites-table.tsx +249 -0
  558. package/template/components/table-properties/column-row.tsx +1 -90
  559. package/template/components/table-properties/draggable-list.ts +1 -49
  560. package/template/components/table-properties/drawer-button.tsx +1 -262
  561. package/template/components/table-properties/drawer.tsx +1 -1166
  562. package/template/components/table-properties/filter-card.tsx +1 -251
  563. package/template/components/table-properties/sort-card.tsx +1 -59
  564. package/template/components/table-properties/types.ts +28 -71
  565. package/template/components/team-board-view.tsx +122 -0
  566. package/template/components/team-client.tsx +100 -0
  567. package/template/components/team-page-header.tsx +92 -0
  568. package/template/components/team-table.tsx +553 -0
  569. package/template/components/templates/dedicated-search-landing-template.tsx +1 -124
  570. package/template/components/templates/dedicated-search-results-template.tsx +1 -19
  571. package/template/components/templates/list-page.tsx +1 -608
  572. package/template/components/templates/nested-secondary-panel-shell.tsx +1 -63
  573. package/template/components/templates/new-focus-template.tsx +659 -0
  574. package/template/components/templates/secondary-panel-hub-template.tsx +1 -1
  575. package/template/components/ui/accordion.tsx +1 -0
  576. package/template/components/ui/alert-dialog.tsx +1 -0
  577. package/template/components/ui/context-menu.tsx +1 -0
  578. package/template/components/ui/dot-pattern.tsx +1 -183
  579. package/template/components/ui/hover-card.tsx +1 -0
  580. package/template/components/ui/resizable.tsx +1 -68
  581. package/template/components/ui/scroll-area.tsx +1 -0
  582. package/template/components/ui/slider.tsx +1 -0
  583. package/template/docs/blueprints/README.md +86 -0
  584. package/template/docs/blueprints/_template.md +91 -0
  585. package/template/docs/blueprints/board-card.md +123 -0
  586. package/template/docs/blueprints/data-table.md +139 -0
  587. package/template/docs/blueprints/key-metrics.md +128 -0
  588. package/template/docs/blueprints/list-page-template.md +123 -0
  589. package/template/docs/blueprints/page-header.md +130 -0
  590. package/template/docs/command-menu-pattern.md +1 -1
  591. package/template/docs/component-selection-guide.md +224 -0
  592. package/template/docs/components-audit-2026-05.md +158 -0
  593. package/template/docs/data-views-pattern.md +17 -54
  594. package/template/docs/drawer-vs-dialog-pattern.md +1 -3
  595. package/template/docs/migrations/0001-brand-deep-alias-stabilization.md +95 -0
  596. package/template/docs/migrations/0002-exxat-token-namespace.md +154 -0
  597. package/template/docs/migrations/0003-globals-css-canonical.md +110 -0
  598. package/template/docs/migrations/README.md +100 -0
  599. package/template/docs/migrations/_template.md +64 -0
  600. package/template/docs/shell-surface-elevation-pattern.md +3 -5
  601. package/template/docs/token-taxonomy.md +416 -0
  602. package/template/eslint.config.mjs +27 -0
  603. package/template/hooks/use-secondary-panel-hub-nav.ts +1 -1
  604. package/template/lib/command-menu-config.ts +0 -1
  605. package/template/lib/command-menu-search-data.ts +27 -11
  606. package/template/lib/compliance-supported-views.ts +10 -0
  607. package/template/lib/conditional-rule-match.ts +6 -97
  608. package/template/lib/data-list-display-options.ts +1 -49
  609. package/template/lib/data-list-view-registry.ts +1 -104
  610. package/template/lib/data-list-view-surface.ts +1 -83
  611. package/template/lib/data-list-view.ts +1 -47
  612. package/template/lib/data-view-dashboard-placements-layout.ts +215 -0
  613. package/template/lib/data-view-dashboard-storage.ts +35 -38
  614. package/template/lib/dev-log.ts +1 -8
  615. package/template/lib/editable-target.ts +1 -10
  616. package/template/lib/list-page-table-properties.ts +1 -48
  617. package/template/lib/list-status-badges.ts +97 -4
  618. package/template/lib/mock/compliance-kpi.ts +61 -0
  619. package/template/lib/mock/compliance.ts +146 -0
  620. package/template/lib/mock/navigation.tsx +0 -9
  621. package/template/lib/mock/placements-kpi.ts +134 -0
  622. package/template/lib/mock/placements.ts +176 -0
  623. package/template/lib/mock/sites-directory.ts +16 -0
  624. package/template/lib/mock/sites-kpi.ts +25 -0
  625. package/template/lib/mock/team-kpi.ts +60 -0
  626. package/template/lib/mock/team.ts +118 -0
  627. package/template/lib/placement-board-card-layout.ts +79 -0
  628. package/template/lib/placements-supported-views.ts +12 -0
  629. package/template/lib/question-bank-supported-views.ts +0 -1
  630. package/template/lib/raf-throttle.ts +1 -45
  631. package/template/lib/row-height.ts +4 -10
  632. package/template/lib/sidebar-state-cookie.ts +11 -2
  633. package/template/lib/sites-supported-views.ts +10 -0
  634. package/template/lib/table-state-lifecycle.ts +2 -2
  635. package/template/lib/team-supported-views.ts +10 -0
  636. package/template/package.json +1 -0
  637. package/template/tests/setup.ts +25 -0
  638. package/consumer-extras/AGENTS.md +0 -76
  639. package/consumer-extras/cursor-skills/exxat-consumer-app/SKILL.md +0 -37
  640. package/consumer-extras/cursor-skills/exxat-focused-workflow-page/SKILL.md +0 -57
  641. package/consumer-extras/patterns/consumer-app-pattern.md +0 -39
  642. package/consumer-extras/patterns/focused-workflow-page-pattern.md +0 -84
  643. package/src/components/ui/button-group.tsx +0 -81
  644. package/src/theme.css +0 -16
  645. package/src/tokens/README.md +0 -15
  646. package/src/tokens/base.css +0 -337
  647. package/src/tokens/high-contrast.css +0 -1195
  648. package/src/tokens/layers.css +0 -224
  649. package/src/tokens/tailwind-bridge.css +0 -118
  650. package/src/tokens/themes.css +0 -201
  651. package/template/app/(app)/data-list/layout.tsx +0 -43
  652. package/template/app/(app)/data-list/page.tsx +0 -10
  653. package/template/app/(app)/examples/focused-workflow/page.tsx +0 -5
  654. package/template/components/app-route-loading.tsx +0 -14
  655. package/template/components/dashboard-onboarding-gallery.tsx +0 -13
  656. package/template/components/dashboard-onboarding.tsx +0 -21
  657. package/template/components/data-views/list-page-calendar-view.tsx +0 -593
  658. package/template/components/data-views/list-page-folder-columns-panel.tsx +0 -345
  659. package/template/components/examples/focused-workflow-showcase.tsx +0 -183
  660. package/template/components/list-hub-board-view.tsx +0 -68
  661. package/template/components/list-hub-client.tsx +0 -186
  662. package/template/components/list-hub-list-view.tsx +0 -36
  663. package/template/components/list-hub-panel-activator.tsx +0 -8
  664. package/template/components/list-hub-secondary-nav.tsx +0 -121
  665. package/template/components/list-hub-table.tsx +0 -336
  666. package/template/components/question-bank-folder-columns-panel.tsx +0 -104
  667. package/template/components/question-bank-list-view.tsx +0 -53
  668. package/template/components/secondary-panel/nav-link-rows.tsx +0 -83
  669. package/template/components/secondary-panels/list-hub-panel.tsx +0 -39
  670. package/template/components/secondary-panels/question-bank-panel.tsx +0 -39
  671. package/template/components/secondary-panels/registry.tsx +0 -15
  672. package/template/components/section-cards.tsx +0 -106
  673. package/template/components/templates/focused-workflow-layouts.tsx +0 -448
  674. package/template/components/templates/focused-workflow-page-template.tsx +0 -69
  675. package/template/components/templates/page-loading-shell.tsx +0 -262
  676. package/template/components/ui/button-group.tsx +0 -1
  677. package/template/docs/consumer-app-pattern.md +0 -39
  678. package/template/docs/focused-workflow-page-pattern.md +0 -84
  679. package/template/lib/list-hub-nav.ts +0 -121
  680. package/template/lib/mock/list-hub-directory.ts +0 -27
  681. package/template/lib/mock/list-hub-kpi.ts +0 -27
  682. package/template/lib/page-loading-variant.ts +0 -40
  683. /package/template/components/{getting-started.tsx → onboarding/getting-started.tsx} +0 -0
  684. /package/template/components/{nav-documents.tsx → sidebar/nav-documents.tsx} +0 -0
  685. /package/template/components/{nav-main.tsx → sidebar/nav-main.tsx} +0 -0
  686. /package/template/components/{nav-secondary.tsx → sidebar/nav-secondary.tsx} +0 -0
  687. /package/template/components/{nav-user.tsx → sidebar/nav-user.tsx} +0 -0
  688. /package/template/components/{sidebar-auto-open.tsx → sidebar/sidebar-auto-open.tsx} +0 -0
@@ -0,0 +1,25 @@
1
+ ---
2
+ description: Exxat DS — do not use toast / sonner / transient snackbars for product messaging.
3
+ alwaysApply: true
4
+ ---
5
+
6
+ # Exxat DS — no toast
7
+
8
+ ## MUST NOT
9
+
10
+ - Do **not** use **`toast()`** (e.g. **Sonner**), **snackbar**, or other **transient corner notifications** for product feedback in this app.
11
+ - Do **not** add new imports from **`sonner`** or wire **`Toaster`** for feature surfaces.
12
+
13
+ ## Use instead
14
+
15
+ - **`LocalBanner`** / **`SystemBanner`** for persistent, readable messaging.
16
+ - **Inline status** next to the action (e.g. button label change, subtle text under the control, row-level state).
17
+ - **Dialog / drawer** confirmations when the user must acknowledge an outcome.
18
+
19
+ ## Why
20
+
21
+ Toasts are easy to miss, stack poorly with complex layouts, and behave inconsistently with screen readers and focus. This product standardizes on **banners + inline + dialogs**.
22
+
23
+ ## Authoritative detail
24
+
25
+ - **`apps/web/AGENTS.md` §6.5**
@@ -0,0 +1,23 @@
1
+ ---
2
+ description: Exxat DS — when to use a drawer vs a new page for actions and auxiliary UI.
3
+ alwaysApply: true
4
+ ---
5
+
6
+ # Exxat DS — page vs drawer
7
+
8
+ ## Rule
9
+
10
+ - **Drawer / sheet** — Use when the user needs **the current page’s context** *and* a **quick view**, **quick actions**, or a **short auxiliary flow** (parent list or hub stays meaningful behind the panel).
11
+ - **Dialog (modal)** — Use for **blocking** short confirms/alerts on the **same route** when the hub must not stay interactable — see **`docs/drawer-vs-dialog-pattern.md`**, **`.cursor/rules/exxat-drawer-vs-dialog.mdc`**.
12
+ - **New page (route)** — Use **otherwise**: primary tasks, long-form or multi-step work, or anything that should have its **own URL** / history without the parent page visible.
13
+
14
+ ## Product examples (this repo)
15
+
16
+ - **Drawer-appropriate:** `TablePropertiesDrawer`, `ExportDrawer`, lightweight panels that supplement a hub.
17
+ - **Page-appropriate:** Full placement or settings flows that are the main task, multi-screen wizards.
18
+
19
+ ## Authoritative detail
20
+
21
+ - **`apps/web/AGENTS.md` §6.4**
22
+ - **`apps/web/docs/data-views-pattern.md`** (Page vs drawer)
23
+ - **`apps/web/docs/drawer-vs-dialog-pattern.md`** (drawer vs modal dialog)
@@ -0,0 +1,47 @@
1
+ ---
2
+ description: Exxat DS — avatar + name + email when showing a person; omit email in dense contexts (e.g. board cards).
3
+ alwaysApply: false
4
+ ---
5
+
6
+ # Exxat DS — person identity (name + email)
7
+
8
+ Use this when rendering **a known person** (user, collaborator, author roster row, invitee, etc.) — not anonymous counts or system actors.
9
+
10
+ ## MUST (when email is available)
11
+
12
+ 1. **Primary** — Display name (or given + family name) as the dominant line.
13
+ 2. **Avatar** — Use **`AvatarInitials`** / the same primitives as **`PageHeader`** collaborator stack and **team** roster patterns (initials from display name via **`initialsFromDisplayName`** where applicable).
14
+ 3. **Secondary** — Work email (or login id) on a **muted** second line **under** the name, smaller type (`text-xs` / `text-muted-foreground`), truncated with **`truncate`** / **`min-w-0`** when the container is narrow.
15
+
16
+ ## Context: when **not** to show email
17
+
18
+ Dense or width-constrained surfaces **MUST NOT** squeeze email if it harms scanability or layout:
19
+
20
+ - **Board / kanban cards** — title row, card trailing, or narrow columns: **avatar + name (or initials chip) only**; skip the email line. Prefer a **Tip** on the avatar/name with full email for discovery if the card is interactive.
21
+ - **Icon-only rails** — avatar only + tooltip with name + email.
22
+ - **Single-line table cells** — if the column is not “Person”, only show what fits (e.g. name + Tip); do not wrap email into a second line inside a 1-line cell unless the column is dedicated to identity.
23
+
24
+ ## Table / list / drawer / inspector
25
+
26
+ - **Dedicated person column** or **profile / invite / access** surfaces — show **avatar + name + email** (stacked or name with email below), consistent with **`InviteCollaboratorsDrawer`** and **`PageHeader`** collaboration variant.
27
+ - **Example:** `QuestionBankTable` **Author** — `AvatarInitials`, **primary name** (`text-sm font-medium`), **muted `text-xs` email** with optional `mailto:` (row click does not navigate when the link is used).
28
+
29
+ ## Avatar rows — **never overlapping**
30
+
31
+ When multiple people share a row (face rail, reviewer pile, attendee list, collaborator stack):
32
+
33
+ - **MUST** render avatars **side-by-side** with a small gap (`gap-1` / `gap-1.5`) — same pattern as the **`PageHeader`** collaboration variant.
34
+ - **MUST NOT** overlap avatars (Slack / GitHub face piles with negative margins like `-space-x-2` and ring-on-background separators). Ring contrast is fragile in dark mode, click targets stack, and screen readers announce ambiguous groupings.
35
+ - **`AvatarGroup`** in **`packages/ui`** already ships the non-overlap default (`flex items-center gap-1.5`). Pair with **`AvatarGroupCount`** for the **`+N`** overflow chip, wrapped in a **`Tip`** that names the hidden people. Each visible avatar gets its own **`Tip`** with the person’s name (per **§8.6 (Case B)** in **`AGENTS.md`**).
36
+
37
+ ## MUST NOT
38
+
39
+ - Show raw email as the only visible identifier when a display name exists (unless the product context is strictly technical, e.g. audit log “principal” column).
40
+ - Use a different avatar size/shape for the same person between list and detail without a deliberate density tier.
41
+ - Restore an overlapping face pile by adding back `-space-x-*` / negative margins / `*:ring-*` to **`AvatarGroup`** or any ad-hoc row of avatars.
42
+
43
+ ## See also
44
+
45
+ - **`.cursor/rules/exxat-collaboration-access.mdc`** — face rail, invite sheet, access roster.
46
+ - **`.cursor/skills/exxat-collaboration-access/SKILL.md`**
47
+ - **`apps/web/AGENTS.md`** collaboration + list hub patterns where relevant.
@@ -0,0 +1,52 @@
1
+ ---
2
+ description: Primary sidebar item opens nested SecondaryPanel (Question bank pattern)
3
+ globs: apps/web/components/**/*.tsx
4
+ alwaysApply: false
5
+ ---
6
+
7
+ # Exxat DS — primary nav → secondary panel
8
+
9
+ Some hubs expose **scoped navigation** (All / My / tree / filters) in a **nested panel** between the **icon rail** and **main content** — not as **primary nav child rows**.
10
+
11
+ **Reference:** **Question bank** — **`lib/mock/navigation.tsx`** (`secondaryPanel: "question-bank"`), **`components/app-sidebar.tsx`**, **`components/secondary-panel.tsx`**, **`components/question-bank-panel-activator.tsx`**, **`components/question-bank-secondary-nav.tsx`**, **`lib/question-bank-nav.ts`** (URL scope).
12
+
13
+ ## MUST (wiring)
14
+
15
+ 1. **`NavLinkItem`** — On the **primary** row that should drive the panel, set **`secondaryPanel`** to a **stable string id** (e.g. **`"question-bank"`**). Keep **`url`** pointing at the **hub route**.
16
+ 2. **`SecondaryPanel` registry** — In **`components/secondary-panel.tsx`**, add **`PANELS[id]`** → component that renders **panel chrome** (title, optional search) + **your secondary nav** list. **MUST** keep ids in sync with **`NAV_PRIMARY`**.
17
+ 3. **Auto-open on route** — The hub **`client`** (or layout slot) **MUST** mount **`*PanelActivator`** that calls **`useAutoPanel(id)`** with the **same id**, so deep links and first visit open the panel while the route is mounted (e.g. **`QuestionBankPanelActivator`** + **`beforeSiteHeader`** on **`QuestionBankClient`**).
18
+ 4. **Same-route reopen** — **`AppSidebar`** already calls **`openPanel(secondaryPanel)`** when the user clicks the primary item **again** while already on that **`url`** (prevents no-op navigation). Secondary nav rows that stay on the same path **SHOULD** call **`openPanel`** on click where **Next.js `Link`** would not fire (same **`href`**).
19
+
20
+ ## Surface elevation (brand chrome)
21
+
22
+ The nested panel sits **between** the icon rail and main content. **MUST** use the three-level stack (darkest → lightest):
23
+
24
+ | Level | Surface | Token |
25
+ |-------|---------|--------|
26
+ | **0** | Primary sidebar | `--sidebar` (= `--brand-tint` on product themes) |
27
+ | **1** | Secondary panel | `--secondary-panel-bg` |
28
+ | **2** | Page canvas | `--background` |
29
+
30
+ - **`NestedSecondaryPanelShell`** — **`bg-[var(--secondary-panel-bg)]`**, not **`bg-sidebar`** (same as level 0).
31
+ - **OKLCH** — light: `color-mix(in oklch, var(--background) 40%, var(--brand-tint-light) 60%)`; dark: `color-mix(in oklch, var(--card) 32%, var(--brand-tint) 68%)`. **MUST** follow **active product** (`theme-one`, `theme-prism`, `theme-custom`) — **MUST NOT** hardcode rose for all products.
32
+ - **`ProductProvider`** — `theme-custom` only when stored accent **differs** from product default (`accentOverrideActive`).
33
+
34
+ **Authoritative detail:** **`apps/web/docs/shell-surface-elevation-pattern.md`**.
35
+
36
+ ## SHOULD
37
+
38
+ - Drive **hub scope** from the **URL** (**`useSearchParams`** + helpers like **`parseQuestionBankNav`**) so **refresh**, **share link**, and **breadcrumbs** match the secondary list.
39
+ - Keep **panel content** **Font Awesome**-aligned with the rest of the app (**`.cursor/rules/exxat-fontawesome-icons.mdc`**).
40
+
41
+ ## MUST NOT
42
+
43
+ - Register a **`secondaryPanel`** id in **`NAV_PRIMARY`** **without** a **`PANELS`** entry and a matching **`useAutoPanel`** on the hub — users get a **collapsed sidebar** with **empty** panel space.
44
+ - Use **`secondaryPanel`** for **full** app sections that deserve their **own primary nav rows** — reserve this for **one hub** + **inner scope** UI.
45
+
46
+ ## See also
47
+
48
+ - **`apps/web/AGENTS.md` §4.6** — handbook summary.
49
+ - **`apps/web/docs/shell-surface-elevation-pattern.md`** — OKLCH tokens + product theme.
50
+ - **`.cursor/rules/exxat-question-bank-hub-header.mdc`** — folder-scoped library header **⋯** → **Customize folder** + client-mounted sheet.
51
+ - **`.cursor/rules/exxat-page-vs-drawer.mdc`** — when **drawer** vs **route**; secondary panel is **nav chrome**, not a workflow drawer.
52
+ - **`.cursor/rules/exxat-kpi-flat-band.mdc`** — flat KPI strip (separate from panel fill).
@@ -0,0 +1,28 @@
1
+ ---
2
+ description: Question bank library — folder-scoped hub header More menu must expose Customize folder; sheet on hub client
3
+ globs: apps/web/components/question-bank-*.tsx, packages/ui/template/components/question-bank-*.tsx
4
+ alwaysApply: false
5
+ ---
6
+
7
+ # Exxat DS — Question bank hub header (folder scope)
8
+
9
+ When the question bank library URL is **scoped to a folder** (`parseQuestionBankNav` → **`scope === "folder"`** and **`folderId`** set), users are effectively on a **“folder page”**: the hub title matches that folder, and **global** actions belong in the **`QuestionBankPageHeader`** **⋯ More** menu — not only on per-row or per-tile overflow menus inside a single view tab.
10
+
11
+ **Pattern doc:** **`apps/web/docs/question-bank-hub-header-pattern.md`**. **Handbook:** **`apps/web/AGENTS.md` §4.6** (folder-scoped hub chrome).
12
+
13
+ ## MUST
14
+
15
+ 1. **`QuestionBankPageHeader`** — When **`navState.scope === "folder"`** and **`navState.folderId`** resolves to a row in **`folders`**, pass **`onCustomizeFolder`** so **⋯ More** includes **Customize folder** ( **`fa-wand-magic-sparkles`** + label **Customize folder** ), placed after **Invite people** (collaboration variant) and before **Export**.
16
+ 2. **Hub client** — Mount **`QuestionBankNewFolderSheet`** on the **hub client** (e.g. **`QuestionBankClient`**) next to **`ListPageTemplate`**, driven by local **`open` / `customizingFolder`** state opened from **`onCustomizeFolder`**. **MUST NOT** rely on **`QuestionBankTable`** alone to host the sheet when some view branches (**table**, **list**, **board**, **dashboard**) do not render that sheet — users would lose **Customize folder** on those tabs.
17
+ 3. **`onCreated`** — On save, **`setFolders`** (or equivalent) **maps** the scoped folder **`id`** to updated **`name`**, **`icon`**, **`colorKey`** — same contract as **`QuestionBankTable`** panel/tree customize handlers.
18
+
19
+ ## MUST NOT
20
+
21
+ - Omit **Customize folder** from the header **⋯** when the URL is folder-scoped, expecting users to find it only on secondary-nav tree rows or OS-folder tiles.
22
+ - Mount **only** one customize sheet inside **`QuestionBankTable`** without a **client-level** sheet when the hub uses **`ListPageTemplate`** view tabs that omit that table subtree.
23
+
24
+ ## See also
25
+
26
+ - **`.cursor/rules/exxat-primary-nav-secondary-panel.mdc`** — URL scope + secondary panel.
27
+ - **`.cursor/rules/exxat-collaboration-access.mdc`** — **`variant="collaboration"`** header + **⋯** invite pattern.
28
+ - **`lib/question-bank-nav.ts`** — **`parseQuestionBankNav`**, **`QuestionBankNavState`**.
@@ -0,0 +1,34 @@
1
+ ---
2
+ description: Exxat DS — prefer centralized reusable components; ask the user before new bespoke primitives.
3
+ alwaysApply: true
4
+ ---
5
+
6
+ # Exxat DS — reuse before custom
7
+
8
+ ## MUST
9
+
10
+ 1. **Compose first** — Use existing **`components/ui/`**, **`components/data-views/`**, **`components/templates/`**, **`PageHeader`**, **`ListPageTemplate`**, **`DataTable`**, **`KeyMetrics`**, and patterns in **`AGENTS.md` §9** before writing new layout or interaction chrome.
11
+ 2. **Search the codebase** — Grep or open the nearest hub (Placements, Team, Question bank) for the same UX (toolbar, drawer, metrics, board card, `ListPageViewFrame`, etc.).
12
+ 3. **Extend in place** — Prefer adding a variant, slot, or prop to a shared component over a one-off duplicate under a single route.
13
+
14
+ ## When the tool must ask the user
15
+
16
+ **MUST pause and ask the user** (with a short option list) when, after scanning, **no reasonable reuse** exists and the implementation would add **any** of:
17
+
18
+ - A **new reusable primitive** (new file under `components/` meant for multiple routes), or
19
+ - A **non-trivial bespoke widget** (custom data grid, chart system, modal stack, or parallel design-system fork) that is not already implied by the task.
20
+
21
+ Do **not** silently ship a second stack for the same product pattern (e.g. another “table”, another metrics strip, another sidebar).
22
+
23
+ If the **user or task already explicitly** approved a greenfield component (“build a new X from scratch”), you may proceed without re-asking.
24
+
25
+ ## MUST NOT
26
+
27
+ - Add **route-only copies** of patterns that already live in **`components/`** or **`packages/ui`** without product reason.
28
+ - Introduce **parallel primitives** (second button row, second card shell, second command surface) when an existing one can be parameterized.
29
+
30
+ ## See also
31
+
32
+ - **`apps/web/AGENTS.md` §1** (compose / scan before new UI), **§9** architecture table
33
+ - **`.cursor/rules/exxat-ds-agents.mdc`**
34
+ - **`.cursor/rules/exxat-centralized-list-dataset.mdc`** — one dataset / one presentation path for hubs
@@ -0,0 +1,77 @@
1
+ ---
2
+ description: TablePropertiesDrawer must receive currentView and onViewChange when used with ListPageTemplate view tabs
3
+ alwaysApply: true
4
+ ---
5
+
6
+ # Exxat DS — Table properties + active view
7
+
8
+ **Authoritative detail:** **`apps/web/AGENTS.md` §4.2**.
9
+
10
+ ## Why this exists
11
+
12
+ `TablePropertiesDrawer` uses **`currentView`** (`DataListViewType`) for the first summary row (“Board display” vs “Table display”, matching icons/descriptions) and to show **table-only** vs **board-only** sub-panels. If **`currentView`** is omitted, the drawer assumes **table** — wrong when the tab is **Board**, **List**, or **Dashboard**.
13
+
14
+ ## MUST
15
+
16
+ When **`ListPageTemplate`** drives **`tab.viewType`** and the page renders **`TablePropertiesDrawer`** (directly or via a toolbar slot):
17
+
18
+ 1. Pass **`currentView={view}`** (same value as **`tab.viewType`** passed into your table component).
19
+ 2. Pass **`onViewChange`** from **`renderContent={(tab, updateTab) => ...}`** so the drawer’s view-type tiles stay in sync with the tab:
20
+
21
+ ```tsx
22
+ import { dataListViewIcon, type DataListViewType } from "@/lib/data-list-view"
23
+
24
+ onViewChange={(v: DataListViewType) =>
25
+ updateTab({ viewType: v, icon: dataListViewIcon(v) })
26
+ }
27
+ ```
28
+
29
+ 3. Thread **`view`** and **`onViewChange`** through: **client → table component → drawer toolbar → `TablePropertiesDrawer`**.
30
+
31
+ **Reference implementations:** `components/placements-table.tsx` (`PlacementsTable`), `components/team-client.tsx` + `team-table.tsx`, `components/compliance-client.tsx` + `compliance-table.tsx`.
32
+
33
+ ## Deep-linking into a specific panel
34
+
35
+ `TablePropertiesDrawer` accepts an optional **`initialPanel`** prop so callsites can open the drawer focused on a named panel — `"main"` (default), `"table-display"`, `"filter"`, `"sort"`, `"group"`, `"columns"`, or `"conditional-rules"`. The current built-in use is the **Add Conditional Rule** item in every column header menu, which deep-links to the **Conditional rules** panel.
36
+
37
+ ### MUST
38
+
39
+ 1. **One state pair owns it.** `useTableState` exposes **`sheetInitialPanel`** + **`setSheetInitialPanel`** alongside `sheetOpen` / `setSheetOpen`. Read both in the drawer button; pass **`initialPanel={sheetInitialPanel}`** to `TablePropertiesDrawer`. Reference: `packages/ui/src/components/table-properties/drawer-button.tsx`.
40
+ 2. **The toolbar Properties button MUST clear the deep-link.** Otherwise the next plain "Properties" click re-opens onto whatever panel the previous deep-link set:
41
+
42
+ ```tsx
43
+ onClick={() => {
44
+ setSheetInitialPanel?.(null)
45
+ setSheetOpen(true)
46
+ }}
47
+ ```
48
+
49
+ 3. **Deep-link callsites MUST set panel + open in the same batched setState call.** Two setters in one callback land in one render, so the drawer mounts with `initialPanel` already populated — no panel-flash:
50
+
51
+ ```tsx
52
+ setSheetInitialPanel("conditional-rules")
53
+ setSheetOpen(true)
54
+ ```
55
+
56
+ 4. **From inside a Radix DropdownMenu, queue the action into `onCloseAutoFocus`.** Opening the non-modal Sheet synchronously from `DropdownMenuItem.onSelect` races with the menu close cycle. Use the `columnMenuPendingActionRef` pattern in `packages/ui/src/components/data-table/index.tsx` (or copy it) so the drawer opens after focus has returned to the trigger.
57
+
58
+ ### MUST NOT
59
+
60
+ - Don't introduce a second source of truth for "which panel" — `sheetInitialPanel` is the only deep-link channel. The drawer's internal `sheetPanel` state stays internal.
61
+ - Don't call `setSheetInitialPanel` from a non-deep-link callsite (e.g. a generic "open Properties" toolbar button). Leave it `null` for index opens.
62
+
63
+ ## View-type tile grid is uniformly square
64
+
65
+ The drawer's "View type" tile grid (and the Export drawer's "File format" grid) renders through `SelectionTileGrid` with `interaction="button"` + `labelPlacement="inside"`. The shared `selectionTileClassNames` utility now applies **`aspect-square`** so every tile is the same shape regardless of how many tiles populate the last row of a `grid-cols-N` track. Two-word labels (e.g. "List & details") wrap inside the square because `leading-tight` keeps line height compact.
66
+
67
+ When you compose your own tile-style picker, **prefer the shared `SelectionTileGrid`** (or `selectionTileClassNames` directly) instead of inventing flex/grid wrappers — that's the only way to keep the squares uniform across the system.
68
+
69
+ ## MUST NOT (overall)
70
+
71
+ - Mount **`TablePropertiesDrawer`** on a multi-view list page **without** **`currentView`** when the active view is known from the tab.
72
+ - Omit **`onViewChange`** if the product shows the **view type** control inside Properties (otherwise tiles cannot update the tab).
73
+
74
+ ## See also
75
+
76
+ - **`apps/web/AGENTS.md` §4.2**, **§13** checklist
77
+ - **`.cursor/rules/exxat-list-page-connected-views.mdc`**
@@ -0,0 +1,103 @@
1
+ # Exxat DS — token discipline
2
+
3
+ **Authoritative reference:** [`apps/web/docs/token-taxonomy.md`](mdc:apps/web/docs/token-taxonomy.md).
4
+ **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`).
5
+ **Enforcement:** [`@exxatdesignux/eslint-plugin`](mdc:packages/eslint-plugin-exxat-ds/README.md) (rules `exxat-ds/no-hex-color`, `exxat-ds/no-deprecated-tokens`).
6
+
7
+ Use this rule when adding **any** color, spacing, radius, shadow, or
8
+ transition value to JSX, CSS, or Tailwind class strings.
9
+
10
+ ## MUST
11
+
12
+ 1. **Prefer the Exxat L0 namespace** for new code — `var(--exxat-color-surface-1)`,
13
+ `bg-surface-1`, `bg-brand-1`, `rounded-2`, `--exxat-spacing-4`, … (taxonomy §2.0).
14
+ L1 shadcn names (`--background`, `bg-brand`, `rounded-md`, …) remain as
15
+ back-compat aliases and continue to work — but new product surfaces should
16
+ read in the canonical brand-prefixed namespace.
17
+ 2. **Reach for a semantic token first.** If the value carries semantic intent
18
+ ("danger", "warning", "muted text", "card surface"), use the matching
19
+ token family from §2 of the taxonomy. Never reinvent semantic colors.
20
+ 3. **Use Tailwind utilities backed by tokens** (e.g. `bg-card`,
21
+ `text-muted-foreground`, `border-border-control`, `ring-ring`,
22
+ `bg-chip-2`, `text-chart-4`, **`bg-surface-1`**, **`bg-brand-1`**,
23
+ **`rounded-2`**). The L2 bridges in `globals.css` already wire
24
+ `--color-*` → `var(--*)` so utilities flip with theme + dark mode.
25
+ 3. **Brand accent comes from `--brand-color` / `bg-brand`** (and its family),
26
+ **not** `--primary` / `bg-primary`. Primary is **neutral charcoal** in
27
+ Exxat — see taxonomy §3.
28
+ 4. **Form-field borders** use `--control-border` (or `border-control-3` /
29
+ `border-control-35`) — never `--border` (which is decorative and < 3:1
30
+ contrast). Taxonomy §6.
31
+ 5. **Status chips and badges** route through
32
+ [`lib/list-status-badges.ts`](mdc:apps/web/lib/list-status-badges.ts)
33
+ (`LIST_HUB_STATUS_TINT_*` + `ListHubStatusBadge`) — not direct
34
+ `bg-green-500` / `bg-red-500` / hex literals.
35
+ 6. **KPI tints** route through `--insight-severity-*` (info / warning) — not
36
+ direct chart-color reuse. Trend polarity is set via
37
+ `MetricItem.trendPolarity` ([`exxat-kpi-trends.mdc`](mdc:.cursor/rules/exxat-kpi-trends.mdc)).
38
+ 7. **Scoped surface tokens stay scoped.** `--dt-*` is `DataTable` only,
39
+ `--key-metrics-*` is `KeyMetrics` only, `--leo-*` is Ask Leo only,
40
+ `--secondary-panel-bg` is the nested panel only. Do **not** reuse these
41
+ tokens outside their owning surface.
42
+ 8. **Adding a new token** — Follow the checklist in
43
+ [`token-taxonomy.md` §4](mdc:apps/web/docs/token-taxonomy.md). Declare
44
+ the primitive in `packages/ui/src/globals.css` (canonical CSS), bridge it in the same file's `@theme inline`
45
+ files when Tailwind utilities are needed, document it in the taxonomy,
46
+ and regenerate `tokens/hooks-index.json`.
47
+
48
+ ## MUST NOT
49
+
50
+ 1. **No raw hex / rgb / hsl color literals** in JSX `className` strings,
51
+ inline `style={{...}}`, or `.css` files outside of `globals.css` /
52
+ `globals.css` / theme overrides. The only places hex is legal are:
53
+ - `--theme-color-chrome` (consumed by `<meta name="theme-color">`)
54
+ - Status icon SVG paths that are part of a vendored asset
55
+ - **Documentation** examples (this rule, blueprints, migrations)
56
+ 2. **No raw `oklch(...)` literals** in component code — those belong in
57
+ `globals.css` theme blocks only. If you need a derived value, use
58
+ `color-mix(in oklch, var(--token) <pct>%, var(--other))` inside a token
59
+ declaration, not at the call site.
60
+ 3. **No deprecated tokens.** Inspect
61
+ [`tokens/hooks-index.json`](mdc:packages/ui/tokens/hooks-index.json) —
62
+ any entry with `"deprecated": true` is removed at the version named in
63
+ `deprecatedMessage`. Migrate before the removal window per
64
+ `apps/web/docs/migrations/`.
65
+ 4. **No ad-hoc Tailwind shades** for product chrome (e.g. `bg-slate-50`,
66
+ `text-zinc-600`, `border-gray-200`) when an Exxat semantic equivalent
67
+ exists. Tailwind shade utilities are reserved for transient prototyping
68
+ only; product code uses the semantic tokens.
69
+ 5. **No `text-primary` for the brand accent.** That maps to neutral charcoal
70
+ (see MUST #3).
71
+ 6. **No utility-class typos that look like tokens.** Examples that look
72
+ right but aren't:
73
+ - `bg-brand-color` — that's the *raw L1 name*; the L2 utility is `bg-brand`.
74
+ - `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)]`.
75
+ - `text-foreground-muted` — the token is `--muted-foreground` (note the order).
76
+ 7. **No SLDS tokens** (`--slds-g-color-*`) — see
77
+ [`exxat-no-slds-leakage.mdc`](mdc:.cursor/rules/exxat-no-slds-leakage.mdc).
78
+
79
+ ## Aliases that ARE official
80
+
81
+ Some L2 bridges intentionally use a **shorter alias** than the L1 primitive
82
+ because the long name would be awkward in Tailwind utilities. Use the alias
83
+ form, but be aware of the underlying primitive:
84
+
85
+ | Alias (use in code) | L0 canonical | L1 primitive | Notes |
86
+ |---|---|---|---|
87
+ | `bg-brand` / `text-brand` | `--exxat-color-brand-1` | `--brand-color` | Brand accent |
88
+ | `bg-brand-deep` / `text-brand-deep` | `--exxat-color-brand-deep` | `--brand-color-deep` | Coach marks, hero callouts |
89
+ | `bg-brand-tint` | `--exxat-color-brand-tint-1` | `--brand-tint` | Sidebar wash |
90
+ | `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 |
91
+ | `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) |
92
+
93
+ 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).
94
+
95
+ ## See also
96
+
97
+ - [`apps/web/docs/token-taxonomy.md`](mdc:apps/web/docs/token-taxonomy.md) — full namespace + naming rules
98
+ - [`apps/web/docs/migrations/`](mdc:apps/web/docs/migrations) — deprecation index
99
+ - [`packages/ui/tokens/hooks-index.json`](mdc:packages/ui/tokens/hooks-index.json) — machine-readable
100
+ - [`.cursor/rules/exxat-no-slds-leakage.mdc`](mdc:.cursor/rules/exxat-no-slds-leakage.mdc)
101
+ - [`.cursor/rules/exxat-kpi-trends.mdc`](mdc:.cursor/rules/exxat-kpi-trends.mdc)
102
+ - [`.cursor/rules/exxat-kpi-flat-band.mdc`](mdc:.cursor/rules/exxat-kpi-flat-band.mdc)
103
+ - [`.cursor/rules/exxat-no-toast.mdc`](mdc:.cursor/rules/exxat-no-toast.mdc)
@@ -8,7 +8,7 @@ user-invocable: true
8
8
 
9
9
  Standard target: **WCAG 2.1 Level AA** (and 2.2 where noted).
10
10
 
11
- **Canonical for agents (MUST/MUST NOT, checklist):** `exxat-ds/AGENTS.md` **§8** in the repo (same content summarized there; this skill stays the detailed checklist + product tokens).
11
+ **Canonical for agents (MUST/MUST NOT, checklist):** `apps/web/AGENTS.md` **§8** in the repo (same content summarized there; this skill stays the detailed checklist + product tokens).
12
12
 
13
13
  ## ARIA roles & structure (SC 1.3.1)
14
14
 
@@ -7,7 +7,7 @@ user-invocable: true
7
7
 
8
8
  # Exxat DS — board (kanban) cards
9
9
 
10
- **Canonical MUST/MUST NOT:** **`exxat-ds/AGENTS.md` §4.4** (or **`./AGENTS.md`** when the workspace is the `exxat-ds` app folder only). **Claude:** **`.claude/skills/exxat-board-cards/SKILL.md`** (repo root) or **`exxat-ds/.claude/skills/exxat-board-cards/SKILL.md`** (app-only workspace) — same body as this file. This skill is the **how-to**; the handbook stays the contract.
10
+ **Canonical MUST/MUST NOT:** **`apps/web/AGENTS.md` §4.4** (or **`./AGENTS.md`** when the workspace is the `apps/web/` app folder only). **Claude:** **`.claude/skills/exxat-board-cards/SKILL.md`** (repo root) — same body as this file. This skill is the **how-to**; the handbook stays the contract.
11
11
 
12
12
  ## When to use this skill
13
13
 
@@ -45,7 +45,7 @@ Prefer **two-line blocks** for stacked **primary / secondary** facts so cards ma
45
45
  - **Component:** **`ListHubStatusBadge`** from **`@/components/list-hub-status-badge`** — **`surface="table"`** for **DataTable** cells and **list** rows; **`surface="board"`** inside **`ListPageBoardCardBadgeRow`**. Do not duplicate the shell classes on each page.
46
46
  - Use the **same** maps everywhere for that entity so copy and colors never drift.
47
47
  - **Do not** add **`uppercase`** or **`tracking-wide`** — **sentence / title case**, consistent with **`BoardStatusBadge`** on Placements (`placement-board-card.tsx`).
48
- - **Placements** lifecycle uses **`StatusBadge`** in **`data-list-table-cells.tsx`** — thin wrapper over **`ListHubStatusBadge`** + **`PLACEMENT_STATUS_*`** in **`list-status-badges.ts`** (same visuals as Team / Question bank).
48
+ - **Placements** lifecycle uses **`StatusBadge`** in **`placements-table-cells.tsx`** — thin wrapper over **`ListHubStatusBadge`** + **`PLACEMENT_STATUS_*`** in **`list-status-badges.ts`** (same visuals as Team / Question bank).
49
49
 
50
50
  ## Avatar when mock has no `initials`
51
51
 
@@ -60,18 +60,7 @@ Goal: **one row model**, **one filtered bag** (`tableState.rows`), **one place f
60
60
 
61
61
  ---
62
62
 
63
- ## 6. View registry + connected body (required)
64
-
65
- - [ ] **`lib/<hub>-supported-views.ts`** — same array on **`ListPageTemplate`** (`supportedViewTypes`) and **`TablePropertiesDrawerButton`**.
66
- - [ ] **`ListPageConnectedViewBody`** + **`defineHubViewRenderers(supported, { … })`** — one renderer per **`DataListViewRenderKind`**; missing → **`ListPageViewNotConfigured`** (never silent dashboard).
67
- - [ ] Branch on **`getDataListViewRenderKind(view)`** via the connected body — not long **`if (view === "table")`** chains in the table file.
68
- - [ ] **`lib/data-list-view-registry.ts`** — labels/icons/render kinds stay centralized.
69
-
70
- **Canon:** `docs/data-views-pattern.md` § “View registry and connected bodies”, **`AGENTS.md` §4.1.1**.
71
-
72
- ---
73
-
74
- ## 7. Implementation checklist (new hub or new view)
63
+ ## 6. Implementation checklist (new hub or new view)
75
64
 
76
65
  - [ ] Exactly **one** primary row array shape in **`lib/mock/<entity>.ts`** (or API).
77
66
  - [ ] **`useTableState`** seeded from that array; **child views** receive **`tableState.rows`** (or equivalent), **not** a fresh import of the mock list.
@@ -83,15 +72,15 @@ Goal: **one row model**, **one filtered bag** (`tableState.rows`), **one place f
83
72
 
84
73
  ---
85
74
 
86
- ## 8. Reference implementations
75
+ ## 7. Reference implementations
87
76
 
88
- - **`components/data-list-client.tsx`** + **`data-list-table.tsx`** — Placements pattern.
77
+ - **`components/placements-client.tsx`** + **`placements-table.tsx`** — Placements pattern.
89
78
  - **`components/team-client.tsx`** + **`team-table.tsx`**.
90
79
  - **`components/question-bank-table.tsx`** — multiple **`DataListViewType`** branches sharing **`tableState`** / **`folders`** / **`items`**.
91
80
 
92
81
  ---
93
82
 
94
- ## 9. Centralized presentation (with the same dataset)
83
+ ## 8. Centralized presentation (with the same dataset)
95
84
 
96
85
  **Layout:** Non-table view branches wrap in **`ListPageViewFrame`** (constants in **`list-page-view-frame.tsx`**) — see **`.cursor/rules/exxat-list-page-view-shells.mdc`**.
97
86
 
@@ -19,9 +19,9 @@ description: >
19
19
  ## 1. Project Overview
20
20
 
21
21
  - **Stack:** Next.js 16 (App Router), React, TypeScript, Tailwind CSS, shadcn/ui primitives, Font Awesome icons
22
- - **App root:** `exxat-ds/app/(app)/` — route group that wraps all authenticated pages
23
- - **Single source of truth:** `exxat-ds/AGENTS.md` for full prose explanations; this skill is the actionable summary
24
- - **Companion skills (narrow topics):** `exxat-fontawesome-icons`, `exxat-mono-ids`, `exxat-primary-nav-secondary-panel`, `exxat-centralized-list-dataset`, `exxat-list-page-view-shells`, `exxat-dedicated-search-surfaces`, `exxat-focused-workflow-page`, `exxat-accessibility`, `exxat-board-cards`, `exxat-collaboration-access` — live under `.cursor/skills/`; vetted copies ship with **`@exxatdesignux/ui`** in `consumer-extras/cursor-skills/` after **`pnpm --filter @exxatdesignux/ui vendor:consumer-extras`**.
22
+ - **App root:** `apps/web/app/(app)/` — route group that wraps all authenticated pages
23
+ - **Single source of truth:** `apps/web/AGENTS.md` for full prose explanations; this skill is the actionable summary
24
+ - **Companion skills (narrow topics):** `exxat-fontawesome-icons`, `exxat-mono-ids`, `exxat-primary-nav-secondary-panel`, `exxat-centralized-list-dataset`, `exxat-list-page-view-shells`, `exxat-dedicated-search-surfaces`, `exxat-accessibility`, `exxat-board-cards`, `exxat-collaboration-access` — live under `.cursor/skills/`; vetted copies ship with **`@exxatdesignux/ui`** in `consumer-extras/cursor-skills/` after **`pnpm --filter @exxatdesignux/ui vendor:consumer-extras`**.
25
25
  - **Question bank folder-scoped header (rule + doc):** **`.cursor/rules/exxat-question-bank-hub-header.mdc`** and **`docs/question-bank-hub-header-pattern.md`** — pair with **`exxat-primary-nav-secondary-panel`** when URL **`scope=folder`** drives the hub title.
26
26
  - **Consumer repos (npm install of `@exxatdesignux/ui`):** After a version bump, read **`node_modules/@exxatdesignux/ui/CHANGELOG.md`**, run **`npx --package=@exxatdesignux/ui@latest exxat-ui sync-extras`** so **`docs/exxat-ds/consumer-upgrade-checklist.md`** and Cursor skills match the tarball, and diff the host app against **`node_modules/@exxatdesignux/ui/template/`** for anything new to port (routes, re-exports, AGENTS). Use **`exxat-ui changelog`**, **`exxat-ui update`**, and **`exxat-ui doctor`** for CLI guidance.
27
27
 
@@ -259,21 +259,8 @@ ListPageTemplate
259
259
  ```
260
260
 
261
261
  **Reference implementations:**
262
- - **`apps/web`:** `components/list-hub-client.tsx` + `list-hub-table.tsx`, `question-bank-client.tsx` + `question-bank-table.tsx`
263
- - **`packages/ui/template/`** (ships with npm): `placements-client.tsx` + `placements-table.tsx`, `team-client.tsx` + `team-table.tsx` diff template on upgrade
264
-
265
- ### 4.1 View registry (do not fork `if (view === …)`)
266
-
267
- 1. **`lib/data-list-view.ts`** — `DATA_LIST_VIEW_TILES` (labels/icons).
268
- 2. **`lib/data-list-view-registry.ts`** — `renderKind`, `showsListPageHubMetricsStrip`, `dataListViewTilesForHub`.
269
- 3. **`lib/foo-supported-views.ts`** — `export const FOO_SUPPORTED_VIEWS = ["table", "list", …] as const`.
270
- 4. **`ListPageTemplate`** — `supportedViewTypes={FOO_SUPPORTED_VIEWS}`.
271
- 5. **`foo-table.tsx`** — `ListPageConnectedViewBody` with renderers per kind; **`TablePropertiesDrawerButton`** gets the same **`supportedViewTypes`**.
272
- 6. Generic bodies under **`components/data-views/`** — calendar, board template, folder grid, etc.
273
-
274
- **MUST NOT** default unknown views to dashboard KPIs — missing renderers use **`ListPageViewNotConfigured`**.
275
-
276
- **Narrative:** `docs/data-views-pattern.md` § “View registry and connected bodies”.
262
+ - `components/team-client.tsx` + `components/team-table.tsx` canonical pattern
263
+ - `components/placements-client.tsx` + `components/placements-table.tsx` — Placements (most complete)
277
264
 
278
265
  **Files to create for a new hub page `Foo`:**
279
266
  | File | Purpose |
@@ -281,21 +268,19 @@ ListPageTemplate
281
268
  | `lib/mock/foo.ts` | Mock data + TypeScript interface (12+ rows) |
282
269
  | `lib/mock/foo-kpi.ts` | `fooKpiMetrics()` + `fooKpiInsight()` |
283
270
  | `components/foo-page-header.tsx` | `PageHeader` + primary CTA + ⋯ menu |
284
- | `lib/foo-supported-views.ts` | Views this hub implements (registry allowlist) |
285
- | `components/foo-table.tsx` | `ListPageConnectedViewBody` + `DataTable` + `useTableState` + Properties |
286
- | `components/foo-client.tsx` | `ListPageTemplate` + `supportedViewTypes` |
271
+ | `components/foo-table.tsx` | `DataTable` + `useTableState` + `TablePropertiesDrawer` |
272
+ | `components/foo-client.tsx` | `ListPageTemplate` orchestrator |
287
273
  | `app/(app)/foo/page.tsx` | Thin server component |
288
274
 
289
- **Do not** ship a **nav-linked hub** as an **empty page** or a single “replace this later” paragraph. If the route appears in **`lib/mock/navigation.tsx`**, implement the full hub (mock rows, **`ListPageTemplate`**, connected views per **`exxat-ds/AGENTS.md` §4.1**) unless the product explicitly defines a non-data shell.
275
+ **Do not** ship a **nav-linked hub** as an **empty page** or a single “replace this later” paragraph. If the route appears in **`lib/mock/navigation.tsx`**, implement the full hub (mock rows, **`ListPageTemplate`**, connected views per **`apps/web/AGENTS.md` §4.1**) unless the product explicitly defines a non-data shell.
290
276
 
291
277
  ### Page vs drawer (actions)
292
278
 
293
279
  - **Drawer / sheet** — Use when the user needs **the current page behind them** *and* a **quick view**, **quick actions**, or a **short step** (e.g. properties, export, glance at a row).
294
280
  - **Dialog** — **Blocking** confirm/alert/short choice — **`docs/drawer-vs-dialog-pattern.md`**, **`.cursor/rules/exxat-drawer-vs-dialog.mdc`**.
295
281
  - **New page** — Use **otherwise**: **primary**, **long-form**, **multi-step**, or flows that need their **own URL** without the hub visible.
296
- - **Focused workflow route** — **`FocusedWorkflowPageTemplate`** + **`FocusedWorkflowSingleColumn`** | **`FocusedWorkflowStepForm`** | **`FocusedWorkflowSidebarSections`** | **`FocusedWorkflowEmptyState`** — **`docs/focused-workflow-page-pattern.md`**, **`AGENTS.md` §14**, **`exxat-focused-workflow-page`** skill. **Not** list hubs; **not** Miller columns.
297
282
 
298
- Align with **`exxat-ds/AGENTS.md` §6.4**, **§14**, **`docs/data-views-pattern.md`**, **`docs/drawer-vs-dialog-pattern.md`**, **`docs/focused-workflow-page-pattern.md`**, **`.cursor/rules/exxat-page-vs-drawer.mdc`**, **`.cursor/rules/exxat-drawer-vs-dialog.mdc`**, **`.cursor/rules/exxat-focused-workflow-page.mdc`**.
283
+ Align with **`apps/web/AGENTS.md` §6.4**, **`docs/data-views-pattern.md`**, **`docs/drawer-vs-dialog-pattern.md`**, **`.cursor/rules/exxat-page-vs-drawer.mdc`**, **`.cursor/rules/exxat-drawer-vs-dialog.mdc`**.
299
284
 
300
285
  ---
301
286
 
@@ -311,7 +296,7 @@ Align with **`exxat-ds/AGENTS.md` §6.4**, **§14**, **`docs/data-views-pattern.
311
296
  | `ColumnDef` from `@/components/data-table/types` | Column type |
312
297
  | `FilterFieldDef`, `FilterOperator`, `ConditionalRule` from `@/components/table-properties/types` | Filter types |
313
298
 
314
- **Board (kanban) cards:** Use **`ListPageBoardCard`** and related parts from **`components/data-views/list-page-board-card.tsx`**; **`BoardCardTwoLineBlock`** / **`BoardCardIconRow`** from **`board-card-primitives.tsx`**. **List hub** status (Team, Compliance, Question bank, …): maps in **`lib/list-status-badges.ts`**; render with **`ListHubStatusBadge`** (**`surface="table"`** in table/list, **`surface="board"`** on cards); semantic tints **`LIST_HUB_STATUS_TINT_*`** for new domains; no **`uppercase`**. **Placements** uses **`StatusBadge`** in **`data-list-table-cells.tsx`** (wrapper over **`ListHubStatusBadge`** + **`PLACEMENT_STATUS_*`**). **Full rules:** **`exxat-ds/AGENTS.md` §4.4**, **`.cursor/rules/exxat-board-cards.mdc`**, **`.cursor/skills/exxat-board-cards/SKILL.md`**.
299
+ **Board (kanban) cards:** Use **`ListPageBoardCard`** and related parts from **`components/data-views/list-page-board-card.tsx`**; **`BoardCardTwoLineBlock`** / **`BoardCardIconRow`** from **`board-card-primitives.tsx`**. **List hub** status (Team, Compliance, Question bank, …): maps in **`lib/list-status-badges.ts`**; render with **`ListHubStatusBadge`** (**`surface="table"`** in table/list, **`surface="board"`** on cards); semantic tints **`LIST_HUB_STATUS_TINT_*`** for new domains; no **`uppercase`**. **Placements** uses **`StatusBadge`** in **`placements-table-cells.tsx`** (wrapper over **`ListHubStatusBadge`** + **`PLACEMENT_STATUS_*`**). **Full rules:** **`apps/web/AGENTS.md` §4.4**, **`.cursor/rules/exxat-board-cards.mdc`**, **`.cursor/skills/exxat-board-cards/SKILL.md`**.
315
300
 
316
301
  **Minimum required features on any data list page:**
317
302
  - Search (wire `searchable={displayOptions.showToolbarSearch}`)
@@ -621,7 +606,7 @@ Reference implementations: `new-placement-form.tsx` (Create placement = Enter on
621
606
  - **Natural language / AI:** Product **SHOULD** show **quick results in the palette** when the response fits; use **Ask Leo** (**⌘⌥K**) for **longer or complex** answers.
622
607
  - **Do not** treat the palette as a static link list only—leave room for inline AI results as they ship.
623
608
 
624
- **Details:** `exxat-ds/docs/command-menu-pattern.md`, **`exxat-ds/AGENTS.md` §7.1** (or `./` when the app folder is the workspace root).
609
+ **Details:** `apps/web/docs/command-menu-pattern.md`, **`apps/web/AGENTS.md` §7.1** (or `./` when the app folder is the workspace root).
625
610
 
626
611
  ---
627
612
 
@@ -876,8 +861,8 @@ Copy and complete for every list/table/hub page:
876
861
  - [ ] Sidebar item added to `lib/mock/navigation.tsx` with light/solid icon pair
877
862
  - [ ] **Shell sidebar:** Product header uses **`ExxatProductLogo`**; school **`logoDevUrl`** + **`lib/logo-dev`**; team switcher menu **`!w-max`** (not trigger-width-only); expanded switcher **`h-auto min-h-12`** so school + program lines are not clipped; no **`CollapsibleTrigger` → `SidebarMenuButton` with `tooltip` prop**; child nav uses **popover** on icon rail per **§3.1**
878
863
  - [ ] Hub pages: `ListPageTemplate` + `DataTable` + `useTableState` + `TablePropertiesDrawer`
879
- - [ ] Board view: `ListPageBoardCard` shell + `ListHubStatusBadge` + `list-status-badges` when applicable (`exxat-ds/AGENTS.md` §4.4)
880
- - [ ] New primary hubs: not placeholder-only — full template + data + views (`exxat-ds/AGENTS.md` §4.1)
864
+ - [ ] Board view: `ListPageBoardCard` shell + `ListHubStatusBadge` + `list-status-badges` when applicable (`apps/web/AGENTS.md` §4.4)
865
+ - [ ] New primary hubs: not placeholder-only — full template + data + views (`apps/web/AGENTS.md` §4.1)
881
866
  - [ ] **§6.4:** Parent **context** + quick view/actions → drawer/sheet; primary or long flows → **new page** (`AGENTS.md`, `docs/data-views-pattern.md`)
882
867
  - [ ] No raw `<table>` or `ui/table` for product data lists
883
868
  - [ ] No double horizontal padding around `DataTable`
@@ -1,6 +1,6 @@
1
1
  # Data Table Pattern — Full Implementation Guide
2
2
 
3
- Reference implementation: `components/team-table.tsx` (Team) and `components/data-list-table.tsx` (Placements).
3
+ Reference implementation: `components/team-table.tsx` (Team) and `components/placements-table.tsx` (Placements).
4
4
 
5
5
  ---
6
6
 
@@ -12,7 +12,7 @@ user-invocable: true
12
12
  ## Wiring checklist
13
13
 
14
14
  1. **`lib/mock/navigation.tsx`** — set **`secondaryPanel: "<id>"`** on the primary **`NavLinkItem`**; **`url`** = hub route.
15
- 2. **`components/secondary-panels/registry.tsx`** — add **`SECONDARY_PANELS["<id>"]`** → panel shell (title) + hub-specific nav component (e.g. **`list-hub-panel.tsx`**, **`question-bank-panel.tsx`**). Do not add new hubs inside **`question-bank-*.tsx`**.
15
+ 2. **`components/secondary-panel.tsx`** — add **`PANELS["<id>"]`** → panel shell (title, optional search) + secondary nav component.
16
16
  3. **Hub client** — mount **`*PanelActivator`** with **`useAutoPanel("<id>")`** (same id) for the lifetime of the route (e.g. `QuestionBankPanelActivator`).
17
17
  4. **Data** — keep **one** **`useTableState`** / **`tableState.rows`**; drive scope from **URL** + small helpers (see **`lib/question-bank-nav.ts`**).
18
18
  5. **Folder-scoped hub header (Question bank library)** — When **`scope === "folder"`** in the URL, **`QuestionBankPageHeader`** **⋯ More** includes **Customize folder**; mount **`QuestionBankNewFolderSheet`** on **`QuestionBankClient`** so it works on **all** **`ListPageTemplate`** view tabs — **`.cursor/rules/exxat-question-bank-hub-header.mdc`**, **`docs/question-bank-hub-header-pattern.md`**.
@@ -39,9 +39,7 @@ Custom panel content (anything you register under `PANELS[id]`) should **read `s
39
39
  ## Reference
40
40
 
41
41
  - `components/app-sidebar.tsx` — `openPanel` on same-route primary click.
42
- - `components/secondary-panel.tsx` — `SecondaryPanelProvider`, **high-zoom auto-collapse**.
43
- - `components/secondary-panels/registry.tsx` — **`SECONDARY_PANELS`** map (`question-bank`, `list-hub`, …).
44
- - `lib/list-hub-nav.ts` + `components/list-hub-secondary-nav.tsx` — second hub reference implementation.
42
+ - `components/secondary-panel.tsx` — `SecondaryPanelProvider`, `PANELS` registry, **high-zoom auto-collapse**.
45
43
  - `hooks/use-sidebar-reflow-zoom.ts` — shared zoom / reflow signal.
46
44
  - `components/templates/nested-secondary-panel-shell.tsx` — expanded vs `compact` (icon rail) widths; **`bg-[var(--secondary-panel-bg)]`**.
47
45
  - `app/globals.css` — `--secondary-panel-bg`, `--sidebar`, product **`theme-one`** / **`theme-prism`** blocks.