@exxatdesignux/ui 0.5.2 → 0.5.4
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/README.md +1 -1
- package/consumer-extras/cursor-rules/exxat-accessibility.mdc +1 -1
- package/consumer-extras/cursor-rules/exxat-data-tables.mdc +8 -6
- package/consumer-extras/cursor-rules/exxat-drawer-vs-dialog.mdc +4 -4
- package/consumer-extras/cursor-rules/exxat-ds-agents.mdc +6 -1
- package/consumer-extras/cursor-rules/exxat-hub-supported-views.mdc +54 -0
- package/consumer-extras/cursor-rules/exxat-nav-single-active.mdc +31 -0
- package/consumer-extras/cursor-rules/exxat-no-vaul.mdc +25 -0
- package/consumer-extras/cursor-rules/exxat-page-header-actions.mdc +31 -0
- package/consumer-extras/cursor-rules/exxat-table-row-preview.mdc +24 -0
- package/consumer-extras/cursor-rules/exxat-tabs-chrome.mdc +31 -0
- package/consumer-extras/cursor-skills/exxat-drawer-vs-dialog/SKILL.md +5 -5
- package/consumer-extras/cursor-skills/exxat-ds-skill/SKILL.md +10 -5
- package/consumer-extras/cursor-skills/exxat-ds-skill/references/accessibility.md +1 -1
- package/consumer-extras/cursor-skills/exxat-ds-skill/references/data-table-pattern.md +15 -5
- package/consumer-extras/cursor-skills/exxat-token-economy/SKILL.md +14 -5
- package/consumer-extras/handbook/HANDBOOK.md +1 -1
- package/consumer-extras/handbook/reference-implementations.md +2 -2
- package/consumer-extras/patterns/consumer-upgrade-checklist.md +14 -1
- package/consumer-extras/patterns/data-views-pattern.md +6 -0
- package/consumer-extras/patterns/drawer-vs-dialog-pattern.md +50 -0
- package/consumer-extras/patterns/hub-supported-views-pattern.md +53 -0
- package/dist/components/data-table/index.js +13 -9
- package/dist/components/data-table/index.js.map +1 -1
- package/dist/components/data-table/pagination.js +13 -9
- package/dist/components/data-table/pagination.js.map +1 -1
- package/dist/components/data-views/hub-table.d.ts +8 -4
- package/dist/components/data-views/hub-table.js +25 -10
- package/dist/components/data-views/hub-table.js.map +1 -1
- package/dist/components/data-views/index.d.ts +1 -1
- package/dist/components/data-views/index.js +25 -10
- package/dist/components/data-views/index.js.map +1 -1
- package/dist/components/data-views/list-page-connected-view-body.d.ts +1 -1
- package/dist/components/data-views/list-page-connected-view-body.js +1 -0
- package/dist/components/data-views/list-page-connected-view-body.js.map +1 -1
- package/dist/components/table-properties/drawer-button.js +1 -0
- package/dist/components/table-properties/drawer-button.js.map +1 -1
- package/dist/components/table-properties/drawer.js +1 -0
- package/dist/components/table-properties/drawer.js.map +1 -1
- package/dist/components/table-properties/index.d.ts +1 -1
- package/dist/components/table-properties/index.js +1 -0
- package/dist/components/table-properties/index.js.map +1 -1
- package/dist/components/templates/index.d.ts +1 -1
- package/dist/components/templates/index.js +12 -2
- package/dist/components/templates/index.js.map +1 -1
- package/dist/components/templates/list-page.d.ts +4 -2
- package/dist/components/templates/list-page.js +12 -2
- package/dist/components/templates/list-page.js.map +1 -1
- package/dist/{data-list-view-registry-CyBoBML4.d.ts → data-list-view-registry-BstmlfQ3.d.ts} +16 -1
- package/dist/index.d.ts +2 -3
- package/dist/index.js +135 -126
- package/dist/index.js.map +1 -1
- package/dist/lib/data-list-view-registry.d.ts +1 -1
- package/dist/lib/data-list-view-registry.js +17 -1
- package/dist/lib/data-list-view-registry.js.map +1 -1
- package/dist/lib/data-list-view-surface.d.ts +1 -1
- package/dist/lib/data-list-view-surface.js +1 -0
- package/dist/lib/data-list-view-surface.js.map +1 -1
- package/dist/lib/list-page-table-properties.d.ts +1 -1
- package/dist/lib/list-page-table-properties.js +1 -0
- package/dist/lib/list-page-table-properties.js.map +1 -1
- package/dist/lib/nav-active.d.ts +38 -0
- package/dist/lib/nav-active.js +104 -0
- package/dist/lib/nav-active.js.map +1 -0
- package/package.json +1 -2
- package/src/components/data-table/index.tsx +25 -17
- package/src/components/data-views/hub-table.tsx +9 -3
- package/src/components/templates/list-page.tsx +9 -3
- package/src/index.ts +1 -1
- package/src/lib/data-list-view-registry.ts +31 -0
- package/src/lib/nav-active.ts +162 -0
- package/template/.claude/skills/exxat-ds-skill/SKILL.md +2 -1
- package/template/.cursor/rules/exxat-accessibility.mdc +1 -1
- package/template/AGENTS.md +18 -3
- package/template/components/columns-client.tsx +3 -2
- package/template/components/columns-showcase.tsx +22 -18
- package/template/components/exxat-product-logo.tsx +1 -1
- package/template/components/library-table.tsx +62 -23
- package/template/components/new-library-item-form.tsx +0 -7
- package/template/components/product-wordmark.tsx +1 -1
- package/template/components/sidebar/app-sidebar.tsx +14 -106
- package/template/components/sidebar/secondary-nav.tsx +22 -4
- package/template/components/site-header.tsx +1 -1
- package/template/components/tokens-hub-auxiliary-views.tsx +301 -0
- package/template/components/tokens-themes-client.tsx +44 -16
- package/template/docs/HANDBOOK.md +2 -2
- package/template/docs/component-selection-guide.md +1 -1
- package/template/docs/consumer-upgrade-checklist.md +51 -0
- package/template/docs/data-views-pattern.md +6 -0
- package/template/docs/drawer-vs-dialog-pattern.md +8 -8
- package/template/docs/glossary.md +2 -1
- package/template/docs/hub-supported-views-pattern.md +53 -0
- package/template/docs/reference-implementations.md +2 -2
- package/template/lib/full-hub-supported-views.ts +8 -0
- package/template/lib/library-supported-views.ts +5 -12
- package/template/lib/motion-ui.ts +2 -2
- package/template/package.json +1 -1
- package/tokens/hooks-index.json +2 -2
- package/dist/components/ui/drawer.d.ts +0 -16
- package/dist/components/ui/drawer.js +0 -125
- package/dist/components/ui/drawer.js.map +0 -1
- package/src/components/ui/drawer.tsx +0 -134
- package/template/components/ui/drawer.tsx +0 -1
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
# Sheet panel vs dialog vs route
|
|
2
|
+
|
|
3
|
+
> **Related:** `docs/data-views-pattern.md` (Page vs drawer), **`AGENTS.md` §6.4**, **`.cursor/rules/exxat-page-vs-drawer.mdc`**. **This doc** splits **floating `Sheet` panels** vs **modal dialog** when both stay on the same route.
|
|
4
|
+
|
|
5
|
+
## Sheet (side panel — product “drawers”)
|
|
6
|
+
|
|
7
|
+
**Use when:**
|
|
8
|
+
|
|
9
|
+
- The **list or hub behind the panel** still matters (user compares, copies, or dismisses and continues browsing).
|
|
10
|
+
- The flow is **medium length** — export options, table/column properties, invite collaborators, filters that mirror the grid.
|
|
11
|
+
- **Width** helps — tables of options, multi-field forms that would feel cramped in a narrow dialog.
|
|
12
|
+
|
|
13
|
+
**Implementation:** **`Sheet`** from `@exxatdesignux/ui/components/sheet` with the floating inset pattern (`showOverlay={false}`, `getFloatingSheetInsetProps`) — see `ExportDrawer`, `TablePropertiesDrawer`, `InviteCollaboratorsDrawer`, `LibraryNewFolderSheet`.
|
|
14
|
+
|
|
15
|
+
**Avoid when:** The task is the **only** thing the user should focus on and the parent would distract (prefer **dialog** for a sharp confirm, or **route** for a full wizard).
|
|
16
|
+
|
|
17
|
+
## Dialog (modal)
|
|
18
|
+
|
|
19
|
+
**Use when:**
|
|
20
|
+
|
|
21
|
+
- You need a **hard stop** — user must answer or dismiss before interacting with the page again (confirm delete, acknowledge legal, pick a single blocking choice).
|
|
22
|
+
- The content is **short and focused** — one decision, one form step, or a compact message with primary/secondary actions.
|
|
23
|
+
- **Destructive or irreversible** actions — pair with clear copy; **Esc** / Cancel returns safely.
|
|
24
|
+
|
|
25
|
+
**Examples:** `AlertDialog`, confirm-before-remove, “Save changes?” when navigating away.
|
|
26
|
+
|
|
27
|
+
**Avoid when:** Users need to **reference** the grid or copy values from the page while the panel is open — use a **sheet panel** or **inline** pattern instead.
|
|
28
|
+
|
|
29
|
+
## Route (new page)
|
|
30
|
+
|
|
31
|
+
Use when the work is **primary**, **long**, **multi-step**, or deserves its **own URL** — see **`exxat-page-vs-drawer.mdc`** and **`AGENTS.md` §6.4**.
|
|
32
|
+
|
|
33
|
+
## Quick matrix
|
|
34
|
+
|
|
35
|
+
| Need | Sheet panel | Dialog | Route |
|
|
36
|
+
| --- | --- | --- | --- |
|
|
37
|
+
| Keep hub visible | Yes | No (blocks) | No |
|
|
38
|
+
| Short confirm / alert | Rare | Yes | Overkill |
|
|
39
|
+
| Long form / wizard | Cramped | No | Yes |
|
|
40
|
+
| Properties tied to a table | Yes | Too small | Optional |
|
|
41
|
+
|
|
42
|
+
## Accessibility
|
|
43
|
+
|
|
44
|
+
- **Dialog / sheet:** Must expose a **title** (`DialogTitle`, `SheetTitle`) — use `sr-only` if visually hidden.
|
|
45
|
+
- **Focus trap** is expected in dialogs; sheet panels should still **restore focus** on close to the invoking control.
|
|
46
|
+
|
|
47
|
+
## See also
|
|
48
|
+
|
|
49
|
+
- **`.cursor/rules/exxat-drawer-vs-dialog.mdc`**, **`.cursor/skills/exxat-drawer-vs-dialog/SKILL.md`**
|
|
50
|
+
- **`exxat-no-toast.mdc`** — use dialog/banner/inline, not toasts, for outcomes that need acknowledgment.
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
# Hub supported views pattern (Add view parity)
|
|
2
|
+
|
|
3
|
+
> **Agents:** `.cursor/rules/exxat-hub-supported-views.mdc` (binding). **Reference hub:** Library / All questions (`library-table.tsx`, `library-client.tsx`).
|
|
4
|
+
|
|
5
|
+
## Problem this solves
|
|
6
|
+
|
|
7
|
+
`ListPageTemplate` filters **Add view** and Properties view tiles from `supportedViewTypes`. If Column types passes four views but Library passes seven, users see inconsistent menus. If a hub allows Board but has no `board-with-toolbar` renderer, users see **“does not implement Board view”**.
|
|
8
|
+
|
|
9
|
+
## Canonical allowlist
|
|
10
|
+
|
|
11
|
+
Import from the registry (single source of truth):
|
|
12
|
+
|
|
13
|
+
```ts
|
|
14
|
+
import { FULL_HUB_SUPPORTED_VIEWS } from "@/lib/data-list-view-registry"
|
|
15
|
+
// or
|
|
16
|
+
import { LIBRARY_SUPPORTED_VIEWS } from "@/lib/library-supported-views" // alias of FULL
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
Seven views: **table**, **list**, **board**, **dashboard**, **folder**, **panel**, **tree-panel**.
|
|
20
|
+
|
|
21
|
+
`HubTable` and `ListPageTemplate` use this list when `supportedViewTypes` is omitted.
|
|
22
|
+
|
|
23
|
+
`PRIMARY_HUB_SUPPORTED_VIEWS` (four views) remains for hubs that intentionally omit folder/panel/tree — document that in `lib/<entity>-supported-views.ts`.
|
|
24
|
+
|
|
25
|
+
## Wiring checklist
|
|
26
|
+
|
|
27
|
+
1. **`ListPageTemplate`** — `supportedViewTypes={FULL_HUB_SUPPORTED_VIEWS}` (or entity alias).
|
|
28
|
+
2. **`HubTable`** — same allowlist (or omit on both).
|
|
29
|
+
3. **List** — `renderListRow` returning **`ListPageBoardCard`** `layout="row"` (copy from `library-table.tsx`).
|
|
30
|
+
4. **Board** — `renderBoardCard` + `boardGroups` and/or `renderers["board-with-toolbar"]`.
|
|
31
|
+
5. **Dashboard** — `renderers["dashboard-with-toolbar"]` with **`KeyMetrics`** on filtered rows.
|
|
32
|
+
6. **Folder / panel / tree** — explicit `renderers` entries (Library reference) or **`LibraryTable`** for `LibraryItem` rows.
|
|
33
|
+
|
|
34
|
+
## Special cases in this app
|
|
35
|
+
|
|
36
|
+
| Hub | Pattern |
|
|
37
|
+
|-----|---------|
|
|
38
|
+
| **Library / All questions** | `LibraryTable` + `LIBRARY_SUPPORTED_VIEWS` — reference |
|
|
39
|
+
| **Column types** | `LibraryTable` with `columnDefs` + `hubLabels` + `DEFAULT_LIBRARY_FOLDERS` — custom table, shared other views |
|
|
40
|
+
| **Tokens & themes** | `FULL_HUB_SUPPORTED_VIEWS` + `tokens-hub-auxiliary-views.tsx` |
|
|
41
|
+
| **New entity hub** | Start from `library-table.tsx` or token/columns references; never table-only unless approved |
|
|
42
|
+
|
|
43
|
+
## Anti-patterns
|
|
44
|
+
|
|
45
|
+
- `supportedViewTypes={["table"]}` on a `ListPageTemplate` hub.
|
|
46
|
+
- `COLUMNS_SUPPORTED_VIEWS = PRIMARY_HUB_SUPPORTED_VIEWS` without board/folder/panel/tree renderers.
|
|
47
|
+
- Minimal `renderListRow` with only stem + `questionId` (not product list UI).
|
|
48
|
+
|
|
49
|
+
## See also
|
|
50
|
+
|
|
51
|
+
- `packages/ui/src/lib/data-list-view-registry.ts`
|
|
52
|
+
- `docs/exxat-ds/patterns/data-views-pattern.md`
|
|
53
|
+
- `apps/web/lib/hub-connected-view-renderers.ts` — `defineHubViewRenderers` dev warnings
|
|
@@ -2256,13 +2256,15 @@ function useBulkBarFixedToTableScrollEl(scrollRef, active, fullWidth) {
|
|
|
2256
2256
|
const scheduled = rafThrottle(apply);
|
|
2257
2257
|
const ro = new ResizeObserver(scheduled);
|
|
2258
2258
|
ro.observe(el);
|
|
2259
|
+
el.addEventListener("scroll", scheduled, { passive: true });
|
|
2259
2260
|
window.addEventListener("resize", scheduled, { passive: true });
|
|
2260
|
-
window.addEventListener("scroll", scheduled, { passive: true
|
|
2261
|
+
window.addEventListener("scroll", scheduled, { passive: true });
|
|
2261
2262
|
return () => {
|
|
2262
2263
|
scheduled.cancel();
|
|
2263
2264
|
ro.disconnect();
|
|
2265
|
+
el.removeEventListener("scroll", scheduled);
|
|
2264
2266
|
window.removeEventListener("resize", scheduled);
|
|
2265
|
-
window.removeEventListener("scroll", scheduled
|
|
2267
|
+
window.removeEventListener("scroll", scheduled);
|
|
2266
2268
|
};
|
|
2267
2269
|
}, [active, fullWidth, scrollRef]);
|
|
2268
2270
|
return style;
|
|
@@ -2429,11 +2431,13 @@ function DataTableInner({
|
|
|
2429
2431
|
};
|
|
2430
2432
|
update();
|
|
2431
2433
|
const scheduled = rafThrottle(update);
|
|
2432
|
-
|
|
2434
|
+
wrapEl.addEventListener("scroll", scheduled, { passive: true });
|
|
2435
|
+
window.addEventListener("scroll", scheduled, { passive: true });
|
|
2433
2436
|
window.addEventListener("resize", scheduled, { passive: true });
|
|
2434
2437
|
return () => {
|
|
2435
2438
|
scheduled.cancel();
|
|
2436
|
-
|
|
2439
|
+
wrapEl.removeEventListener("scroll", scheduled);
|
|
2440
|
+
window.removeEventListener("scroll", scheduled);
|
|
2437
2441
|
window.removeEventListener("resize", scheduled);
|
|
2438
2442
|
};
|
|
2439
2443
|
}, [showColumnHeaders, rows.length, displayCols.length]);
|
|
@@ -2870,11 +2874,11 @@ function DataTableInner({
|
|
|
2870
2874
|
const rowPy = rowHeight === "compact" ? "py-1" : rowHeight === "comfortable" ? "py-4" : "py-2.5";
|
|
2871
2875
|
const cs = cellStyle(col.key);
|
|
2872
2876
|
const tdBase = cn(
|
|
2873
|
-
`px-3 ${rowPy} align-middle`,
|
|
2877
|
+
`px-3 ${rowPy} align-middle max-w-0`,
|
|
2874
2878
|
showGridlines && !isEdgePin && "border-e border-border last:border-e-0",
|
|
2875
2879
|
"border-b border-border group-last/row:border-b-0",
|
|
2876
2880
|
isPinned && [
|
|
2877
|
-
"z-20 pinned-cell",
|
|
2881
|
+
"z-20 pinned-cell relative",
|
|
2878
2882
|
"bg-dt-row-bg",
|
|
2879
2883
|
"group-data-[state=selected]/row:bg-dt-row-selected",
|
|
2880
2884
|
"group-hover/row:bg-dt-row-hover",
|
|
@@ -2924,17 +2928,17 @@ function DataTableInner({
|
|
|
2924
2928
|
wrap && "[&_.truncate]:!whitespace-normal [&_.truncate]:!overflow-visible [&_.truncate]:!text-clip"
|
|
2925
2929
|
),
|
|
2926
2930
|
style: tdStyle,
|
|
2927
|
-
children: col.cell(row, {
|
|
2931
|
+
children: /* @__PURE__ */ jsx("div", { className: "min-w-0 overflow-hidden", children: col.cell(row, {
|
|
2928
2932
|
rowIndex,
|
|
2929
2933
|
selected: isSelected,
|
|
2930
2934
|
onSelect: (checked) => checked ? setSelected((prev) => /* @__PURE__ */ new Set([...prev, rowId])) : toggleRow(rowId)
|
|
2931
|
-
})
|
|
2935
|
+
}) })
|
|
2932
2936
|
},
|
|
2933
2937
|
col.key
|
|
2934
2938
|
);
|
|
2935
2939
|
}
|
|
2936
2940
|
const rawVal = String(row[col.key] ?? "");
|
|
2937
|
-
return /* @__PURE__ */ jsx("td", { className: cn(tdBase, "text-sm text-foreground/80"), style: tdStyle, children: /* @__PURE__ */ jsx("span", { className: wrap ? "whitespace-normal" : "block truncate", title: !wrap ? rawVal : void 0, children: rawVal }) }, col.key);
|
|
2941
|
+
return /* @__PURE__ */ jsx("td", { className: cn(tdBase, "text-sm text-foreground/80"), style: tdStyle, children: /* @__PURE__ */ jsx("div", { className: "min-w-0 overflow-hidden", children: /* @__PURE__ */ jsx("span", { className: wrap ? "whitespace-normal" : "block truncate", title: !wrap ? rawVal : void 0, children: rawVal }) }) }, col.key);
|
|
2938
2942
|
})
|
|
2939
2943
|
},
|
|
2940
2944
|
String(rowId)
|