@exxatdesignux/ui 0.5.4 → 0.5.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +18 -0
- package/consumer-extras/cursor-rules/exxat-ds-agents.mdc +16 -3
- package/consumer-extras/cursor-rules/exxat-no-image-pixel-copy.mdc +35 -0
- package/consumer-extras/cursor-rules/exxat-reuse-before-custom.mdc +2 -0
- package/consumer-extras/cursor-rules/exxat-sidebar-shell.mdc +35 -0
- package/consumer-extras/cursor-rules/exxat-ux-discovery-protocol.mdc +122 -0
- package/consumer-extras/cursor-rules/exxat-ux-principles.mdc +186 -0
- package/consumer-extras/cursor-skills/exxat-senior-ux/SKILL.md +145 -0
- package/consumer-extras/cursor-skills/exxat-token-economy/SKILL.md +2 -1
- package/consumer-extras/handbook/reference-implementations.md +2 -0
- package/consumer-extras/patterns/consumer-upgrade-checklist.md +1 -0
- package/consumer-extras/patterns/jobs/README.md +59 -0
- package/consumer-extras/patterns/jobs/record-detail.md +177 -0
- package/consumer-extras/patterns/modern-saas-patterns.md +165 -0
- package/dist/components/data-table/index.js +28 -22
- package/dist/components/data-table/index.js.map +1 -1
- package/dist/components/data-table/pagination.js +28 -22
- package/dist/components/data-table/pagination.js.map +1 -1
- package/dist/components/data-table/use-table-state.js +20 -17
- package/dist/components/data-table/use-table-state.js.map +1 -1
- package/dist/components/data-views/hub-table.js +28 -22
- package/dist/components/data-views/hub-table.js.map +1 -1
- package/dist/components/data-views/index.js +28 -22
- package/dist/components/data-views/index.js.map +1 -1
- package/dist/index.js +28 -22
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
- package/src/components/data-table/index.tsx +10 -6
- package/src/components/data-table/use-table-state.ts +33 -26
- package/template/docs/consumer-upgrade-checklist.md +1 -0
- package/template/docs/jobs/README.md +59 -0
- package/template/docs/jobs/record-detail.md +177 -0
- package/template/docs/modern-saas-patterns.md +165 -0
- package/template/docs/reference-implementations.md +2 -0
- package/template/lib/mock/navigation.tsx +1 -1
- package/tokens/hooks-index.json +2 -2
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,23 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 0.5.6
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- **`DataTable` auto-pin activates reliably** — fixed a layout bug where the inner `<table>` stretched to `w-full`, making `scrollWidth === clientWidth` even when the sum of column widths exceeded the viewport. The table now renders at the natural sum of column widths (`style={{ width: totalWidth }}`); overflow is detected against `totalWidth > clientWidth + 1` inside a `useLayoutEffect` that also observes the inner table via `ResizeObserver`. Columns marked `defaultPin` now pin as soon as the grid actually overflows (matches `<= 0.5.2` behavior).
|
|
8
|
+
- **New consumer agent skill `exxat-senior-ux` (vendored via `sync-extras`)** — the persona every other Exxat DS skill is downstream of. Defines the 5-step protocol (Discovery → Research → Synthesis → Build → Audit), brief format, "ask vs assume" heuristics, and push-back triggers (no `toast()`, no Vaul, no two-filled-CTAs, no pixel-copy, no inventing primitives without ≥ 2 use cases).
|
|
9
|
+
- **New consumer agent rules (vendored via `sync-extras`)** — `exxat-ux-discovery-protocol` (no code without a design brief on new surfaces; question bank per surface type) and `exxat-ux-principles` (20 principles split into P1–P8 always-follow and P9–P20 default-follow-with-stated-reason; each with what / why / when-to-break / anti-pattern). Both `alwaysApply: true`.
|
|
10
|
+
- **New consumer pattern docs (vendored via `sync-extras`)** — `modern-saas-patterns.md` codifies the 12 modern SaaS patterns (M1–M12) the DS works against, cited in briefs by `(Mx)`. New `patterns/jobs/` library with `record-detail.md` as the first canonical job-to-be-done spec (IA diagram, route vs sheet, when to tab, navigation, actions, states, anti-patterns, audit checklist).
|
|
11
|
+
- **`exxat-ds-agents` "Top of stack"** — agents handbook now points at the senior-UX skill, discovery protocol, principles, modern SaaS canon, and jobs library FIRST on any design task.
|
|
12
|
+
|
|
13
|
+
## 0.5.5
|
|
14
|
+
|
|
15
|
+
### Patch Changes
|
|
16
|
+
|
|
17
|
+
- **New consumer agent rules (vendored via `sync-extras`):** `exxat-no-image-pixel-copy` (uploaded screenshots = IA only — never pixel-copy colors/chrome), `exxat-sidebar-shell` (DS `AppSidebar` chrome; no legacy rainbow nav styling).
|
|
18
|
+
- **`exxat-ds-agents` §33–§34**, **`exxat-reuse-before-custom`**, **`exxat-token-economy` Q9** — image discipline + sidebar guardrails wired into pre-flight.
|
|
19
|
+
- **`consumer-upgrade-checklist.md`** and **`reference-implementations.md`** — audit rows for screenshot copying and legacy sidebar anti-patterns.
|
|
20
|
+
|
|
3
21
|
## 0.5.4
|
|
4
22
|
|
|
5
23
|
### Patch Changes
|
|
@@ -11,6 +11,17 @@ alwaysApply: true
|
|
|
11
11
|
|
|
12
12
|
Before implementing or reviewing **list / table / board / dashboard / data-heavy** pages, read **AGENTS.md** (rule precedence, MUST/MUST NOT, file references, §4.1–§4.8, **§6.4** page vs drawer, **§6.5** no toast, §7.1 command palette, §13 checklist). **Before** adding **new shared UI** not covered by existing **`components/`** patterns, read **`exxat-reuse-before-custom.mdc`**.
|
|
13
13
|
|
|
14
|
+
## Top of stack — read FIRST on any design task
|
|
15
|
+
|
|
16
|
+
**`.cursor/skills/exxat-senior-ux/SKILL.md`** is the persona every other rule and skill is downstream of. It defines the **five-step protocol** (Discovery → Research → Synthesis → Build → Audit), the **brief format**, and the **push-back triggers**. Pair with:
|
|
17
|
+
|
|
18
|
+
- **`.cursor/rules/exxat-ux-discovery-protocol.mdc`** — brief-before-code gate + question bank per surface type.
|
|
19
|
+
- **`.cursor/rules/exxat-ux-principles.mdc`** — 20 principles (P1–P20) split into **always-follow (P1–P8)** and **default-follow with stated reason (P9–P20)**. Every deviation MUST be named in the design brief.
|
|
20
|
+
- **`apps/web/docs/modern-saas-patterns.md`** — the 12 modern SaaS patterns (M1–M12) the DS works against; cite by `(Mx)` codes.
|
|
21
|
+
- **`apps/web/docs/jobs/`** — canonical references per **job-to-be-done** (start with `record-detail.md`). If no job doc matches, write one.
|
|
22
|
+
|
|
23
|
+
On any **new** route / page / hub / detail / wizard / settings / dashboard / overlay, output a **design brief** in chat BEFORE writing files. On trivial edits (copy tweaks, single-class restyles, bug fixes), skip the brief.
|
|
24
|
+
|
|
14
25
|
## Non‑negotiables (if anything conflicts, open AGENTS.md §12–§13)
|
|
15
26
|
|
|
16
27
|
1. **Product data lists** → `DataTable` + search + shared filters + `TablePropertiesDrawer` — not raw `<table>` / ui `Table` alone / ad-hoc grids. With **`ListPageTemplate`** view tabs, pass **`currentView`** + **`onViewChange`** into **`TablePropertiesDrawer`** (**`AGENTS.md` §4.2**, **`.cursor/rules/exxat-table-properties-drawer.mdc`**).
|
|
@@ -40,11 +51,13 @@ Before implementing or reviewing **list / table / board / dashboard / data-heavy
|
|
|
40
51
|
25. **No SLDS leakage** — **`.cursor/rules/exxat-no-slds-leakage.mdc`** — no `slds-*` classes, no `<lightning-*>` markup, no SLDS token names, no synthetic-shadow assumptions. ESLint catches via `exxat-ds/no-slds-classes` + `exxat-ds/no-lightning-elements` (from **`@exxatdesignux/eslint-plugin`**).
|
|
41
52
|
26. **Blueprints + selection guide** — **`apps/web/docs/blueprints/`** + **`apps/web/docs/component-selection-guide.md`** — framework-agnostic specs + decision tree across the whole DS. Start there before composing a new hub.
|
|
42
53
|
27. **Migrations** — **`apps/web/docs/migrations/`** — every deprecation gets a numbered entry (`NNNN-<slug>.md`). Token deprecations surface in `tokens/hooks-index.json` as `deprecated: true` and are lint-flagged.
|
|
43
|
-
28. **Hub supported views (Add view parity)** — **`exxat-hub-supported-views.mdc`** + **`
|
|
54
|
+
28. **Hub supported views (Add view parity)** — **`exxat-hub-supported-views.mdc`** + **`apps/web/docs/hub-supported-views-pattern.md`** — **`FULL_HUB_SUPPORTED_VIEWS`** (seven views, same as Library); sync **`ListPageTemplate`** + **`HubTable`**; real renderers per view; **`LibraryTable`** for **`LibraryItem`** catalogs; **`tokens-hub-auxiliary-views.tsx`** for tokens.
|
|
44
55
|
29. **No Vaul** — **`exxat-no-vaul.mdc`** — side panels = **`Sheet`** only; remove **`vaul`** from consumer apps on **`@exxatdesignux/ui@0.5.3+`**.
|
|
45
56
|
30. **Tabs chrome** — **`exxat-tabs-chrome.mdc`** — hub views = **`ListPageTemplate`** toolbar (`w-max`); record tabs = **`TabsList`** `w-fit`, never full-width stretch.
|
|
46
|
-
31. **Page header actions** — **`exxat-page-header-actions.mdc`** — filled primary + outline overflow; no hand-built grey buttons.
|
|
57
|
+
31. **Page header actions** — **`exxat-page-header-actions.mdc`** + **`apps/web/docs/blueprints/page-header.md`** — filled primary + outline overflow; no hand-built grey buttons.
|
|
47
58
|
32. **Table row preview** — **`exxat-table-row-preview.mdc`** — **`HoverCard`** + DS badges/cells; no bespoke popover cards.
|
|
59
|
+
33. **Sidebar shell** — **`exxat-sidebar-shell.mdc`** + **`AGENTS.md` §9.1** — legacy screenshots = **IA only** (labels/routes); **MUST NOT** copy per-section colors or fork **`app-sidebar.tsx`** styling; use **`SidebarMenuButton`** + **`lib/nav-active`**.
|
|
60
|
+
34. **Uploaded images** — **`exxat-no-image-pixel-copy.mdc`** (always apply) — screenshots/mockups = **intent + IA only**; **MUST** map to blueprints + reference hubs; **MUST NOT** pixel-copy colors, chrome, or bespoke stacks.
|
|
48
61
|
|
|
49
62
|
## Also read
|
|
50
63
|
|
|
@@ -55,7 +68,7 @@ Before implementing or reviewing **list / table / board / dashboard / data-heavy
|
|
|
55
68
|
- **`apps/web/docs/blueprints/`** — framework-agnostic specs (start: `page-header.md`, `data-table.md`).
|
|
56
69
|
- **`apps/web/docs/migrations/`** — token rename + removal history.
|
|
57
70
|
- **`packages/ui/tokens/hooks-index.json`** — machine-readable token index (regenerate via `pnpm --filter @exxatdesignux/ui tokens:index`).
|
|
58
|
-
- `.cursor/rules/exxat-data-tables.mdc`, **`exxat-hub-supported-views.mdc`**, **`exxat-no-vaul.mdc`**, **`exxat-tabs-chrome.mdc`**, **`exxat-page-header-actions.mdc`**, **`exxat-table-row-preview.mdc`**, `exxat-list-page-connected-views.mdc`, **`exxat-centralized-list-dataset.mdc`**, **`exxat-list-page-view-shells.mdc`**, **`exxat-fontawesome-icons.mdc`**, **`exxat-mono-ids.mdc`**, **`exxat-primary-nav-secondary-panel.mdc`**, **`exxat-library-hub-header.mdc`**, **`exxat-collaboration-access.mdc`**, **`exxat-dedicated-search-surfaces.mdc`**, **`exxat-kpi-trends.mdc`**, **`exxat-kpi-flat-band.mdc`**, **`exxat-drawer-vs-dialog.mdc`**, **`exxat-card-vs-list-rows.mdc`**, **`exxat-kpi-max-four.mdc`**, **`exxat-reuse-before-custom.mdc`**, `exxat-table-properties-drawer.mdc`, **`exxat-board-cards.mdc`**, **`exxat-page-vs-drawer.mdc`**, **`exxat-no-toast.mdc`**, **`exxat-command-menu.mdc`**, `exxat-kbd-shortcuts.mdc`, `exxat-accessibility.mdc` at repo root; **`apps/web/.cursor/rules/exxat-dashboard-view-charts.mdc`** for Data tab charts.
|
|
71
|
+
- `.cursor/rules/exxat-data-tables.mdc`, **`exxat-hub-supported-views.mdc`**, **`exxat-no-vaul.mdc`**, **`exxat-tabs-chrome.mdc`**, **`exxat-page-header-actions.mdc`**, **`exxat-table-row-preview.mdc`**, `exxat-list-page-connected-views.mdc`, **`exxat-centralized-list-dataset.mdc`**, **`exxat-list-page-view-shells.mdc`**, **`exxat-fontawesome-icons.mdc`**, **`exxat-mono-ids.mdc`**, **`exxat-nav-single-active.mdc`** (one active sidebar/secondary link — `nav-active` helpers), **`exxat-primary-nav-secondary-panel.mdc`**, **`exxat-library-hub-header.mdc`**, **`exxat-collaboration-access.mdc`**, **`exxat-dedicated-search-surfaces.mdc`**, **`exxat-kpi-trends.mdc`**, **`exxat-kpi-flat-band.mdc`**, **`exxat-drawer-vs-dialog.mdc`**, **`exxat-card-vs-list-rows.mdc`**, **`exxat-kpi-max-four.mdc`**, **`exxat-reuse-before-custom.mdc`**, `exxat-table-properties-drawer.mdc`, **`exxat-board-cards.mdc`**, **`exxat-page-vs-drawer.mdc`**, **`exxat-no-toast.mdc`**, **`exxat-command-menu.mdc`**, `exxat-kbd-shortcuts.mdc`, `exxat-accessibility.mdc` at repo root; **`apps/web/.cursor/rules/exxat-dashboard-view-charts.mdc`** for Data tab charts.
|
|
59
72
|
- **`apps/web/docs/kpi-flat-band-pattern.md`**, **`apps/web/docs/shell-surface-elevation-pattern.md`** — flat KPI strip + sidebar/secondary/page OKLCH stack.
|
|
60
73
|
- **`apps/web/docs/library-hub-header-pattern.md`** — folder-scoped library header **Customize folder**.
|
|
61
74
|
- **`apps/web/docs/collaboration-access-pattern.md`** — shared hub face rail + invite sheet.
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
---
|
|
2
|
+
description: Uploaded screenshots/mockups are IA reference only — map to Exxat DS patterns; never pixel-copy
|
|
3
|
+
alwaysApply: true
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Exxat DS — uploaded images are not the implementation spec
|
|
7
|
+
|
|
8
|
+
When the user attaches a **screenshot**, **mockup**, **Figma export**, **legacy app capture**, or any **reference image**, treat it as **product intent** — **not** as code to transcribe.
|
|
9
|
+
|
|
10
|
+
**Exxat DS rules, blueprints, and reference hubs always win** over what the image shows.
|
|
11
|
+
|
|
12
|
+
## Allowed to take from an image (content / IA)
|
|
13
|
+
|
|
14
|
+
- **Screen purpose**, **nav labels**, **routes**, **fields**, **columns**, **KPIs**, **actions**, **statuses**
|
|
15
|
+
- **Icon suffix** (Font Awesome) — still use **`fa-light` / `fa-solid`** DS pairing
|
|
16
|
+
- **Workflow intent** — export, invite, row → detail, etc.
|
|
17
|
+
|
|
18
|
+
## MUST NOT copy from an image (visual / stack)
|
|
19
|
+
|
|
20
|
+
- **Hex / RGB colors**, rainbow section text, custom sidebar washes, bespoke pills
|
|
21
|
+
- **Shell forks** — sidebar, header, list toolbar, tabs that bypass DS components
|
|
22
|
+
- **Bespoke widgets** when DS primitives exist — raw tables, custom popovers, Vaul, full-width tabs
|
|
23
|
+
- **Pixel implementation “because it’s in the picture”** without citing a **DS pattern + reference hub**
|
|
24
|
+
|
|
25
|
+
## REQUIRED workflow (before UI code)
|
|
26
|
+
|
|
27
|
+
1. Classify via **`component-selection-guide`** + **`blueprints/`**
|
|
28
|
+
2. Pick **`reference-implementations`** hub
|
|
29
|
+
3. State mapping (screen → DS composition)
|
|
30
|
+
4. Build with **`AGENTS.md`** + topic rules
|
|
31
|
+
5. Image vs DS conflict → **DS wins**; ask one question only for true business gaps
|
|
32
|
+
|
|
33
|
+
## See also
|
|
34
|
+
|
|
35
|
+
- **`exxat-reuse-before-custom.mdc`**, **`exxat-sidebar-shell.mdc`**, **`exxat-token-economy`** §2
|
|
@@ -20,6 +20,8 @@ alwaysApply: true
|
|
|
20
20
|
|
|
21
21
|
Do **not** silently ship a second stack for the same product pattern (e.g. another “table”, another metrics strip, another sidebar).
|
|
22
22
|
|
|
23
|
+
When the user **uploads a screenshot or mockup**, read **`exxat-no-image-pixel-copy.mdc`** first — extract IA only; map to DS patterns; never pixel-copy colors or chrome.
|
|
24
|
+
|
|
23
25
|
If the **user or task already explicitly** approved a greenfield component (“build a new X from scratch”), you may proceed without re-asking.
|
|
24
26
|
|
|
25
27
|
## MUST NOT
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
---
|
|
2
|
+
description: Application sidebar — DS shell only; legacy screenshots are IA reference, not visual spec
|
|
3
|
+
globs: "**/app-sidebar.tsx,**/navigation*.tsx,**/lib/mock/navigation.tsx,**/lib/*-navigation.tsx"
|
|
4
|
+
alwaysApply: false
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
# Exxat DS — application sidebar shell (MUST)
|
|
8
|
+
|
|
9
|
+
Customer / legacy app **screenshots** may show **what links exist** — not **how the sidebar is styled**. Full policy: **`exxat-no-image-pixel-copy.mdc`**.
|
|
10
|
+
|
|
11
|
+
## Screenshots are allowed to inform (content only)
|
|
12
|
+
|
|
13
|
+
- Nav **labels**, **grouping**, **route paths**, **Font Awesome icon suffixes**
|
|
14
|
+
- Whether a row needs **children**, a **secondary panel**, or a **badge**
|
|
15
|
+
|
|
16
|
+
## Screenshots MUST NOT drive styling (MUST NOT)
|
|
17
|
+
|
|
18
|
+
- **Per-section label colors** (magenta / teal / gold text on every row in a group)
|
|
19
|
+
- **Custom active pills** (hand-built white `rounded-*` + shadow instead of `SidebarMenuButton` `data-active`)
|
|
20
|
+
- **Non-token sidebar fills** (pink wash, `#hex` tints, inline `style={{ color: … }}`)
|
|
21
|
+
- **Forking `app-sidebar.tsx` layout** for one product while rest of DS uses shared chrome
|
|
22
|
+
- **Re-implementing `isNavActive`** in the app — use **`@exxatdesignux/ui/lib/nav-active`** (see **`exxat-nav-single-active.mdc`**)
|
|
23
|
+
|
|
24
|
+
## MUST — DS sidebar chrome
|
|
25
|
+
|
|
26
|
+
1. **Shell:** **`AppSidebar`** + **`SidebarMenuButton`** / **`SidebarGroup`** / **`SidebarGroupLabel`** from **`@exxatdesignux/ui`**. Reference: **`AGENTS.md` §9.1**, **`exxat-ds-skill` §3.1–§3.2**.
|
|
27
|
+
2. **Typography:** Row labels **`text-sidebar-foreground`**. Section headings **`SidebarGroupLabel`** + **`text-sidebar-section-label`**.
|
|
28
|
+
3. **Active state:** **`SidebarMenuButton` `isActive`** only — one active row in expanded rail; collapsible parent neutral when child active.
|
|
29
|
+
4. **Icons:** **`fa-light`** / **`fa-solid`** on icons — do **not** recolor labels per module.
|
|
30
|
+
5. **Nav data:** Extend **`lib/mock/navigation.tsx`** (or imported mock). **MUST NOT** paste legacy sidebar components from customer repos.
|
|
31
|
+
6. **Consumer products:** Build in a **separate repo** with **`@exxatdesignux/ui`** — not DS monorepo sidebar forks.
|
|
32
|
+
|
|
33
|
+
## Anti-pattern
|
|
34
|
+
|
|
35
|
+
Legacy product sidebars with rainbow section text and bespoke selection chrome — **do not reproduce** on Exxat DS.
|
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
---
|
|
2
|
+
description: Exxat DS — output a design brief before writing files for any new surface; question bank by surface type
|
|
3
|
+
alwaysApply: true
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Exxat DS — UX discovery protocol
|
|
7
|
+
|
|
8
|
+
On any task that creates a **new route, page, template, wizard, or
|
|
9
|
+
significant component**, the assistant MUST output a **design brief in chat**
|
|
10
|
+
BEFORE writing files. Brief format is defined in
|
|
11
|
+
`.cursor/skills/exxat-senior-ux/SKILL.md` §3.
|
|
12
|
+
|
|
13
|
+
## MUST
|
|
14
|
+
|
|
15
|
+
1. **No code without a brief.** New surfaces require the brief. Trivial edits
|
|
16
|
+
to existing surfaces (copy tweak, single-class change, bug fix, refactor)
|
|
17
|
+
are exempt.
|
|
18
|
+
2. **Cite a reference.** Every brief names **one repo reference** + **two
|
|
19
|
+
modern SaaS analogues** (Linear / Notion / Stripe / Figma / Vercel / etc.)
|
|
20
|
+
that solve the same **job-to-be-done**. Cite the SaaS analogues by
|
|
21
|
+
product name + pattern codes from
|
|
22
|
+
`apps/web/docs/modern-saas-patterns.md` (e.g. `Linear issue detail (M1, M4, M7)`).
|
|
23
|
+
3. **Name principles + breaks.** Brief lists the principles applied
|
|
24
|
+
(`exxat-ux-principles.mdc`) and any deviations with one-sentence reasons.
|
|
25
|
+
**Never-break** principles (P1–P8) cannot be deviated from.
|
|
26
|
+
4. **One assumption per gap.** If the user can't or won't answer, state the
|
|
27
|
+
assumption inline; never invent silently.
|
|
28
|
+
5. **Sync the brief to the implementation.** PR / commit message references
|
|
29
|
+
the job doc (`apps/web/docs/jobs/`) and any principle break.
|
|
30
|
+
|
|
31
|
+
## MUST NOT
|
|
32
|
+
|
|
33
|
+
- Generate files before the brief.
|
|
34
|
+
- Ask more than **3** questions in one batch.
|
|
35
|
+
- Ask questions whose answer is already in the prompt, the file tree, or
|
|
36
|
+
`apps/web/docs/jobs/`.
|
|
37
|
+
- Use uploaded screenshots as the implementation spec
|
|
38
|
+
(`exxat-no-image-pixel-copy.mdc`).
|
|
39
|
+
- Treat a feature list as a job. Ask: *what decision does this enable?*
|
|
40
|
+
|
|
41
|
+
## Question bank by surface type
|
|
42
|
+
|
|
43
|
+
Pick **at most 3** questions whose answers change the design. Skip the rest.
|
|
44
|
+
|
|
45
|
+
### Record / entity detail
|
|
46
|
+
1. Who reads this most — power admin (dense, keyboard-first) or occasional
|
|
47
|
+
user (cozy, guided)?
|
|
48
|
+
2. How is it reached — list, deep link, notification, search? (Drives
|
|
49
|
+
breadcrumb + back-affordance model.)
|
|
50
|
+
3. Section tabs needed, or single-scroll page? (Field count > ~20 or rich
|
|
51
|
+
children → tabs.)
|
|
52
|
+
|
|
53
|
+
### Hub / list page
|
|
54
|
+
1. Dense comparison (table) or visual browse (board / gallery)?
|
|
55
|
+
2. Per-record actions, bulk actions, or both?
|
|
56
|
+
3. Will users filter / sort / customize columns, or is the view fixed?
|
|
57
|
+
|
|
58
|
+
### Wizard / compose flow
|
|
59
|
+
1. One screen with sections, or multi-step (>3 decisions)?
|
|
60
|
+
2. Are intermediate steps savable as drafts?
|
|
61
|
+
3. Submit is destructive, or always reversible?
|
|
62
|
+
|
|
63
|
+
### Settings / preferences
|
|
64
|
+
1. User scope (personal), workspace (shared), or both?
|
|
65
|
+
2. Search needed (>20 settings) or flat list?
|
|
66
|
+
3. Apply-on-change or explicit Save?
|
|
67
|
+
|
|
68
|
+
### Dashboard / analytics
|
|
69
|
+
1. One critical KPI or a comparison set (≤4)?
|
|
70
|
+
2. Read at a glance, or drill into details?
|
|
71
|
+
3. Time range fixed, or user-controlled?
|
|
72
|
+
|
|
73
|
+
### Overlay (drawer / dialog / sheet)
|
|
74
|
+
1. Does the user need the hub visible behind them? (Yes → sheet; no → route.)
|
|
75
|
+
2. Blocking confirmation, or reversible? (Blocking → dialog; reversible → sheet.)
|
|
76
|
+
3. Will it grow to ≥3 steps? (Yes → consider route instead.)
|
|
77
|
+
|
|
78
|
+
## Brief template (copy verbatim)
|
|
79
|
+
|
|
80
|
+
```
|
|
81
|
+
Problem: <one sentence — the user's pain, not the feature>
|
|
82
|
+
User & frequency: <persona, frequency, expertise>
|
|
83
|
+
Job-to-be-done: <the decision or action this enables>
|
|
84
|
+
Pattern: <route | sheet | dialog | inline> + IA shape
|
|
85
|
+
Reference (repo): <file path>
|
|
86
|
+
Reference (modern): <product 1 + Mx>, <product 2 + Mx>
|
|
87
|
+
Principles applied: <P-codes from exxat-ux-principles>
|
|
88
|
+
Deviations: <principle + one-sentence reason, or "none">
|
|
89
|
+
Out of scope: <what this does not do, deliberately>
|
|
90
|
+
Open questions: <max 2; ideally 0>
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
## Examples
|
|
94
|
+
|
|
95
|
+
**Good:**
|
|
96
|
+
> Problem: Coordinators can't tell at a glance which students are
|
|
97
|
+
> non-compliant before placement.
|
|
98
|
+
> User & frequency: Program coordinator, daily, keyboard-first.
|
|
99
|
+
> Job-to-be-done: Identify and act on at-risk students in < 30s per record.
|
|
100
|
+
> Pattern: route `/students/[id]` + identity row + status row + 2×2 card grid.
|
|
101
|
+
> Reference (repo): `components/library-table.tsx` for IA cadence.
|
|
102
|
+
> Reference (modern): Linear issue detail (M1, M4, M7); Stripe customer
|
|
103
|
+
> record (M4, M11).
|
|
104
|
+
> Principles applied: P1, P2, P3, P5, P6, P13, P19.
|
|
105
|
+
> Deviations: none.
|
|
106
|
+
> Out of scope: inline editing (v2), bulk message (lives on list).
|
|
107
|
+
> Open questions: none.
|
|
108
|
+
|
|
109
|
+
**Bad (silent generate):**
|
|
110
|
+
> *Agent writes 4 files without explanation.*
|
|
111
|
+
|
|
112
|
+
**Bad (vague prompt accepted):**
|
|
113
|
+
> User: "make a settings page". *Agent writes generic form.* Should have
|
|
114
|
+
> asked: scope (personal/workspace), search needed, apply-on-change vs Save.
|
|
115
|
+
|
|
116
|
+
## See also
|
|
117
|
+
|
|
118
|
+
- `.cursor/skills/exxat-senior-ux/SKILL.md` — the persona + full protocol
|
|
119
|
+
- `.cursor/rules/exxat-ux-principles.mdc` — principles + when to break
|
|
120
|
+
- `apps/web/docs/jobs/` — canonical references per job type
|
|
121
|
+
- `apps/web/docs/modern-saas-patterns.md` — pattern codes (M1–M12)
|
|
122
|
+
- `.cursor/rules/exxat-no-image-pixel-copy.mdc` — IA from screenshots only
|
|
@@ -0,0 +1,186 @@
|
|
|
1
|
+
---
|
|
2
|
+
description: Exxat DS UX principles — what to follow, when to break, why
|
|
3
|
+
alwaysApply: true
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Exxat DS — UX principles (and when to break them)
|
|
7
|
+
|
|
8
|
+
Principles are the senior designer's spine. They make most decisions cheap.
|
|
9
|
+
**Break deliberately, not accidentally** — and say so in the design brief
|
|
10
|
+
(`exxat-ux-discovery-protocol.mdc`). If you can't write the deviation reason
|
|
11
|
+
in one sentence, you shouldn't be breaking the principle.
|
|
12
|
+
|
|
13
|
+
Each principle below has: **what it says**, **why**, **when to break**, and
|
|
14
|
+
the **anti-pattern**.
|
|
15
|
+
|
|
16
|
+
---
|
|
17
|
+
|
|
18
|
+
## Always-follow (P1–P8) — no exceptions
|
|
19
|
+
|
|
20
|
+
### P1. Way back is obvious, and exactly once
|
|
21
|
+
Breadcrumb in `SiteHeader` OR explicit back affordance — **never both**.
|
|
22
|
+
- **Why:** Two paths back create cognitive overhead and a redundant UI.
|
|
23
|
+
- **When to break:** Never.
|
|
24
|
+
- **Anti-pattern:** Breadcrumb "Dashboard › Students › Jordan Lee" + a
|
|
25
|
+
separate "Back to roster" button in the body.
|
|
26
|
+
- **Reference:** `exxat-breadcrumbs-no-back.mdc`.
|
|
27
|
+
|
|
28
|
+
### P2. One H1 per page; no duplicated identity
|
|
29
|
+
The record name appears in exactly one carrier — typically `PageHeader.title`
|
|
30
|
+
+ ancestors-only breadcrumb. Not also as an `<h1>` in the body.
|
|
31
|
+
- **Why:** Screen readers and scan-reading rely on a single page title.
|
|
32
|
+
- **When to break:** Never.
|
|
33
|
+
- **Anti-pattern:** Name in breadcrumb leaf + `PageHeader title` + body `<h1>`.
|
|
34
|
+
|
|
35
|
+
### P3. One primary action per surface
|
|
36
|
+
Exactly one filled `Button`; everything else `outline` / `ghost` / `link`.
|
|
37
|
+
- **Why:** Two primaries = no primary.
|
|
38
|
+
- **When to break:** Never. Symmetric pairs ("Approve" + "Reject") are both
|
|
39
|
+
*outline* — neither is the styled "primary".
|
|
40
|
+
- **Anti-pattern:** Two filled buttons in the header.
|
|
41
|
+
|
|
42
|
+
### P4. Don't pixel-copy
|
|
43
|
+
Extract IA from screenshots and competitor references; never copy chrome,
|
|
44
|
+
colors, or bespoke widgets.
|
|
45
|
+
- **Why:** Pixels carry decisions made in another product's context.
|
|
46
|
+
- **When to break:** Never.
|
|
47
|
+
- **Reference:** `exxat-no-image-pixel-copy.mdc`.
|
|
48
|
+
|
|
49
|
+
### P5. Every list / detail / action ships empty + error + loading
|
|
50
|
+
- **Why:** Real users hit all three; afterthoughts ship as bugs.
|
|
51
|
+
- **When to break:** Never.
|
|
52
|
+
- **Anti-pattern:** "Loading…" text and no skeleton; missing 404 / empty.
|
|
53
|
+
|
|
54
|
+
### P6. Keyboard parity
|
|
55
|
+
Every mouse action has a keyboard equivalent; focus is always visible.
|
|
56
|
+
- **Why:** Power users, motor-disabled users, screen-reader users all rely
|
|
57
|
+
on this.
|
|
58
|
+
- **When to break:** Never.
|
|
59
|
+
- **Reference:** `exxat-kbd-shortcuts.mdc`, `exxat-accessibility.mdc`.
|
|
60
|
+
|
|
61
|
+
### P7. WCAG 2.1 AA minimum
|
|
62
|
+
Contrast ≥ 4.5:1 (text) / ≥ 3:1 (UI), targets ≥ 24×24, labels on icon-only.
|
|
63
|
+
- **Why:** Floor for shipping. Not negotiable.
|
|
64
|
+
- **When to break:** Never.
|
|
65
|
+
- **Reference:** `exxat-accessibility.mdc`.
|
|
66
|
+
|
|
67
|
+
### P8. Reuse before invent
|
|
68
|
+
Compose from DS primitives first. New shared primitives require user approval
|
|
69
|
+
after a real, repeated need (≥ 2 use cases).
|
|
70
|
+
- **Why:** Forked stacks divide the team; the DS is the vocabulary.
|
|
71
|
+
- **When to break:** Never silently. Ask the user.
|
|
72
|
+
- **Reference:** `exxat-reuse-before-custom.mdc`.
|
|
73
|
+
|
|
74
|
+
---
|
|
75
|
+
|
|
76
|
+
## Default-follow (P9–P20) — break only with stated reason
|
|
77
|
+
|
|
78
|
+
### P9. Clarity over cleverness
|
|
79
|
+
Direct labels, recognizable patterns. "Save" beats "Persist". "Send" beats
|
|
80
|
+
"Beam".
|
|
81
|
+
- **Why:** Decisions cost less when the label states the action.
|
|
82
|
+
- **Break when:** Intentional brand voice in low-stakes surfaces (onboarding
|
|
83
|
+
celebration, marketing splash). Never in core flows.
|
|
84
|
+
- **Anti-pattern:** "Materialize this configuration" instead of "Save".
|
|
85
|
+
|
|
86
|
+
### P10. Recognition over recall
|
|
87
|
+
Surface what the user needs; don't make them remember.
|
|
88
|
+
- **Why:** Working memory is the most expensive resource on a screen.
|
|
89
|
+
- **Break when:** Daily power users where keyboard shortcuts replace visible
|
|
90
|
+
chrome (Cron, Linear, Raycast). Provide a discoverable hint.
|
|
91
|
+
- **Anti-pattern:** Hiding a frequent action behind a chord with no UI.
|
|
92
|
+
|
|
93
|
+
### P11. One job per surface
|
|
94
|
+
A screen optimizes for one primary user decision.
|
|
95
|
+
- **Why:** Splits attention, splits metrics, splits design quality.
|
|
96
|
+
- **Break when:** Workspace surfaces (Notion-style pages, Linear-style issue
|
|
97
|
+
views) deliberately compose multiple jobs. Even then, one job is **primary**.
|
|
98
|
+
- **Anti-pattern:** Settings page that also includes a dashboard.
|
|
99
|
+
|
|
100
|
+
### P12. Progressive disclosure
|
|
101
|
+
Show core first; depth on demand (popovers, sheets, expand).
|
|
102
|
+
- **Why:** Most users do the common thing most of the time.
|
|
103
|
+
- **Break when:** Compliance / legal / audit surfaces where everything must
|
|
104
|
+
be visible.
|
|
105
|
+
- **Anti-pattern:** 30-field form on first load with no grouping.
|
|
106
|
+
|
|
107
|
+
### P13. Status visible without scroll
|
|
108
|
+
Status signals that drive decisions (compliance, errors, urgency) appear
|
|
109
|
+
above the fold.
|
|
110
|
+
- **Why:** Status hidden = ignored.
|
|
111
|
+
- **Break when:** Privacy / discretion contexts (e.g. HR records where peer
|
|
112
|
+
visibility is undesirable).
|
|
113
|
+
- **Anti-pattern:** Compliance status on tab #3 of a record detail.
|
|
114
|
+
|
|
115
|
+
### P14. Density follows frequency
|
|
116
|
+
Daily power users get compact / dense; occasional users get cozy / spacious.
|
|
117
|
+
- **Why:** Different audiences scan differently.
|
|
118
|
+
- **Break when:** Accessibility (low-vision, motor) mandates generous
|
|
119
|
+
spacing. Offer a density toggle if both audiences share a surface.
|
|
120
|
+
- **Anti-pattern:** Sparse table for a coordinator viewing 200 students/day.
|
|
121
|
+
|
|
122
|
+
### P15. Inline editing where data is read
|
|
123
|
+
Modern SaaS (Notion, Linear, Airtable) edits in place. Don't bounce users
|
|
124
|
+
to a form for a single-field change.
|
|
125
|
+
- **Why:** Mode-switch friction kills throughput.
|
|
126
|
+
- **Break when:** Bulk operations, multi-field validation, audit-logged
|
|
127
|
+
fields, destructive edits — use a focused form / drawer.
|
|
128
|
+
- **Anti-pattern:** "Edit" page just to change a phone number.
|
|
129
|
+
|
|
130
|
+
### P16. Optimistic UI for low-risk actions
|
|
131
|
+
Favorite, archive, status flip, reorder — feel instant; reconcile on error.
|
|
132
|
+
- **Why:** Speed of feedback is a quality signal.
|
|
133
|
+
- **Break when:** Financial / irreversible / regulated actions — show progress
|
|
134
|
+
and confirmation.
|
|
135
|
+
- **Anti-pattern:** Spinner overlay for a star-favorite toggle.
|
|
136
|
+
|
|
137
|
+
### P17. Search is global and fast
|
|
138
|
+
`⌘K` opens command + search; everything addressable is searchable.
|
|
139
|
+
- **Why:** Modern users navigate by typing.
|
|
140
|
+
- **Break when:** Never for modern SaaS at this scale.
|
|
141
|
+
- **Reference:** `exxat-command-menu.mdc`.
|
|
142
|
+
|
|
143
|
+
### P18. Content first, chrome last
|
|
144
|
+
Data is the star. Sidebars collapse to icons. Headers stay ~48–56px.
|
|
145
|
+
Surfaces are generous.
|
|
146
|
+
- **Why:** Chrome competes with the work.
|
|
147
|
+
- **Break when:** Heavily configurable admin consoles where chrome **is** the
|
|
148
|
+
content. Prefer collapsing over crowding.
|
|
149
|
+
- **Anti-pattern:** Purple gradient hero bar above a data table.
|
|
150
|
+
|
|
151
|
+
### P19. Type carries hierarchy
|
|
152
|
+
Weight, size, color do the heavy lifting before borders, boxes, or color
|
|
153
|
+
tints.
|
|
154
|
+
- **Why:** Ornament dates fast; type ages well.
|
|
155
|
+
- **Break when:** Status surfaces where color is encoding meaning (chips,
|
|
156
|
+
alerts).
|
|
157
|
+
- **Anti-pattern:** Every value wrapped in a tinted card.
|
|
158
|
+
|
|
159
|
+
### P20. AI is a sidecar, not the primary path
|
|
160
|
+
Ask Leo / inline AI — opt-in, contextual, cancellable. Never auto-runs on a
|
|
161
|
+
record. Never the only way to do something.
|
|
162
|
+
- **Why:** AI is a feature; the core product must work without it.
|
|
163
|
+
- **Break when:** Surfaces explicitly built around AI (e.g. an AI-only
|
|
164
|
+
composer). Even then, expose the deterministic path.
|
|
165
|
+
- **Reference:** `exxat-command-menu.mdc` (⌘K vs ⌘⌥K split).
|
|
166
|
+
|
|
167
|
+
---
|
|
168
|
+
|
|
169
|
+
## How to declare a deviation
|
|
170
|
+
|
|
171
|
+
In the design brief, list the broken principle + the reason on one line:
|
|
172
|
+
|
|
173
|
+
```
|
|
174
|
+
Deviations: P14 (density) — broke "follows frequency" because the primary
|
|
175
|
+
user here is occasional but the same surface also serves daily
|
|
176
|
+
admins; resolved with a density toggle, default cozy.
|
|
177
|
+
```
|
|
178
|
+
|
|
179
|
+
If the reason doesn't fit on one line, the deviation isn't justified yet.
|
|
180
|
+
|
|
181
|
+
## See also
|
|
182
|
+
|
|
183
|
+
- `.cursor/skills/exxat-senior-ux/SKILL.md` — the persona
|
|
184
|
+
- `.cursor/rules/exxat-ux-discovery-protocol.mdc` — gating + brief
|
|
185
|
+
- `apps/web/docs/modern-saas-patterns.md` — the modern canon (M1–M12)
|
|
186
|
+
- All `exxat-*.mdc` rules — concrete enforcement per pattern
|
|
@@ -0,0 +1,145 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: exxat-senior-ux
|
|
3
|
+
description: >-
|
|
4
|
+
Make the agent behave like a senior UX designer — understand the problem
|
|
5
|
+
before designing, study how modern SaaS solves the same job, propose a
|
|
6
|
+
brief before writing code, follow principles, know when to break them,
|
|
7
|
+
audit your own work. Load FIRST on any design / UI / page / hub / detail /
|
|
8
|
+
wizard / settings task, BEFORE opening AGENTS.md or any blueprint.
|
|
9
|
+
user-invocable: true
|
|
10
|
+
---
|
|
11
|
+
|
|
12
|
+
# Exxat DS — senior UX (read this BEFORE you design)
|
|
13
|
+
|
|
14
|
+
You are not a typing assistant. You are a senior product designer with 10+
|
|
15
|
+
years across modern SaaS (Linear, Notion, Stripe, Figma, Vercel-class
|
|
16
|
+
products). You design for the **user's job**, not the user's words.
|
|
17
|
+
|
|
18
|
+
## When to load this skill
|
|
19
|
+
|
|
20
|
+
- The user asks for a **new** page, route, hub, detail screen, wizard,
|
|
21
|
+
settings section, dashboard, dialog/sheet flow, or significant component.
|
|
22
|
+
- The user attaches a screenshot or mockup.
|
|
23
|
+
- The user asks "how should I build X" / "design X" / "make it modern".
|
|
24
|
+
- Any task where the prompt names a *surface* rather than a single line of
|
|
25
|
+
code.
|
|
26
|
+
|
|
27
|
+
Do **not** load on: typo fixes, dependency bumps, ESLint passes, single-class
|
|
28
|
+
restyles of an existing surface that already follows DS rules.
|
|
29
|
+
|
|
30
|
+
## Mindset (5 lines, memorize)
|
|
31
|
+
|
|
32
|
+
1. **Problem before solution.** A prompt is a symptom. The job is the disease.
|
|
33
|
+
2. **Recognition before invention.** Modern products converged for a reason —
|
|
34
|
+
start from what users already know.
|
|
35
|
+
3. **One job per surface.** A screen that tries to do three things does none.
|
|
36
|
+
4. **Push back, don't transcribe.** Challenge vague briefs, solution-shaped
|
|
37
|
+
prompts, feature stacking, pixel-copies.
|
|
38
|
+
5. **The DS is the vocabulary, not the design.** Composition is the means;
|
|
39
|
+
clarity for the user is the end.
|
|
40
|
+
|
|
41
|
+
## The five-step protocol (mandatory on new surfaces)
|
|
42
|
+
|
|
43
|
+
### 1. Discovery — ask, infer, or state assumptions
|
|
44
|
+
|
|
45
|
+
Output a **design brief in chat** BEFORE writing files. Ask 1–3 questions
|
|
46
|
+
only if the answer materially changes the design — otherwise state
|
|
47
|
+
assumptions and proceed.
|
|
48
|
+
|
|
49
|
+
Use the **question bank by surface type** in
|
|
50
|
+
`.cursor/rules/exxat-ux-discovery-protocol.mdc`.
|
|
51
|
+
|
|
52
|
+
If the user said "no questions, build it", still output the brief + your
|
|
53
|
+
assumptions, then build.
|
|
54
|
+
|
|
55
|
+
### 2. Research — recognize the pattern, don't reinvent
|
|
56
|
+
|
|
57
|
+
1. Check this repo first — does a canonical reference solve the same **job**?
|
|
58
|
+
See `apps/web/docs/jobs/`.
|
|
59
|
+
2. If unfamiliar, call **Mobbin** `search_screens` for the **job type**
|
|
60
|
+
("record detail", "triage list", "compose flow") — not the domain.
|
|
61
|
+
3. For 2026 conventions, **WebSearch** (e.g. "Linear issue detail 2026",
|
|
62
|
+
"Notion property panel pattern").
|
|
63
|
+
4. Read `apps/web/docs/modern-saas-patterns.md` for the canon you're working
|
|
64
|
+
against — content-first chrome, command palette, inline editing,
|
|
65
|
+
optimistic UI, side-panel detail, density layers, type-first hierarchy,
|
|
66
|
+
activity timeline, AI as sidecar.
|
|
67
|
+
5. Extract **patterns** (IA, hierarchy, action placement), never pixels
|
|
68
|
+
(`exxat-no-image-pixel-copy.mdc`).
|
|
69
|
+
|
|
70
|
+
### 3. Synthesis — output a one-screen brief
|
|
71
|
+
|
|
72
|
+
```
|
|
73
|
+
Problem: <one sentence — the user's pain, not the feature>
|
|
74
|
+
User & frequency: <persona, daily/weekly/occasional, expertise>
|
|
75
|
+
Job-to-be-done: <the decision or action this enables>
|
|
76
|
+
Pattern: <route | sheet | dialog | inline> + IA shape
|
|
77
|
+
Reference (repo): <file path>
|
|
78
|
+
Reference (modern): <product 1 + Mx codes>, <product 2 + Mx codes>
|
|
79
|
+
Principles applied: <list of Pxx from exxat-ux-principles>
|
|
80
|
+
Deviations: <principle + reason, or "none">
|
|
81
|
+
Out of scope: <what this surface intentionally does not do>
|
|
82
|
+
Open questions: <max 2; ideally 0>
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
Then build against the brief. Every decision references it.
|
|
86
|
+
|
|
87
|
+
### 4. Build — compose, don't invent
|
|
88
|
+
|
|
89
|
+
- Use DS primitives (see `exxat-token-economy/SKILL.md` §1 + §3).
|
|
90
|
+
- Apply principles from `exxat-ux-principles.mdc`.
|
|
91
|
+
- When you break a principle, **say so in chat** with the one-sentence
|
|
92
|
+
reason. If you can't articulate it, you shouldn't be breaking it.
|
|
93
|
+
|
|
94
|
+
### 5. Audit — self-review like a senior would
|
|
95
|
+
|
|
96
|
+
Before declaring done, answer yes/no/N/A:
|
|
97
|
+
|
|
98
|
+
- [ ] One H1, no duplicated identity (e.g. name in breadcrumb + title + body).
|
|
99
|
+
- [ ] Primary action findable in < 2 seconds.
|
|
100
|
+
- [ ] Exactly one filled primary CTA per surface; others outline / ghost.
|
|
101
|
+
- [ ] Way-back is provided **once** (breadcrumb OR back affordance, not both).
|
|
102
|
+
- [ ] Status signals visible without scrolling.
|
|
103
|
+
- [ ] Empty / error / loading states all designed (not afterthoughts).
|
|
104
|
+
- [ ] Keyboard: every action reachable; Enter / Esc behave as expected.
|
|
105
|
+
- [ ] Accessibility: contrast ≥ 4.5:1, focus ring visible, target ≥ 24×24,
|
|
106
|
+
tooltips on icon-only.
|
|
107
|
+
- [ ] Voice: empty-state and button copy match `docs/voice-and-tone.md`.
|
|
108
|
+
- [ ] Modern: no `toast()`, no Vaul, no full-width tab bar, no legacy
|
|
109
|
+
pixel-copy, no two filled CTAs.
|
|
110
|
+
|
|
111
|
+
If any answer is **no**, fix before responding.
|
|
112
|
+
|
|
113
|
+
## When to ask vs assume
|
|
114
|
+
|
|
115
|
+
| Situation | Do |
|
|
116
|
+
|-----------|----|
|
|
117
|
+
| Brief is vague ("make it nice", "modern", "clean") | Ask **1 sharp question** that finds the underlying job |
|
|
118
|
+
| Solution-shaped prompt ("add a tab for X") | Ask what job that tab serves; offer 1 alternative |
|
|
119
|
+
| User said "like our other admin pages" | Don't ask — pick the reference, state the assumption |
|
|
120
|
+
| User attached a screenshot/mockup | Don't pixel-copy — extract IA, map to DS, state mapping |
|
|
121
|
+
| You don't recognize the job | Research (Mobbin + WebSearch), then synthesize |
|
|
122
|
+
| User explicitly said "no questions, build it" | Build, but still output the brief + assumptions |
|
|
123
|
+
|
|
124
|
+
## Push back when
|
|
125
|
+
|
|
126
|
+
- Prompt would produce 2+ filled CTAs, duplicate identity, hidden status, or
|
|
127
|
+
the way-back duplicated.
|
|
128
|
+
- User wants to pixel-copy a competitor (extract pattern instead).
|
|
129
|
+
- User wants a new shared primitive without 2+ proven use cases.
|
|
130
|
+
- User wants `toast()` for product feedback (use banners / inline / dialog).
|
|
131
|
+
- User wants `vaul` (use `Sheet`).
|
|
132
|
+
- A "feature list" prompt has no underlying job — ask: "What decision does
|
|
133
|
+
this enable?"
|
|
134
|
+
|
|
135
|
+
Be polite, unambiguous, brief: *"I'd suggest X because Y — okay to proceed
|
|
136
|
+
that way?"*
|
|
137
|
+
|
|
138
|
+
## See also
|
|
139
|
+
|
|
140
|
+
- `.cursor/rules/exxat-ux-discovery-protocol.mdc` — brief-before-code gate
|
|
141
|
+
- `.cursor/rules/exxat-ux-principles.mdc` — principles + when to break
|
|
142
|
+
- `apps/web/docs/modern-saas-patterns.md` — what "modern" means here
|
|
143
|
+
- `apps/web/docs/jobs/` — canonical references per job type
|
|
144
|
+
- `.cursor/skills/exxat-token-economy/SKILL.md` — minimum files + scaffolds
|
|
145
|
+
- `.cursor/rules/exxat-no-image-pixel-copy.mdc` — IA from screenshots only
|
|
@@ -66,8 +66,9 @@ Answer **yes / no / N/A** to each. A **no** means re-plan; you'll save a regener
|
|
|
66
66
|
6. **Seven views + real bodies?** — `FULL_HUB_SUPPORTED_VIEWS` on **`ListPageTemplate`** + **`HubTable`** (sync both); every allowed view has a renderer; list uses **`ListPageBoardCard`** — not `["table"]` / `PRIMARY_HUB_SUPPORTED_VIEWS` / empty `renderers={}`.
|
|
67
67
|
7. **Sheet only (no Vaul)?** — side panels use **`Sheet`**; **`vaul`** must not be in `package.json`.
|
|
68
68
|
8. **Header + tabs + table preview?** — **`PageHeader`** + DS **`Button`** variants for actions; hub views via **`ListPageTemplate`** (not full-width tabs); record tabs **`TabsList`** `w-fit`; row preview via **`HoverCard`** + shared cells — not custom popovers.
|
|
69
|
+
9. **Uploaded image ≠ spec?** — If the user attached a screenshot/mockup: extract **IA only** (labels, routes, fields); map to **`component-selection-guide`** + a **reference hub**; **MUST NOT** pixel-copy colors, sidebar chrome, tabs, or bespoke widgets — **`exxat-no-image-pixel-copy.mdc`**.
|
|
69
70
|
|
|
70
|
-
If all
|
|
71
|
+
If all nine are **yes**, generate. If any is **no**, either narrow the requirements
|
|
71
72
|
with **one** clarifying question or fix the gap silently and note it in your response.
|
|
72
73
|
|
|
73
74
|
---
|
|
@@ -131,6 +131,8 @@ These exist but are **not** canonical. They predate a rule, are scoped to a one-
|
|
|
131
131
|
| Custom search input above a `DataTable` | `HubTable`'s toolbar already does this; duplicating leads to drift | Configure `ColumnDef.filter` + use `HubTable` |
|
|
132
132
|
| `toast()` / Sonner / snackbar | Forbidden — see [`exxat-no-toast.mdc`](../../../.cursor/rules/exxat-no-toast.mdc) | `LocalBanner` / `SystemBanner` or inline status |
|
|
133
133
|
| Negative-margin overlapping avatars | Forbidden — see [`exxat-person-identity-display.mdc`](../../../.cursor/rules/exxat-person-identity-display.mdc) | `AvatarGroup` (gapped by default) |
|
|
134
|
+
| Legacy customer sidebar screenshots (rainbow section text, pink wash, custom pills) | Visual spec for old product — **not** Exxat DS chrome | **`AppSidebar`** + **`SidebarMenuButton`** + **`lib/mock/navigation.tsx`** — **`exxat-sidebar-shell.mdc`** |
|
|
135
|
+
| Uploaded screenshots / mockups treated as pixel spec | Images show **intent** — DS blueprints + reference hubs define **implementation** | **`exxat-no-image-pixel-copy.mdc`** + **`component-selection-guide.md`** |
|
|
134
136
|
|
|
135
137
|
---
|
|
136
138
|
|
|
@@ -42,6 +42,7 @@ If the app was built before current agent rules, verify:
|
|
|
42
42
|
| Grey custom header buttons | **`PageHeader`** + **`Button`** variants — **`exxat-page-header-actions.mdc`** |
|
|
43
43
|
| Bespoke student popover in table | **`HoverCard`** + shared cells/badges — **`exxat-table-row-preview.mdc`** |
|
|
44
44
|
| Custom hub table / trimmed Add view | **`HubTable`** + **`FULL_HUB_SUPPORTED_VIEWS`** — **`exxat-hub-supported-views.mdc`** |
|
|
45
|
+
| Agent copied uploaded screenshots pixel-for-pixel | **`exxat-no-image-pixel-copy.mdc`** — images = IA only; map to blueprints + reference hubs |
|
|
45
46
|
|
|
46
47
|
## 6. Still stuck?
|
|
47
48
|
|