@exxatdesignux/ui 0.2.18 → 0.2.19

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 (140) hide show
  1. package/CHANGELOG.md +15 -0
  2. package/consumer-extras/AGENTS.md +76 -0
  3. package/consumer-extras/README.md +5 -1
  4. package/consumer-extras/cursor-skills/exxat-centralized-list-dataset/SKILL.md +14 -3
  5. package/consumer-extras/cursor-skills/exxat-consumer-app/SKILL.md +37 -0
  6. package/consumer-extras/cursor-skills/exxat-ds-skill/SKILL.md +21 -6
  7. package/consumer-extras/cursor-skills/exxat-focused-workflow-page/SKILL.md +57 -0
  8. package/consumer-extras/cursor-skills/exxat-primary-nav-secondary-panel/SKILL.md +4 -2
  9. package/consumer-extras/patterns/consumer-app-pattern.md +39 -0
  10. package/consumer-extras/patterns/consumer-upgrade-checklist.md +20 -0
  11. package/consumer-extras/patterns/data-views-pattern.md +40 -3
  12. package/consumer-extras/patterns/focused-workflow-page-pattern.md +84 -0
  13. package/consumer-extras/patterns/shell-surface-elevation-pattern.md +5 -3
  14. package/package.json +2 -1
  15. package/src/components/ui/button-group.tsx +81 -0
  16. package/src/components/ui/button.tsx +4 -4
  17. package/src/globals.css +7 -1858
  18. package/src/theme.css +10 -1126
  19. package/src/tokens/README.md +15 -0
  20. package/src/tokens/base.css +337 -0
  21. package/src/tokens/high-contrast.css +1195 -0
  22. package/src/tokens/layers.css +224 -0
  23. package/src/tokens/tailwind-bridge.css +118 -0
  24. package/src/tokens/themes.css +201 -0
  25. package/template/AGENTS.md +60 -22
  26. package/template/app/(app)/dashboard/loading.tsx +3 -15
  27. package/template/app/(app)/dashboard/page.tsx +2 -14
  28. package/template/app/(app)/data-list/layout.tsx +43 -0
  29. package/template/app/(app)/data-list/page.tsx +2 -2
  30. package/template/app/(app)/examples/focused-workflow/page.tsx +5 -0
  31. package/template/app/(app)/examples/page.tsx +1 -0
  32. package/template/app/(app)/loading.tsx +1 -18
  33. package/template/app/(app)/question-bank/find/page.tsx +2 -1
  34. package/template/app/(app)/question-bank/library/page.tsx +2 -1
  35. package/template/app/(app)/question-bank/list/page.tsx +2 -1
  36. package/template/app/(app)/question-bank/new/page.tsx +15 -23
  37. package/template/app/(app)/question-bank/page.tsx +2 -1
  38. package/template/app/(app)/settings/page.tsx +4 -5
  39. package/template/app/globals.css +7 -1964
  40. package/template/components/app-route-loading.tsx +14 -0
  41. package/template/components/app-sidebar.tsx +70 -55
  42. package/template/components/data-views/index.ts +37 -9
  43. package/template/components/data-views/list-page-calendar-view.tsx +593 -0
  44. package/template/components/data-views/list-page-connected-view-body.tsx +66 -0
  45. package/template/components/data-views/list-page-folder-columns-panel.tsx +345 -0
  46. package/template/components/data-views/list-page-split-hub-chrome.tsx +8 -0
  47. package/template/components/examples/focused-workflow-showcase.tsx +183 -0
  48. package/template/components/list-hub-board-view.tsx +68 -0
  49. package/template/components/list-hub-client.tsx +186 -0
  50. package/template/components/list-hub-list-view.tsx +36 -0
  51. package/template/components/list-hub-panel-activator.tsx +8 -0
  52. package/template/components/list-hub-secondary-nav.tsx +121 -0
  53. package/template/components/list-hub-table.tsx +336 -0
  54. package/template/components/new-question-composer.tsx +6 -24
  55. package/template/components/product-switcher.tsx +3 -2
  56. package/template/components/question-bank-client.tsx +4 -1
  57. package/template/components/question-bank-folder-columns-panel.tsx +104 -0
  58. package/template/components/question-bank-table.tsx +143 -485
  59. package/template/components/secondary-panel/nav-link-rows.tsx +83 -0
  60. package/template/components/secondary-panel.tsx +4 -44
  61. package/template/components/secondary-panels/list-hub-panel.tsx +39 -0
  62. package/template/components/secondary-panels/question-bank-panel.tsx +39 -0
  63. package/template/components/secondary-panels/registry.tsx +15 -0
  64. package/template/components/settings-appearance-card.tsx +3 -2
  65. package/template/components/settings-client.tsx +59 -15
  66. package/template/components/settings-form-row.tsx +9 -4
  67. package/template/components/table-properties/drawer-button.tsx +13 -0
  68. package/template/components/table-properties/drawer.tsx +65 -4
  69. package/template/components/templates/focused-workflow-layouts.tsx +448 -0
  70. package/template/components/templates/focused-workflow-page-template.tsx +69 -0
  71. package/template/components/templates/list-page.tsx +29 -5
  72. package/template/components/templates/nested-secondary-panel-shell.tsx +2 -1
  73. package/template/components/templates/page-loading-shell.tsx +262 -0
  74. package/template/components/ui/button-group.tsx +1 -0
  75. package/template/docs/consumer-app-pattern.md +39 -0
  76. package/template/docs/data-views-pattern.md +40 -3
  77. package/template/docs/drawer-vs-dialog-pattern.md +3 -1
  78. package/template/docs/focused-workflow-page-pattern.md +84 -0
  79. package/template/docs/shell-surface-elevation-pattern.md +5 -3
  80. package/template/lib/command-menu-search-data.ts +11 -27
  81. package/template/lib/data-list-display-options.ts +16 -2
  82. package/template/lib/data-list-view-registry.ts +104 -0
  83. package/template/lib/data-list-view-surface.ts +15 -1
  84. package/template/lib/data-list-view.ts +10 -1
  85. package/template/lib/data-view-dashboard-storage.ts +38 -35
  86. package/template/lib/hub-connected-view-renderers.ts +58 -0
  87. package/template/lib/list-hub-nav.ts +121 -0
  88. package/template/lib/list-hub-supported-views.ts +10 -0
  89. package/template/lib/list-page-table-properties.ts +3 -7
  90. package/template/lib/list-status-badges.ts +4 -97
  91. package/template/lib/mock/list-hub-directory.ts +27 -0
  92. package/template/lib/mock/list-hub-kpi.ts +27 -0
  93. package/template/lib/mock/navigation.tsx +1 -0
  94. package/template/lib/page-loading-variant.ts +40 -0
  95. package/template/lib/question-bank-supported-views.ts +13 -0
  96. package/template/lib/table-state-lifecycle.ts +2 -2
  97. package/template/app/(app)/data-list/[id]/page.tsx +0 -44
  98. package/template/app/(app)/data-list/new/page.tsx +0 -34
  99. package/template/components/compliance-board-view.tsx +0 -142
  100. package/template/components/compliance-client.tsx +0 -92
  101. package/template/components/compliance-list-view.tsx +0 -54
  102. package/template/components/compliance-page-header.tsx +0 -89
  103. package/template/components/compliance-table.tsx +0 -612
  104. package/template/components/data-view-dashboard-charts-compliance.tsx +0 -963
  105. package/template/components/data-view-dashboard-charts-team.tsx +0 -971
  106. package/template/components/data-view-dashboard-charts.tsx +0 -1503
  107. package/template/components/new-placement-back-btn.tsx +0 -28
  108. package/template/components/new-placement-form.tsx +0 -1068
  109. package/template/components/placement-board-card.tsx +0 -262
  110. package/template/components/placement-detail.tsx +0 -438
  111. package/template/components/placements-board-view.tsx +0 -404
  112. package/template/components/placements-client.tsx +0 -252
  113. package/template/components/placements-list-view.tsx +0 -171
  114. package/template/components/placements-page-header.tsx +0 -166
  115. package/template/components/placements-table-cells.test.tsx +0 -22
  116. package/template/components/placements-table-cells.tsx +0 -173
  117. package/template/components/placements-table-columns.tsx +0 -640
  118. package/template/components/placements-table.tsx +0 -1642
  119. package/template/components/rotations-empty-state.tsx +0 -50
  120. package/template/components/rotations-panel-activator.tsx +0 -8
  121. package/template/components/sites-all-client.tsx +0 -154
  122. package/template/components/sites-board-view.tsx +0 -67
  123. package/template/components/sites-list-view.tsx +0 -42
  124. package/template/components/sites-table.tsx +0 -382
  125. package/template/components/team-board-view.tsx +0 -122
  126. package/template/components/team-client.tsx +0 -100
  127. package/template/components/team-list-view.tsx +0 -59
  128. package/template/components/team-page-header.tsx +0 -92
  129. package/template/components/team-table.tsx +0 -693
  130. package/template/lib/data-view-dashboard-placements-layout.ts +0 -215
  131. package/template/lib/mock/compliance-kpi.ts +0 -61
  132. package/template/lib/mock/compliance.ts +0 -146
  133. package/template/lib/mock/placements-kpi.ts +0 -134
  134. package/template/lib/mock/placements.ts +0 -183
  135. package/template/lib/mock/sites-directory.ts +0 -16
  136. package/template/lib/mock/sites-kpi.ts +0 -25
  137. package/template/lib/mock/team-kpi.ts +0 -60
  138. package/template/lib/mock/team.ts +0 -118
  139. package/template/lib/placement-board-card-layout.ts +0 -79
  140. package/template/lib/placement-lifecycle.ts +0 -5
package/CHANGELOG.md CHANGED
@@ -15,6 +15,21 @@ After the user bumps `@exxatdesignux/ui`, do this in order:
15
15
 
16
16
  ---
17
17
 
18
+ ## [0.2.19] - 2026-05-19
19
+
20
+ ### Added
21
+
22
+ - **Design tokens (CSS modules):** Split theme surface into `src/tokens/` (`base.css`, `themes.css`, `high-contrast.css`, `layers.css`, `tailwind-bridge.css`). Entry points `globals.css` / `theme.css` re-export only — **no token value changes**.
23
+ - **Package export:** `@exxatdesignux/ui/tokens/*` for consumers that import token partials alongside Tailwind v4.
24
+
25
+ ### Changed
26
+
27
+ - **Starter `template/`** and **consumer extras:** List hub shell, secondary panel registry, route-aware loading skeletons, focused-workflow settings layout, KPI flat band + shell elevation docs/skills — synced from `apps/web`.
28
+
29
+ ### Chore (monorepo)
30
+
31
+ - Package **`version`** **0.2.19** — publish with tag **`ui-v0.2.19`**.
32
+
18
33
  ## [0.2.18] - 2026-05-19
19
34
 
20
35
  ### Fixed
@@ -0,0 +1,76 @@
1
+ # Exxat DS — consumer app handbook
2
+
3
+ **Purpose:** Guide for **product repositories** that depend on **`@exxatdesignux/ui`** from npm. The monorepo **`apps/web`** app is the full reference implementation; this file is what ships in the package for consumers.
4
+
5
+ **Path after sync:** `docs/exxat-ds/AGENTS-consumer.md` or merge sections into your app handbook via **`exxat-ui sync-extras`**.
6
+
7
+ ---
8
+
9
+ ## 1. How to use this file (for AI agents)
10
+
11
+ 1. **Before** upgrading **`@exxatdesignux/ui`**, read **`consumer-upgrade-checklist.md`** and **`CHANGELOG.md`** in the installed package.
12
+ 2. **Before** adding a **list / table / board hub**, read **`data-views-pattern.md`** (view registry + connected bodies), **`consumer-app-pattern.md`**, and skill **`exxat-centralized-list-dataset`**.
13
+ 3. **Before** a **dedicated form / wizard / settings route**, read **`focused-workflow-page-pattern.md`** and **`exxat-focused-workflow-page`** skill.
14
+ 4. **Before** nested **Library / scope** nav, read **`exxat-primary-nav-secondary-panel`** skill and **`shell-surface-elevation-pattern.md`**.
15
+ 5. Run **`exxat-ui sync-extras`** after every DS version bump so **`.cursor/skills/exxat-*`** match the tarball.
16
+
17
+ ---
18
+
19
+ ## 2. What ships in the package
20
+
21
+ | Artifact | Location in npm | Use |
22
+ |----------|-----------------|-----|
23
+ | Components + tokens | `@exxatdesignux/ui` | Import UI, hooks, CSS |
24
+ | Reference app | `node_modules/@exxatdesignux/ui/template/` | Diff / port routes and hub clients |
25
+ | Cursor skills | `consumer-extras/cursor-skills/` → sync to `.cursor/skills/` | AI checklists |
26
+ | Pattern docs | `consumer-extras/patterns/` → sync to `docs/exxat-ds/` | Human + AI narrative |
27
+
28
+ **`sync-extras` does not** modify your product routes — you port intentionally from **`template/`**.
29
+
30
+ ---
31
+
32
+ ## 3. List hub stack (centralized)
33
+
34
+ **MUST:**
35
+
36
+ - **`lib/mock/<entity>.ts`** — one row type + seed data.
37
+ - **`lib/<hub>-supported-views.ts`** — allowlist shared by **`ListPageTemplate`** and **`TablePropertiesDrawer`**.
38
+ - **`useTableState`** — **`tableState.rows`** feeds table, list, board, dashboard, folder, panel, tree.
39
+ - **`ListPageConnectedViewBody`** + **`defineHubViewRenderers`** — no silent dashboard fallback.
40
+ - **`ListPageViewFrame`** / **`components/data-views/`** for non-table bodies.
41
+
42
+ **MUST NOT:** Second mock array per view; **`ListPageTemplate`** on a dedicated create/edit URL.
43
+
44
+ **Rule/skill (sync from package):** `exxat-centralized-list-dataset`, `exxat-list-page-connected-views`, `exxat-list-page-view-shells`.
45
+
46
+ ---
47
+
48
+ ## 4. Shell elevation
49
+
50
+ | Level | Token |
51
+ |-------|--------|
52
+ | Primary sidebar | `--sidebar` |
53
+ | Secondary panel (Library) | `--secondary-panel-bg` |
54
+ | Page | `--background` |
55
+
56
+ Dark mode secondary panel **MUST** use **`color-mix(… var(--sidebar-accent) …)`**, not light **`--brand-tint`**. See **`shell-surface-elevation-pattern.md`**.
57
+
58
+ ---
59
+
60
+ ## 5. Consumer app checklist (copy for PRs)
61
+
62
+ - [ ] **`@exxatdesignux/ui`** version recorded; **`exxat-ui sync-extras`** run if skills/docs changed.
63
+ - [ ] Template diff reviewed for new **`template/`** files relevant to this feature.
64
+ - [ ] List hub: **`supportedViewTypes`** aligned; **`ListPageConnectedViewBody`**; **`tableState.rows`** everywhere.
65
+ - [ ] Form/wizard route: **`FocusedWorkflowPageTemplate`** (not list hub shell).
66
+ - [ ] Secondary panel: **`--secondary-panel-bg`** on **`NestedSecondaryPanelShell`**; dark mode spot-checked.
67
+ - [ ] Product switcher: collapsed sidebar opens menu (**`SidebarMenuButton` `tooltip`**, not nested Tooltip + DropdownMenu).
68
+ - [ ] No toast — banners / inline / dialog.
69
+
70
+ ---
71
+
72
+ ## 6. See also
73
+
74
+ - **`consumer-app-pattern.md`**
75
+ - **`consumer-upgrade-checklist.md`**
76
+ - Monorepo **`apps/web/AGENTS.md`** (full product handbook when you have the design-system repo)
@@ -8,7 +8,9 @@ touching product routes or pages.
8
8
  |----------------------|-------------------------------------------|
9
9
  | `CHANGELOG.md` (package root) | Stay in `node_modules/…` — read for release notes; **`exxat-ui changelog`** prints it |
10
10
  | `cursor-skills/exxat-*` | `.cursor/skills/exxat-*` (replaced) |
11
- | `patterns/*.md` | `docs/exxat-ds/*.md` (replaced) — includes **`consumer-upgrade-checklist.md`** for upgrades + AI handoff |
11
+ | `patterns/*.md` | `docs/exxat-ds/*.md` (replaced) — includes **`consumer-upgrade-checklist.md`**, **`consumer-app-pattern.md`**, view-registry + shell docs |
12
+ | `AGENTS.md` (this folder) | Copy or merge into your app handbook as **`AGENTS-consumer.md`** |
13
+ | `cursor-skills/exxat-consumer-app` | Consumer-repo checklist (npm install, template diff) |
12
14
 
13
15
  **Components and hooks** still come only from `node_modules/@exxatdesignux/ui`
14
16
  via normal semver installs — `sync-extras` does not copy TS source into your app.
@@ -20,3 +22,5 @@ pnpm --filter @exxatdesignux/ui vendor:consumer-extras
20
22
  ```
21
23
 
22
24
  …then bump `packages/ui` version and publish so consumers get the new bundle.
25
+
26
+ **List-page stack** (registry, `ListPageConnectedViewBody`, `supportedViewTypes`) lives in **`template/`** inside the tarball — not in `@exxatdesignux/ui` component exports. After changing **`apps/web`** or **`packages/ui/template`**, diff both trees and re-publish so consumer apps that copy from **`node_modules/@exxatdesignux/ui/template/`** stay aligned.
@@ -60,7 +60,18 @@ Goal: **one row model**, **one filtered bag** (`tableState.rows`), **one place f
60
60
 
61
61
  ---
62
62
 
63
- ## 6. Implementation checklist (new hub or new view)
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)
64
75
 
65
76
  - [ ] Exactly **one** primary row array shape in **`lib/mock/<entity>.ts`** (or API).
66
77
  - [ ] **`useTableState`** seeded from that array; **child views** receive **`tableState.rows`** (or equivalent), **not** a fresh import of the mock list.
@@ -72,7 +83,7 @@ Goal: **one row model**, **one filtered bag** (`tableState.rows`), **one place f
72
83
 
73
84
  ---
74
85
 
75
- ## 7. Reference implementations
86
+ ## 8. Reference implementations
76
87
 
77
88
  - **`components/data-list-client.tsx`** + **`data-list-table.tsx`** — Placements pattern.
78
89
  - **`components/team-client.tsx`** + **`team-table.tsx`**.
@@ -80,7 +91,7 @@ Goal: **one row model**, **one filtered bag** (`tableState.rows`), **one place f
80
91
 
81
92
  ---
82
93
 
83
- ## 8. Centralized presentation (with the same dataset)
94
+ ## 9. Centralized presentation (with the same dataset)
84
95
 
85
96
  **Layout:** Non-table view branches wrap in **`ListPageViewFrame`** (constants in **`list-page-view-frame.tsx`**) — see **`.cursor/rules/exxat-list-page-view-shells.mdc`**.
86
97
 
@@ -0,0 +1,37 @@
1
+ ---
2
+ name: exxat-consumer-app
3
+ description: Build or upgrade product apps that install @exxatdesignux/ui from npm — sync-extras, diff template/, centralized list hubs, focused workflow routes, shell elevation. Use when working outside the design-system monorepo or after pnpm add @exxatdesignux/ui.
4
+ user-invocable: true
5
+ ---
6
+
7
+ # Exxat DS — consumer app
8
+
9
+ **Pattern:** `consumer-app-pattern.md` (in `docs/exxat-ds/` after sync)
10
+ **Handbook:** `AGENTS-consumer.md` or `consumer-app-pattern.md` parent **`AGENTS.md`** in package extras
11
+ **Upgrade:** `consumer-upgrade-checklist.md`
12
+
13
+ ## When this applies
14
+
15
+ - Repo has **`@exxatdesignux/ui`** in **`package.json`**, not the design-system monorepo **`apps/web`**.
16
+ - Task is **porting** a hub, shell, or route from **`node_modules/@exxatdesignux/ui/template/`**.
17
+
18
+ ## Checklist
19
+
20
+ - [ ] Read installed **`CHANGELOG.md`**; run **`exxat-ui sync-extras`** after bump.
21
+ - [ ] Diff **`template/`** vs your app for the feature (client, table, mocks, layout).
22
+ - [ ] **List hub:** `lib/<hub>-supported-views.ts` + **`ListPageConnectedViewBody`** + **`defineHubViewRenderers`** + one **`useTableState`** row bag.
23
+ - [ ] **Same** `supportedViewTypes` on **`ListPageTemplate`** and **`TablePropertiesDrawer`**.
24
+ - [ ] **Form/wizard/settings URL:** **`FocusedWorkflowPageTemplate`** — not **`ListPageTemplate`**.
25
+ - [ ] **Secondary panel:** `NestedSecondaryPanelShell` + **`--secondary-panel-bg`**; verify **dark mode** (no light rose panel).
26
+ - [ ] **Product switcher (collapsed):** `DropdownMenuTrigger` → **`SidebarMenuButton`** with **`tooltip=`** — do not nest **`Tooltip`** outside **`DropdownMenuTrigger`**.
27
+ - [ ] CSS: import DS globals; product theme classes on **`<html>`** via **`ProductProvider`** pattern from template.
28
+
29
+ ## MUST NOT
30
+
31
+ - Fork **`DataTable`** / view-tab stack when template already has the hub pattern.
32
+ - Import raw **`ENTITY_ROWS`** into folder/board views while the table filters **`useTableState`**.
33
+ - Skip **`exxat-ui sync-extras`** and rely on stale **`.cursor/skills`**.
34
+
35
+ ## Pair with
36
+
37
+ - **`exxat-centralized-list-dataset`**, **`exxat-list-page-view-shells`**, **`exxat-focused-workflow-page`**, **`exxat-primary-nav-secondary-panel`**
@@ -21,7 +21,7 @@ description: >
21
21
  - **Stack:** Next.js 16 (App Router), React, TypeScript, Tailwind CSS, shadcn/ui primitives, Font Awesome icons
22
22
  - **App root:** `exxat-ds/app/(app)/` — route group that wraps all authenticated pages
23
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-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`**.
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`**.
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,8 +259,21 @@ ListPageTemplate
259
259
  ```
260
260
 
261
261
  **Reference implementations:**
262
- - `components/team-client.tsx` + `components/team-table.tsx` canonical pattern
263
- - `components/data-list-client.tsx` + `components/data-list-table.tsx` — Placements (most complete)
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”.
264
277
 
265
278
  **Files to create for a new hub page `Foo`:**
266
279
  | File | Purpose |
@@ -268,8 +281,9 @@ ListPageTemplate
268
281
  | `lib/mock/foo.ts` | Mock data + TypeScript interface (12+ rows) |
269
282
  | `lib/mock/foo-kpi.ts` | `fooKpiMetrics()` + `fooKpiInsight()` |
270
283
  | `components/foo-page-header.tsx` | `PageHeader` + primary CTA + ⋯ menu |
271
- | `components/foo-table.tsx` | `DataTable` + `useTableState` + `TablePropertiesDrawer` |
272
- | `components/foo-client.tsx` | `ListPageTemplate` orchestrator |
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` |
273
287
  | `app/(app)/foo/page.tsx` | Thin server component |
274
288
 
275
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.
@@ -279,8 +293,9 @@ ListPageTemplate
279
293
  - **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).
280
294
  - **Dialog** — **Blocking** confirm/alert/short choice — **`docs/drawer-vs-dialog-pattern.md`**, **`.cursor/rules/exxat-drawer-vs-dialog.mdc`**.
281
295
  - **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.
282
297
 
283
- Align with **`exxat-ds/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`**.
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`**.
284
299
 
285
300
  ---
286
301
 
@@ -0,0 +1,57 @@
1
+ ---
2
+ name: exxat-focused-workflow-page
3
+ description: FocusedWorkflowPageTemplate — dedicated routes for large forms, multi-step wizards, and sectioned settings (single column, steps, sidebar nav). Not list hubs or Miller-column explorers. Use when adding create/edit routes, settings pages, or empty workflow placeholders.
4
+ user-invocable: true
5
+ ---
6
+
7
+ # Exxat DS — focused workflow page
8
+
9
+ **Rule:** `.cursor/rules/exxat-focused-workflow-page.mdc`
10
+ **Doc:** `docs/focused-workflow-page-pattern.md` (app / consumer-extras `patterns/`)
11
+ **Handbook:** `AGENTS.md` §6.4, **§14** checklist
12
+
13
+ ## When to use
14
+
15
+ | Use **focused workflow** | Use something else |
16
+ | --- | --- |
17
+ | Own URL; primary create/edit; multi-step wizard; sectioned settings | **List hub** → `ListPageTemplate` + `DataTable` |
18
+ | Large form that should not sit in a drawer | **Quick hub adjunct** → drawer (`ExportDrawer`, `TablePropertiesDrawer`) |
19
+ | | **Blocking confirm** → dialog |
20
+ | | **Finder / folder columns** → `ListPageSplitHubChrome`, `ListPageFolderColumnsPanel` |
21
+
22
+ ## Checklist
23
+
24
+ - [ ] Route uses **`FocusedWorkflowPageTemplate`** — not raw `SidebarInset` copy-paste; not **`PrimaryPageTemplate`** / **`ListPageTemplate`**.
25
+ - [ ] **`siteHeader`**: `back` or `breadcrumbs` + `title`; parent trail stays in header, not duplicated in body.
26
+ - [ ] **`maxWidth`**: `md` simple forms · `lg` settings / wide fields · `xl` only when justified.
27
+ - [ ] **One body layout** from `focused-workflow-layouts.tsx`:
28
+ - **`FocusedWorkflowSingleColumn`** — default stack
29
+ - **`FocusedWorkflowStepForm`** + **`FocusedWorkflowWizardFooter`** — wizard
30
+ - **`FocusedWorkflowSidebarSections`** — left section nav (`id` on `<section>` matches `sections[].id`)
31
+ - **`FocusedWorkflowEmptyState`** — not configured / coming soon
32
+ - [ ] **Footers:** **`FocusedWorkflowActionFooter`** or **`FocusedWorkflowWizardFooter`** with **`Shortcut`** + **`<Kbd variant="bare">`** in buttons (**`exxat-kbd-shortcuts.mdc`**).
33
+ - [ ] Domain UI in **`*-composer.tsx`** / **`*-client.tsx`**; keep **`FocusedWorkflow*`** names generic (not product-specific).
34
+ - [ ] Long forms: optional **`beforeSiteHeader={<SidebarAutoCollapse />}`** (see `/question-bank/new`).
35
+ - [ ] **No** **`ListPageTemplate`** view tabs, **no** Miller columns, **no** **`ListPageFolderColumnsPanel`** inside this shell.
36
+ - [ ] **No toast** for outcomes — banners, inline, or dialog (**`exxat-no-toast.mdc`**).
37
+
38
+ ## MUST NOT
39
+
40
+ - Ship a **full create/edit wizard** only in a drawer when it needs bookmarkable URL / long focus.
41
+ - Use **`ListPageTemplate`** for a dedicated “new record” route.
42
+ - Name shared templates after one feature (`NewQuestionPageTemplate`, etc.).
43
+
44
+ ## Code pointers
45
+
46
+ | Piece | Path |
47
+ | --- | --- |
48
+ | Shell | `components/templates/focused-workflow-page-template.tsx` |
49
+ | Layouts + footers | `components/templates/focused-workflow-layouts.tsx` |
50
+ | Showcase | `components/examples/focused-workflow-showcase.tsx`, `/examples/focused-workflow` |
51
+ | Single column | `app/(app)/question-bank/new/page.tsx` + `new-question-composer.tsx` |
52
+ | Sidebar sections | `app/(app)/settings/page.tsx` + `settings-client.tsx` |
53
+
54
+ ## Pair with
55
+
56
+ - **`exxat-page-vs-drawer`**, **`exxat-drawer-vs-dialog`**, **`exxat-kbd-shortcuts`**
57
+ - **`exxat-reuse-before-custom`** — extend layouts before forking shell markup
@@ -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-panel.tsx`** — add **`PANELS["<id>"]`** → panel shell (title, optional search) + secondary nav component.
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`**.
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,7 +39,9 @@ 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`, `PANELS` registry, **high-zoom auto-collapse**.
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.
43
45
  - `hooks/use-sidebar-reflow-zoom.ts` — shared zoom / reflow signal.
44
46
  - `components/templates/nested-secondary-panel-shell.tsx` — expanded vs `compact` (icon rail) widths; **`bg-[var(--secondary-panel-bg)]`**.
45
47
  - `app/globals.css` — `--secondary-panel-bg`, `--sidebar`, product **`theme-one`** / **`theme-prism`** blocks.
@@ -0,0 +1,39 @@
1
+ # Consumer app pattern (`@exxatdesignux/ui`)
2
+
3
+ > **Audience:** Product repos that **install** the design system from npm — not the `apps/web` monorepo reference app.
4
+ > **Handbook:** `packages/ui/consumer-extras/AGENTS.md` · **Upgrade:** `consumer-upgrade-checklist.md` · **Skill:** `.cursor/skills/exxat-consumer-app/SKILL.md`
5
+
6
+ ## Intent
7
+
8
+ A **consumer app** composes **`@exxatdesignux/ui`** primitives and copies **patterns** from the published **`template/`** tree. It does **not** fork parallel table stacks, view routers, or shell tokens.
9
+
10
+ ## MUST
11
+
12
+ 1. **Install** — `@exxatdesignux/ui` + peers; import DS CSS once (`@exxatdesignux/ui/globals.css` or documented entry).
13
+ 2. **Sync extras** — After version bumps: `npx --package=@exxatdesignux/ui@latest exxat-ui sync-extras` → `.cursor/skills/exxat-*` + `docs/exxat-ds/*.md`.
14
+ 3. **Diff template** — Compare `node_modules/@exxatdesignux/ui/template/` for new files (layouts, `ListPageConnectedViewBody`, `FocusedWorkflowPageTemplate`, mocks).
15
+ 4. **List hubs** — One **`useTableState`** row bag; **`ListPageConnectedViewBody`** + **`defineHubViewRenderers`**; same **`supportedViewTypes`** on **`ListPageTemplate`** and **`TablePropertiesDrawer`**.
16
+ 5. **Shell tokens** — Sidebar / secondary panel / page elevation via **`--sidebar`**, **`--secondary-panel-bg`**, **`--background`** — see **`shell-surface-elevation-pattern.md`**.
17
+ 6. **Focused workflows** — Dedicated create/edit/settings routes use **`FocusedWorkflowPageTemplate`** — **`focused-workflow-page-pattern.md`**.
18
+
19
+ ## MUST NOT
20
+
21
+ - Copy only components without porting **AGENTS**, **rules**, and **pattern docs** when behavior changes.
22
+ - Ship hub view tabs with long **`if (view === "table")`** chains instead of **`ListPageConnectedViewBody`**.
23
+ - Keep a second mock array per view while the grid uses **`useTableState`**.
24
+ - Set secondary panel to **`bg-sidebar`** or light **`--brand-tint`** mixes in dark mode.
25
+
26
+ ## Checklist (new consumer feature)
27
+
28
+ - [ ] Read **`consumer-upgrade-checklist.md`** for the installed UI version.
29
+ - [ ] Run **`exxat-ui sync-extras`** if skills/patterns are stale.
30
+ - [ ] Find the closest **`template/`** hub or page; port file names and imports to your app paths.
31
+ - [ ] **List hub:** `lib/<hub>-supported-views.ts`, `lib/data-list-view-registry.ts`, `ListPageConnectedViewBody`, centralized **`tableState.rows`**.
32
+ - [ ] **Form route:** `FocusedWorkflowPageTemplate` + one body layout from **`focused-workflow-layouts.tsx`**.
33
+ - [ ] **Nav + secondary panel:** `secondaryPanel` on nav item, `PANELS` registry, `useAutoPanel` — **`exxat-primary-nav-secondary-panel`** skill.
34
+ - [ ] Re-run **`fa:subset-audit`** when adding Font Awesome glyphs.
35
+
36
+ ## See also
37
+
38
+ - Monorepo reference: `apps/web/` (full product demo)
39
+ - **`.cursor/rules/exxat-consumer-app.mdc`** (when working inside a consumer repo that synced rules)
@@ -25,6 +25,26 @@ The npm package includes a full Next.js reference under:
25
25
 
26
26
  Use it when you need to know **what files exist**, **how shims re-export** `@exxatdesignux/ui`, or **what AGENTS / layout** patterns look like for the current release. Porting is manual: diff template vs your repo and apply intentional changes (imports, new components, CSS entrypoints).
27
27
 
28
+ ### List-page view registry (required for data hubs)
29
+
30
+ After upgrading, confirm each hub table uses **`ListPageConnectedViewBody`** (not long **`if (view === …)`** chains) and that these stay aligned:
31
+
32
+ | File | Purpose |
33
+ |------|---------|
34
+ | `lib/data-list-view-registry.ts` | Render kinds + hub KPI strip rules |
35
+ | `lib/<hub>-supported-views.ts` | What the hub can add/switch to |
36
+ | `components/templates/list-page.tsx` | `supportedViewTypes` on Add view + shortcuts |
37
+ | `components/data-views/list-page-connected-view-body.tsx` | View router |
38
+ | `lib/hub-connected-view-renderers.ts` | **`defineHubViewRenderers(supported, { … })`** — dev warnings when a supported view has no body |
39
+ | `components/data-views/list-page-folder-columns-panel.tsx` | Generic Miller columns for **panel** view (hub wrapper for QB colors/actions) |
40
+
41
+ Pass the **same** `supportedViewTypes` array to **`ListPageTemplate`** and **`TablePropertiesDrawerButton`**. Wrap hub renderers with **`defineHubViewRenderers`**. Import **question-bank-only** tree/folder nav from hub files, not the generic **`data-views`** barrel. See **`docs/exxat-ds/data-views-pattern.md`** § “View registry and connected bodies” and **`consumer-app-pattern.md`** for the full consumer-app checklist.
42
+
43
+ ### Shell + sidebar (after DS token changes)
44
+
45
+ - [ ] Dark mode **secondary panel** uses **`--secondary-panel-bg`** from DS globals (sidebar-accent mix) — spot-check Question bank **Library** rail.
46
+ - [ ] Collapsed **product switcher** — **`SidebarMenuButton` `tooltip=`** + **`DropdownMenuTrigger`** only (no outer **`Tooltip`** wrapping the trigger).
47
+
28
48
  ## 4. Dependency and Node
29
49
 
30
50
  - Keep **`@exxatdesignux/ui`** on the same semver your team tested; prefer explicit **`^x.y.z`** or pinned **`x.y.z`**.
@@ -38,6 +38,41 @@ Non-table view branches (e.g. **folder** icon grid, **panel** finder, OS-style f
38
38
 
39
39
  **Handbook:** **`AGENTS.md` §4.5**. **Cursor:** **`.cursor/rules/exxat-list-page-view-shells.mdc`**. **Skill:** **`.cursor/skills/exxat-list-page-view-shells/SKILL.md`**. **Do not** wrap **`DataTable`** in the frame if that stacks padding with the table toolbar (**`AGENTS.md` §5**).
40
40
 
41
+ ## View registry and connected bodies (extensibility)
42
+
43
+ To add a **new view type** without breaking existing hubs:
44
+
45
+ 1. **Register once** — Add a tile in `lib/data-list-view.ts` (`DATA_LIST_VIEW_TILES`). Capabilities (hub KPI strip, render kind) derive automatically in `lib/data-list-view-registry.ts`.
46
+ 2. **Build the body once** — Add or extend a generic surface under `components/data-views/` (e.g. `ListPageCalendarView`). Entity-specific wiring stays in props (`getEventDate`, board `renderCard`), not a second calendar implementation per hub.
47
+ 3. **Declare what each hub supports** — `lib/<hub>-supported-views.ts` exports a `const` array; pass the same array to **`ListPageTemplate`** (`supportedViewTypes`), the hub table (`supportedViewTypes` → `TablePropertiesDrawerButton`), and rely on defaults if omitted. **Add view**, **⌘1–9** shortcuts, and **Properties → View type** tiles all use `dataListViewTilesForHub` / `dataListViewSelectionTilesForHub` so users cannot pick a view the hub never implemented.
48
+ 4. **Route in the hub table with `ListPageConnectedViewBody`** — Switch on **`getDataListViewRenderKind(view)`**, not raw `view === "…"` chains. Pass one renderer per kind the hub supports via **`defineHubViewRenderers(MY_HUB_SUPPORTED_VIEWS, { … })`** (`lib/hub-connected-view-renderers.ts`) so dev builds warn when a supported view has no body. **Do not** use a default branch that renders dashboard/KPIs; missing renderers show `ListPageViewNotConfigured`.
49
+ 5. **Let the template own hub chrome** — `ListPageTemplate` hides the metrics strip on calendar/dashboard via `showsListPageHubMetricsStrip(activeTab.viewType)`. Hub clients pass `showMetrics` only; they do not reimplement per-tab KPI visibility.
50
+ 6. **Panel / Miller columns** — Reuse **`ListPageFolderColumnsPanel`** (`components/data-views/list-page-folder-columns-panel.tsx`) for folder + record columns; hub-specific chrome (folder colors, actions) lives in a thin wrapper (e.g. `QuestionBankFolderColumnsPanel`). **Do not** export question-bank-only tree/folder nav from the generic `data-views` barrel.
51
+
52
+ ```tsx
53
+ // lib/my-hub-supported-views.ts
54
+ export const MY_HUB_SUPPORTED_VIEWS = ["table", "list", "calendar"] as const satisfies readonly DataListViewType[]
55
+
56
+ // my-hub-client.tsx
57
+ <ListPageTemplate supportedViewTypes={MY_HUB_SUPPORTED_VIEWS} showMetrics={showMetrics} … />
58
+
59
+ // my-hub-table.tsx
60
+ import { defineHubViewRenderers } from "@/lib/hub-connected-view-renderers"
61
+
62
+ return (
63
+ <ListPageConnectedViewBody
64
+ view={view}
65
+ hubLabel="My hub"
66
+ renderers={defineHubViewRenderers(MY_HUB_SUPPORTED_VIEWS, {
67
+ "data-table": <DataTable … />,
68
+ "calendar-with-toolbar": toolbarShell(<ListPageCalendarView rows={tableState.rows} getEventDate={…} />),
69
+ })}
70
+ />
71
+ )
72
+ ```
73
+
74
+ **Checklist for a new view type:** registry tile → `data-views/` component → update each `*-supported-views.ts` that should expose it → add renderer in each `*-table.tsx` (via `defineHubViewRenderers`) → Properties drawer copy in `table-properties/drawer.tsx` if needed → `table-state-lifecycle` picks up types via `DATA_LIST_VIEW_TILES` (no separate allowlist).
75
+
41
76
  ## Architecture
42
77
 
43
78
  - **Page shell** — `ListPageTemplate` owns the views toolbar (tabs), optional metrics, and export drawer. Content for the active tab is rendered via `renderContent`.
@@ -146,11 +181,13 @@ Reference: `components/placements-page-header.tsx`, `components/team-page-header
146
181
 
147
182
  **When to use a new page (route):** The flow is **primary**, **long-form**, **multi-step**, or should have its **own URL** / bookmark / history **without** the parent page behind it — e.g. full create/edit, wizards, or detail that *is* the task.
148
183
 
149
- **Rule of thumb:** **Context + quick** **drawer**; **blocking short choice** **dialog**; **otherwise** **new page**.
184
+ **Focused workflow shell:** For dedicated create/edit, wizards, and sectioned settings, use **`FocusedWorkflowPageTemplate`** + layouts in **`focused-workflow-layouts.tsx`** see **`docs/focused-workflow-page-pattern.md`** and **`AGENTS.md` §14**. **Not** for list hubs (**`ListPageTemplate`**) or Miller-column explorers.
185
+
186
+ **Rule of thumb:** **Context + quick** → **drawer**; **blocking short choice** → **dialog**; **primary / long / wizard / settings** → **focused workflow route** (or other dedicated page).
150
187
 
151
188
  **Modal vs side panel (same route):** When the overlay stays on the same URL, prefer **`docs/drawer-vs-dialog-pattern.md`** and **`.cursor/rules/exxat-drawer-vs-dialog.mdc`** — drawers keep the hub visible; dialogs trap focus for confirms.
152
189
 
153
- Canonical rules: **`AGENTS.md` §6.4**, root **`.cursor/rules/exxat-page-vs-drawer.mdc`**, **`.cursor/rules/exxat-drawer-vs-dialog.mdc`**.
190
+ Canonical rules: **`AGENTS.md` §6.4**, **§14**, root **`.cursor/rules/exxat-page-vs-drawer.mdc`**, **`.cursor/rules/exxat-drawer-vs-dialog.mdc`**, **`.cursor/rules/exxat-focused-workflow-page.mdc`**.
154
191
 
155
192
  ---
156
193
 
@@ -170,7 +207,7 @@ When a route is a **primary** destination in nav (main hub for an entity) **and*
170
207
  - [ ] **>10 items** → search, filter, sort, properties (per surface type above).
171
208
  - [ ] **Has data to export** → **More** menu with **Export** + shared `ExportDrawer` pattern.
172
209
  - [ ] **Primary + large / main hub** → `ListPageTemplate`-style shell where applicable.
173
- - [ ] **Page vs drawer vs dialog (§6.4)** — Quick with parent **context** → drawer/sheet; **blocking** confirm → **dialog**; primary or long flows → **new route** (`docs/drawer-vs-dialog-pattern.md`).
210
+ - [ ] **Page vs drawer vs dialog (§6.4)** — Quick with parent **context** → drawer/sheet; **blocking** confirm → **dialog**; primary or long flows → **focused workflow route** (`docs/focused-workflow-page-pattern.md`, **§14**) or other dedicated page (`docs/drawer-vs-dialog-pattern.md`).
174
211
  - [ ] **Primary button** → `Button` default variant (`size="lg"` for parity with Placements), not outline.
175
212
  - [ ] **Dashboard view tab** → `KeyMetrics` + shared KPI helpers from **`tableState.rows`**; no duplicate one-off metric cards.
176
213
  - [ ] **Data view charts** → `ChartFigure` + `chart-keyboard-selection`; layout persistence via **`data-view-dashboard-storage`** (see `AGENTS.md` §4.3).
@@ -0,0 +1,84 @@
1
+ # Focused workflow page (dedicated routes)
2
+
3
+ > **Related:** **`AGENTS.md` §6.4** (page vs drawer vs dialog), **§14** (AI checklist), **`docs/drawer-vs-dialog-pattern.md`**, **`.cursor/rules/exxat-page-vs-drawer.mdc`**, **`.cursor/rules/exxat-focused-workflow-page.mdc`**, **`.cursor/skills/exxat-focused-workflow-page/SKILL.md`**.
4
+
5
+ ## Intent
6
+
7
+ Use **`FocusedWorkflowPageTemplate`** for **large or multi-step work** on its **own route** — create/edit forms, wizards, and sectioned settings. The shell is **narrower** than list hubs and **does not** use Miller-column / split-panel explorers.
8
+
9
+ | Surface | Use instead |
10
+ | --- | --- |
11
+ | Browsable record hubs (table, board, dashboard tabs) | **`PrimaryPageTemplate`** + **`ListPageTemplate`** |
12
+ | Finder / folder columns / split hub chrome | **`ListPageSplitHubChrome`**, **`ListPageFolderColumnsPanel`** |
13
+ | Quick properties or export beside a grid | **Drawer** (`TablePropertiesDrawer`, `ExportDrawer`) |
14
+ | Blocking confirm on the same route | **Dialog** |
15
+
16
+ ## Surface matrix (§6.4)
17
+
18
+ | Need | Drawer | Dialog | **Focused workflow route** |
19
+ | --- | --- | --- | --- |
20
+ | Keep hub visible while acting | Yes | No | No |
21
+ | Own URL / bookmark / history | Rare | No | **Yes** |
22
+ | Multi-step wizard | Cramped | No | **Yes** |
23
+ | Sectioned settings (left nav) | Awkward | No | **Yes** |
24
+ | Short delete confirm | No | **Yes** | Overkill |
25
+
26
+ ## Shell
27
+
28
+ **`FocusedWorkflowPageTemplate`** (`components/templates/focused-workflow-page-template.tsx`):
29
+
30
+ - **`SidebarInset`** + **`SiteHeader`** (breadcrumb back link + title).
31
+ - Centered column: **`max-w-3xl` / `max-w-4xl` / `max-w-5xl`** via **`maxWidth`** (`md` | `lg` | `xl`).
32
+ - Default padding: **`FOCUSED_WORKFLOW_CONTENT_PADDING_CLASS`**.
33
+
34
+ Optional **`beforeSiteHeader`** (e.g. **`SidebarAutoCollapse`** on long forms).
35
+
36
+ ## Body layouts
37
+
38
+ Import from **`components/templates/focused-workflow-layouts.tsx`**:
39
+
40
+ | Layout | When |
41
+ | --- | --- |
42
+ | **`FocusedWorkflowSingleColumn`** | Default stack — header, form sections, footer actions (e.g. question authoring). |
43
+ | **`FocusedWorkflowStepForm`** + **`FocusedWorkflowWizardFooter`** | Multi-step wizard with progress list and sticky footer (placement-style flows). |
44
+ | **`FocusedWorkflowSidebarSections`** | Sectioned form with **left nav rail** (settings-style); put **`id`** on each `<section>` matching **`sections[].id`**. |
45
+ | **`FocusedWorkflowEmptyState`** | Placeholder / not-yet-configured route body. |
46
+ | **`FocusedWorkflowActionFooter`** | Single-step Cancel (Esc) + primary (Enter) without step chrome. |
47
+
48
+ Keyboard: wizard and action footers pair **`Shortcut`** with inline **`<Kbd variant="bare">`** per **`.cursor/rules/exxat-kbd-shortcuts.mdc`**.
49
+
50
+ ## Golden references
51
+
52
+ | Route | Variant |
53
+ | --- | --- |
54
+ | **`/question-bank/new`** | Shell + **`FocusedWorkflowSingleColumn`** + domain composer |
55
+ | **`/settings`** | Shell (`maxWidth="lg"`) + **`FocusedWorkflowSidebarSections`** |
56
+ | **`/examples/focused-workflow`** | Showcase: empty, steps, sidebar (toggle) |
57
+
58
+ ## Wiring checklist (implementers)
59
+
60
+ 1. **Route** under **`app/(app)/…/page.tsx`** — thin server page; heavy UI in a **client** component.
61
+ 2. **`siteHeader`**: **`back`** or **`breadcrumbs`** + **`title`**; avoid duplicating the trail in the body.
62
+ 3. Pick **`maxWidth`**: **`md`** for simple forms, **`lg`** for settings / wide fields.
63
+ 4. Choose **one** body layout; do **not** nest Miller columns or **`ListPageTemplate`** view tabs inside this shell.
64
+ 5. Domain logic stays in **`*-composer.tsx`** / **`*-client.tsx`**; templates stay generic **`FocusedWorkflow*`**.
65
+ 6. Run **§14** in **`AGENTS.md`** when reviewing.
66
+
67
+ ## AI execution checklist (copy for PRs)
68
+
69
+ - [ ] **`FocusedWorkflowPageTemplate`** on the route — not ad-hoc **`SidebarInset`** / list-hub shell.
70
+ - [ ] Correct body variant: **single column** | **step form** | **sidebar sections** | **empty**.
71
+ - [ ] Wizard/action footers use **`Shortcut`** + bare **`Kbd`** in buttons.
72
+ - [ ] **No** list-hub view tabs, **no** folder-column explorer inside the page.
73
+ - [ ] Template/component names remain **generic** (not tied to one entity).
74
+ - [ ] **§6.5** — no toast for product feedback.
75
+
76
+ ## Pair with
77
+
78
+ - **`exxat-page-vs-drawer.mdc`**, **`exxat-drawer-vs-dialog.mdc`**, **`exxat-kbd-shortcuts.mdc`**
79
+ - **`exxat-reuse-before-custom.mdc`** — extend **`focused-workflow-layouts.tsx`** before forking a second shell
80
+
81
+ ## See also
82
+
83
+ - **`components/examples/focused-workflow-showcase.tsx`**
84
+ - **`packages/ui/consumer-extras/patterns/focused-workflow-page-pattern.md`** (npm consumers)
@@ -1,7 +1,7 @@
1
1
  # Shell surface elevation (sidebar · secondary panel · page)
2
2
 
3
3
  > **Tokens:** `app/globals.css` — `--sidebar`, `--secondary-panel-bg`, `--background`, `--brand-tint*`.
4
- > **Shell:** `components/templates/nested-secondary-panel-shell.tsx` — `bg-[var(--secondary-panel-bg)]`.
4
+ > **Shell:** `components/templates/nested-secondary-panel-shell.tsx` — `bg-secondary-panel-bg` + `[data-slot="secondary-panel"]` rule in `globals.css`.
5
5
  > **Cursor:** `.cursor/rules/exxat-primary-nav-secondary-panel.mdc` · `.cursor/skills/exxat-primary-nav-secondary-panel/SKILL.md`
6
6
 
7
7
  ## Stack (back → front)
@@ -24,14 +24,16 @@
24
24
  ## OKLCH formulas (dark)
25
25
 
26
26
  ```css
27
- --secondary-panel-bg: color-mix(in oklch, var(--card) 32%, var(--brand-tint) 68%);
27
+ --secondary-panel-bg: color-mix(in oklch, var(--background) 32%, var(--sidebar-accent) 68%);
28
28
  ```
29
29
 
30
+ **Do not** mix with light-mode **`--brand-tint`** in dark — product theme classes keep a light **`--brand-tint`** for logos/KPI glow; the secondary rail must use **`--sidebar-accent`** so the Library panel stays on-hue and dark.
31
+
30
32
  Per-product **dark** theme blocks (`.theme-one.dark`, `.theme-prism.dark`, …) set **`--brand-tint-light`** where needed so mixes stay on-hue.
31
33
 
32
34
  ## Implementation
33
35
 
34
- - **`NestedSecondaryPanelShell`** — `bg-[var(--secondary-panel-bg)]`, `ring-sidebar-border` (not generic `ring-border` alone).
36
+ - **`NestedSecondaryPanelShell`** — `bg-secondary-panel-bg` (token + `[data-slot="secondary-panel"][data-state="open"]` in `globals.css`), `border-sidebar-border` (not generic `ring-border` alone).
35
37
  - **Do not** set secondary panel to `bg-sidebar` (same as level 0 — loses elevation).
36
38
  - **Do not** use `color-mix(… var(--sidebar) …)` without brand tokens if it drifts from active product theme.
37
39
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@exxatdesignux/ui",
3
- "version": "0.2.18",
3
+ "version": "0.2.19",
4
4
  "description": "Exxat shared design system (components, hooks, tokens). Monorepo setup: clone repo then pnpm bootstrap at workspace root — see github.com/ExxatDesign/Exxat-DS-Workspace README.",
5
5
  "type": "module",
6
6
  "engines": {
@@ -27,6 +27,7 @@
27
27
  },
28
28
  "./globals.css": "./src/globals.css",
29
29
  "./theme.css": "./src/theme.css",
30
+ "./tokens/*": "./src/tokens/*",
30
31
  "./components/*": {
31
32
  "types": "./src/components/ui/*.tsx",
32
33
  "import": "./src/components/ui/*.tsx",