@tailor-platform/app-shell 1.11.0 → 1.13.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -0
- package/dist/app-shell-core.css +3 -1
- package/dist/app-shell.d.ts +1192 -88
- package/dist/app-shell.js +10669 -13117
- package/dist/appshell-CSQWUk6q.js +1823 -0
- package/dist/fonts/NOTO-SANS-JP-LICENSE.txt +93 -0
- package/dist/fonts/files/noto-sans-jp-0-wght-normal.woff2 +0 -0
- package/dist/fonts/files/noto-sans-jp-1-wght-normal.woff2 +0 -0
- package/dist/fonts/files/noto-sans-jp-10-wght-normal.woff2 +0 -0
- package/dist/fonts/files/noto-sans-jp-100-wght-normal.woff2 +0 -0
- package/dist/fonts/files/noto-sans-jp-101-wght-normal.woff2 +0 -0
- package/dist/fonts/files/noto-sans-jp-102-wght-normal.woff2 +0 -0
- package/dist/fonts/files/noto-sans-jp-103-wght-normal.woff2 +0 -0
- package/dist/fonts/files/noto-sans-jp-104-wght-normal.woff2 +0 -0
- package/dist/fonts/files/noto-sans-jp-105-wght-normal.woff2 +0 -0
- package/dist/fonts/files/noto-sans-jp-106-wght-normal.woff2 +0 -0
- package/dist/fonts/files/noto-sans-jp-107-wght-normal.woff2 +0 -0
- package/dist/fonts/files/noto-sans-jp-108-wght-normal.woff2 +0 -0
- package/dist/fonts/files/noto-sans-jp-109-wght-normal.woff2 +0 -0
- package/dist/fonts/files/noto-sans-jp-11-wght-normal.woff2 +0 -0
- package/dist/fonts/files/noto-sans-jp-110-wght-normal.woff2 +0 -0
- package/dist/fonts/files/noto-sans-jp-111-wght-normal.woff2 +0 -0
- package/dist/fonts/files/noto-sans-jp-112-wght-normal.woff2 +0 -0
- package/dist/fonts/files/noto-sans-jp-113-wght-normal.woff2 +0 -0
- package/dist/fonts/files/noto-sans-jp-114-wght-normal.woff2 +0 -0
- package/dist/fonts/files/noto-sans-jp-115-wght-normal.woff2 +0 -0
- package/dist/fonts/files/noto-sans-jp-116-wght-normal.woff2 +0 -0
- package/dist/fonts/files/noto-sans-jp-117-wght-normal.woff2 +0 -0
- package/dist/fonts/files/noto-sans-jp-118-wght-normal.woff2 +0 -0
- package/dist/fonts/files/noto-sans-jp-119-wght-normal.woff2 +0 -0
- package/dist/fonts/files/noto-sans-jp-12-wght-normal.woff2 +0 -0
- package/dist/fonts/files/noto-sans-jp-13-wght-normal.woff2 +0 -0
- package/dist/fonts/files/noto-sans-jp-14-wght-normal.woff2 +0 -0
- package/dist/fonts/files/noto-sans-jp-15-wght-normal.woff2 +0 -0
- package/dist/fonts/files/noto-sans-jp-16-wght-normal.woff2 +0 -0
- package/dist/fonts/files/noto-sans-jp-17-wght-normal.woff2 +0 -0
- package/dist/fonts/files/noto-sans-jp-18-wght-normal.woff2 +0 -0
- package/dist/fonts/files/noto-sans-jp-19-wght-normal.woff2 +0 -0
- package/dist/fonts/files/noto-sans-jp-2-wght-normal.woff2 +0 -0
- package/dist/fonts/files/noto-sans-jp-20-wght-normal.woff2 +0 -0
- package/dist/fonts/files/noto-sans-jp-21-wght-normal.woff2 +0 -0
- package/dist/fonts/files/noto-sans-jp-22-wght-normal.woff2 +0 -0
- package/dist/fonts/files/noto-sans-jp-23-wght-normal.woff2 +0 -0
- package/dist/fonts/files/noto-sans-jp-24-wght-normal.woff2 +0 -0
- package/dist/fonts/files/noto-sans-jp-25-wght-normal.woff2 +0 -0
- package/dist/fonts/files/noto-sans-jp-26-wght-normal.woff2 +0 -0
- package/dist/fonts/files/noto-sans-jp-27-wght-normal.woff2 +0 -0
- package/dist/fonts/files/noto-sans-jp-28-wght-normal.woff2 +0 -0
- package/dist/fonts/files/noto-sans-jp-29-wght-normal.woff2 +0 -0
- package/dist/fonts/files/noto-sans-jp-3-wght-normal.woff2 +0 -0
- package/dist/fonts/files/noto-sans-jp-30-wght-normal.woff2 +0 -0
- package/dist/fonts/files/noto-sans-jp-31-wght-normal.woff2 +0 -0
- package/dist/fonts/files/noto-sans-jp-32-wght-normal.woff2 +0 -0
- package/dist/fonts/files/noto-sans-jp-33-wght-normal.woff2 +0 -0
- package/dist/fonts/files/noto-sans-jp-34-wght-normal.woff2 +0 -0
- package/dist/fonts/files/noto-sans-jp-35-wght-normal.woff2 +0 -0
- package/dist/fonts/files/noto-sans-jp-36-wght-normal.woff2 +0 -0
- package/dist/fonts/files/noto-sans-jp-37-wght-normal.woff2 +0 -0
- package/dist/fonts/files/noto-sans-jp-38-wght-normal.woff2 +0 -0
- package/dist/fonts/files/noto-sans-jp-39-wght-normal.woff2 +0 -0
- package/dist/fonts/files/noto-sans-jp-4-wght-normal.woff2 +0 -0
- package/dist/fonts/files/noto-sans-jp-40-wght-normal.woff2 +0 -0
- package/dist/fonts/files/noto-sans-jp-41-wght-normal.woff2 +0 -0
- package/dist/fonts/files/noto-sans-jp-42-wght-normal.woff2 +0 -0
- package/dist/fonts/files/noto-sans-jp-43-wght-normal.woff2 +0 -0
- package/dist/fonts/files/noto-sans-jp-44-wght-normal.woff2 +0 -0
- package/dist/fonts/files/noto-sans-jp-45-wght-normal.woff2 +0 -0
- package/dist/fonts/files/noto-sans-jp-46-wght-normal.woff2 +0 -0
- package/dist/fonts/files/noto-sans-jp-47-wght-normal.woff2 +0 -0
- package/dist/fonts/files/noto-sans-jp-48-wght-normal.woff2 +0 -0
- package/dist/fonts/files/noto-sans-jp-49-wght-normal.woff2 +0 -0
- package/dist/fonts/files/noto-sans-jp-5-wght-normal.woff2 +0 -0
- package/dist/fonts/files/noto-sans-jp-50-wght-normal.woff2 +0 -0
- package/dist/fonts/files/noto-sans-jp-51-wght-normal.woff2 +0 -0
- package/dist/fonts/files/noto-sans-jp-52-wght-normal.woff2 +0 -0
- package/dist/fonts/files/noto-sans-jp-53-wght-normal.woff2 +0 -0
- package/dist/fonts/files/noto-sans-jp-54-wght-normal.woff2 +0 -0
- package/dist/fonts/files/noto-sans-jp-55-wght-normal.woff2 +0 -0
- package/dist/fonts/files/noto-sans-jp-6-wght-normal.woff2 +0 -0
- package/dist/fonts/files/noto-sans-jp-60-wght-normal.woff2 +0 -0
- package/dist/fonts/files/noto-sans-jp-61-wght-normal.woff2 +0 -0
- package/dist/fonts/files/noto-sans-jp-62-wght-normal.woff2 +0 -0
- package/dist/fonts/files/noto-sans-jp-63-wght-normal.woff2 +0 -0
- package/dist/fonts/files/noto-sans-jp-64-wght-normal.woff2 +0 -0
- package/dist/fonts/files/noto-sans-jp-65-wght-normal.woff2 +0 -0
- package/dist/fonts/files/noto-sans-jp-66-wght-normal.woff2 +0 -0
- package/dist/fonts/files/noto-sans-jp-67-wght-normal.woff2 +0 -0
- package/dist/fonts/files/noto-sans-jp-68-wght-normal.woff2 +0 -0
- package/dist/fonts/files/noto-sans-jp-69-wght-normal.woff2 +0 -0
- package/dist/fonts/files/noto-sans-jp-7-wght-normal.woff2 +0 -0
- package/dist/fonts/files/noto-sans-jp-70-wght-normal.woff2 +0 -0
- package/dist/fonts/files/noto-sans-jp-71-wght-normal.woff2 +0 -0
- package/dist/fonts/files/noto-sans-jp-72-wght-normal.woff2 +0 -0
- package/dist/fonts/files/noto-sans-jp-73-wght-normal.woff2 +0 -0
- package/dist/fonts/files/noto-sans-jp-74-wght-normal.woff2 +0 -0
- package/dist/fonts/files/noto-sans-jp-75-wght-normal.woff2 +0 -0
- package/dist/fonts/files/noto-sans-jp-76-wght-normal.woff2 +0 -0
- package/dist/fonts/files/noto-sans-jp-77-wght-normal.woff2 +0 -0
- package/dist/fonts/files/noto-sans-jp-78-wght-normal.woff2 +0 -0
- package/dist/fonts/files/noto-sans-jp-79-wght-normal.woff2 +0 -0
- package/dist/fonts/files/noto-sans-jp-8-wght-normal.woff2 +0 -0
- package/dist/fonts/files/noto-sans-jp-80-wght-normal.woff2 +0 -0
- package/dist/fonts/files/noto-sans-jp-81-wght-normal.woff2 +0 -0
- package/dist/fonts/files/noto-sans-jp-82-wght-normal.woff2 +0 -0
- package/dist/fonts/files/noto-sans-jp-83-wght-normal.woff2 +0 -0
- package/dist/fonts/files/noto-sans-jp-84-wght-normal.woff2 +0 -0
- package/dist/fonts/files/noto-sans-jp-85-wght-normal.woff2 +0 -0
- package/dist/fonts/files/noto-sans-jp-86-wght-normal.woff2 +0 -0
- package/dist/fonts/files/noto-sans-jp-87-wght-normal.woff2 +0 -0
- package/dist/fonts/files/noto-sans-jp-88-wght-normal.woff2 +0 -0
- package/dist/fonts/files/noto-sans-jp-89-wght-normal.woff2 +0 -0
- package/dist/fonts/files/noto-sans-jp-9-wght-normal.woff2 +0 -0
- package/dist/fonts/files/noto-sans-jp-90-wght-normal.woff2 +0 -0
- package/dist/fonts/files/noto-sans-jp-91-wght-normal.woff2 +0 -0
- package/dist/fonts/files/noto-sans-jp-92-wght-normal.woff2 +0 -0
- package/dist/fonts/files/noto-sans-jp-93-wght-normal.woff2 +0 -0
- package/dist/fonts/files/noto-sans-jp-94-wght-normal.woff2 +0 -0
- package/dist/fonts/files/noto-sans-jp-95-wght-normal.woff2 +0 -0
- package/dist/fonts/files/noto-sans-jp-96-wght-normal.woff2 +0 -0
- package/dist/fonts/files/noto-sans-jp-97-wght-normal.woff2 +0 -0
- package/dist/fonts/files/noto-sans-jp-98-wght-normal.woff2 +0 -0
- package/dist/fonts/files/noto-sans-jp-99-wght-normal.woff2 +0 -0
- package/dist/fonts/noto-sans-jp.css +2506 -0
- package/dist/style-entry.d.ts +600 -0
- package/dist/style-entry.js +0 -1
- package/dist/testing.d.ts +1140 -0
- package/dist/testing.js +14 -0
- package/dist/theme-bridge.test.ts +59 -0
- package/dist/theme.bridge.css +50 -1
- package/dist/vite-plugin.d.ts +600 -0
- package/dist/vite-plugin.js +2 -4
- package/package.json +27 -19
- package/skills/app-shell-patterns/SKILL.md +14 -7
- package/skills/app-shell-patterns/references/fundamental/components.md +56 -3
- package/skills/app-shell-patterns/references/fundamental/design-system.md +216 -162
- package/skills/app-shell-patterns/references/migrations.md +167 -0
- package/skills/app-shell-patterns/references/patterns/form-composer.md +142 -0
- package/skills/app-shell-patterns/references/patterns/form-single-page.md +3 -3
- package/skills/app-shell-patterns/references/patterns/form-wizard.md +5 -3
- package/skills/app-shell-patterns/references/patterns/interaction-multi-select.md +1 -1
package/dist/vite-plugin.js
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@tailor-platform/app-shell",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.13.0",
|
|
4
4
|
"description": "An opinionated React application framework for building ERP applications on Tailor Platform",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"app-shell",
|
|
@@ -37,16 +37,20 @@
|
|
|
37
37
|
"./vite-plugin": {
|
|
38
38
|
"types": "./dist/vite-plugin.d.ts",
|
|
39
39
|
"default": "./dist/vite-plugin.js"
|
|
40
|
+
},
|
|
41
|
+
"./testing": {
|
|
42
|
+
"types": "./dist/testing.d.ts",
|
|
43
|
+
"default": "./dist/testing.js"
|
|
40
44
|
}
|
|
41
45
|
},
|
|
42
46
|
"publishConfig": {
|
|
43
47
|
"access": "public"
|
|
44
48
|
},
|
|
45
49
|
"dependencies": {
|
|
46
|
-
"@base-ui/react": "
|
|
50
|
+
"@base-ui/react": "1.6.0",
|
|
47
51
|
"@internationalized/date": "3.12.2",
|
|
48
52
|
"@standard-schema/spec": "^1.1.0",
|
|
49
|
-
"@tailor-platform/auth-public-client": "^0.
|
|
53
|
+
"@tailor-platform/auth-public-client": "^0.6.1",
|
|
50
54
|
"change-case": "^5.4.4",
|
|
51
55
|
"class-variance-authority": "^0.7.1",
|
|
52
56
|
"clsx": "^2.1.1",
|
|
@@ -60,27 +64,29 @@
|
|
|
60
64
|
"@tailor-platform/app-shell-vite-plugin": "0.2.3"
|
|
61
65
|
},
|
|
62
66
|
"devDependencies": {
|
|
63
|
-
"@
|
|
64
|
-
"@
|
|
65
|
-
"@
|
|
66
|
-
"@
|
|
67
|
+
"@fontsource-variable/noto-sans-jp": "5.3.0",
|
|
68
|
+
"@microsoft/api-extractor": "7.58.12",
|
|
69
|
+
"@tailwindcss/postcss": "^4.3.3",
|
|
70
|
+
"@testing-library/react": "16.3.3",
|
|
71
|
+
"@testing-library/user-event": "14.6.6",
|
|
72
|
+
"@types/encoding-japanese": "2.2.1",
|
|
67
73
|
"@types/node": "^25.9.5",
|
|
68
|
-
"@types/papaparse": "
|
|
74
|
+
"@types/papaparse": "5.5.2",
|
|
69
75
|
"@types/react": "^19",
|
|
70
76
|
"@types/react-dom": "^19",
|
|
71
|
-
"@vitejs/plugin-react": "^
|
|
72
|
-
"
|
|
73
|
-
"
|
|
77
|
+
"@vitejs/plugin-react": "^6.1.0",
|
|
78
|
+
"@vitest/coverage-v8": "4.1.10",
|
|
79
|
+
"happy-dom": "20.9.0",
|
|
80
|
+
"postcss": "8.5.26",
|
|
74
81
|
"react": "^19.2.7",
|
|
75
82
|
"react-dom": "^19.2.7",
|
|
76
|
-
"
|
|
77
|
-
"
|
|
78
|
-
"
|
|
79
|
-
"
|
|
80
|
-
"vite
|
|
81
|
-
"vite-plugin-
|
|
82
|
-
"
|
|
83
|
-
"vitest": "^4.1.6"
|
|
83
|
+
"react-hook-form": "7.71.2",
|
|
84
|
+
"tailwindcss": "^4.3.3",
|
|
85
|
+
"tw-animate-css": "1.4.0",
|
|
86
|
+
"typescript": "5.9.3",
|
|
87
|
+
"vite": "^8.2.2",
|
|
88
|
+
"vite-plugin-dts": "5.0.3",
|
|
89
|
+
"vitest": "^4.1.10"
|
|
84
90
|
},
|
|
85
91
|
"peerDependencies": {
|
|
86
92
|
"react": ">=19.2.7",
|
|
@@ -89,6 +95,8 @@
|
|
|
89
95
|
"scripts": {
|
|
90
96
|
"dev": "vite build --watch --mode development",
|
|
91
97
|
"build": "vite build",
|
|
98
|
+
"check-dts": "node scripts/check-dts.mjs",
|
|
99
|
+
"vendor:fonts": "node scripts/sync-noto-fonts.mjs",
|
|
92
100
|
"lint": "oxlint -c .oxlintrc.jsonc",
|
|
93
101
|
"test": "vitest run",
|
|
94
102
|
"type-check": "tsc --incremental"
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: app-shell-patterns
|
|
3
|
-
description: "Best-practice UI patterns and correct component usage for building pages in apps that use @tailor-platform/app-shell. Use when: building or editing any screen, page, list, table, detail view, form, modal, dialog, wizard, or bulk/confirm/toast interaction in an app with @tailor-platform/app-shell installed —
|
|
3
|
+
description: "Best-practice UI patterns and correct component usage for building pages in apps that use @tailor-platform/app-shell. Use when: building or editing any screen, page, list, table, detail view, form, modal, dialog, wizard, or bulk/confirm/toast interaction in an app with @tailor-platform/app-shell installed — when choosing the right AppShell component, layout, or design token for a UI — or when upgrading @tailor-platform/app-shell, or diagnosing styling, theming, or dark-mode breakage that appeared after a version bump."
|
|
4
4
|
---
|
|
5
5
|
|
|
6
6
|
# App-Shell Patterns
|
|
@@ -19,6 +19,12 @@ These are the foundational rules that underpin all patterns. All patterns build
|
|
|
19
19
|
| [design-system.md](references/fundamental/design-system.md) | design-system reference |
|
|
20
20
|
| [graphql.md](references/fundamental/graphql.md) | graphql reference |
|
|
21
21
|
|
|
22
|
+
## Migrations
|
|
23
|
+
|
|
24
|
+
[`migrations.md`](references/migrations.md) lists every change that requires editing the consuming app, newest first — what breaks, how to detect it, and what to change.
|
|
25
|
+
|
|
26
|
+
Read it when upgrading `@tailor-platform/app-shell`, and whenever styling, theming, or dark mode looks wrong after a version bump. These breakages are silent: the build succeeds and nothing warns, so the cause is not discoverable from the error output. The package ships no CHANGELOG, so this file is the only migration record available locally.
|
|
27
|
+
|
|
22
28
|
## Available Patterns
|
|
23
29
|
|
|
24
30
|
### detail
|
|
@@ -29,12 +35,13 @@ These are the foundational rules that underpin all patterns. All patterns build
|
|
|
29
35
|
|
|
30
36
|
### form
|
|
31
37
|
|
|
32
|
-
| Slug | Name | Description
|
|
33
|
-
| ------------------------------------------------------------- | ---------------- |
|
|
34
|
-
| [`form/
|
|
35
|
-
| [`form/
|
|
36
|
-
| [`form/
|
|
37
|
-
| [`form/
|
|
38
|
+
| Slug | Name | Description |
|
|
39
|
+
| ------------------------------------------------------------- | ---------------- | ------------------------------------------------------------------------------------------------------------------------ |
|
|
40
|
+
| [`form/composer`](references/patterns/form-composer.md) | Composer | Free-text composer — a multi-line input above a trailing action row, for notes, replies, and comments submitted in place |
|
|
41
|
+
| [`form/modal`](references/patterns/form-modal.md) | Modal Form | Default form pattern for Create/Edit — keeps user in context on the parent screen |
|
|
42
|
+
| [`form/sectioned`](references/patterns/form-sectioned.md) | Sectioned Form | Complex form with 15+ fields organized into named fieldset sections |
|
|
43
|
+
| [`form/single-page`](references/patterns/form-single-page.md) | Single Page Form | Routed full-page form for moderate field count (6-15) without natural sectioning |
|
|
44
|
+
| [`form/wizard`](references/patterns/form-wizard.md) | Wizard Form | Multi-stage create flow with 3-7 steps and per-step validation gates |
|
|
38
45
|
|
|
39
46
|
### interaction
|
|
40
47
|
|
|
@@ -194,6 +194,13 @@ import { Button, Link } from '@tailor-platform/app-shell';
|
|
|
194
194
|
**API:** `to`, `replace`, `state`, etc. — same as `react-router`.
|
|
195
195
|
**Used in patterns:** all (navigation).
|
|
196
196
|
|
|
197
|
+
### `NavLink`
|
|
198
|
+
|
|
199
|
+
**Import:** `import { NavLink } from '@tailor-platform/app-shell'`
|
|
200
|
+
**Purpose:** `Link` that knows when it is active — for nav menus and tab bars.
|
|
201
|
+
**API:** `to`, plus `className` / `style` / `children` as render functions receiving `{ isActive, isPending }`.
|
|
202
|
+
**Used in patterns:** navigation shells.
|
|
203
|
+
|
|
197
204
|
### `Dialog`
|
|
198
205
|
|
|
199
206
|
> Full API: [https://raw.githubusercontent.com/tailor-platform/app-shell/refs/heads/main/docs/components/dialog.md](https://raw.githubusercontent.com/tailor-platform/app-shell/refs/heads/main/docs/components/dialog.md)
|
|
@@ -250,7 +257,7 @@ import { Button, Link } from '@tailor-platform/app-shell';
|
|
|
250
257
|
|
|
251
258
|
**Used in patterns:** `list/*` (filter sheet variant).
|
|
252
259
|
|
|
253
|
-
**Notes:** Size the panel with **`
|
|
260
|
+
**Notes:** Size the panel with `Sheet.Content`'s **`size`** prop (`"sm" | "md" | "lg" | "xl" | "full"`, default `"sm"`) — not a width utility. `astw:` rules → **`design-system.md`** §5.
|
|
254
261
|
|
|
255
262
|
### `Menu`
|
|
256
263
|
|
|
@@ -378,7 +385,7 @@ Plus `badgeVariants` CVA for custom-styled siblings.
|
|
|
378
385
|
|
|
379
386
|
**Notes:**
|
|
380
387
|
|
|
381
|
-
- **Inside a card?** Pass `containerClassName="astw:px-6"` on `Table.Root` for the horizontal inset, and either drop `Card.Content` (bare list form) or pass `Card.Content className="astw:px-0"` (header+content form). Skipping the `containerClassName` lands the first column flush against the card edge. See the `Card` entry for the two canonical forms and a DON'T example. Dense cell typography (**`text-
|
|
388
|
+
- **Inside a card?** Pass `containerClassName="astw:px-6"` on `Table.Root` for the horizontal inset, and either drop `Card.Content` (bare list form) or pass `Card.Content className="astw:px-0"` (header+content form). Skipping the `containerClassName` lands the first column flush against the card edge. See the `Card` entry for the two canonical forms and a DON'T example. Dense cell typography (**`text-sm`**, **`tabular-nums`** for figures, **`font-mono`** for identifiers) → **`design-system.md`** §4 Typography.
|
|
382
389
|
- **Whole row is clickable.** Use `<Table.Row onClick={() => navigate(detailPath)} className="astw:cursor-pointer">`. For keyboard and screen-reader users, also wrap the primary identifier cell content in `<Link>` (so the row is reachable via Tab; `Table.Row` is a `<tr>` and cannot itself be a Link — wrapping a `<tr>` in `<a>` is invalid HTML). **No per-row "View" / "Open" / "→" buttons.** Per-row `Menu` (overflow `…`) is the only allowed per-row action surface and is reserved for non-navigation actions like Archive, Duplicate.
|
|
383
390
|
|
|
384
391
|
### `DataTable`
|
|
@@ -387,7 +394,7 @@ Plus `badgeVariants` CVA for custom-styled siblings.
|
|
|
387
394
|
|
|
388
395
|
**Import:** compound namespace + helpers from `'@tailor-platform/app-shell'`, e.g. `DataTable`, `useDataTable`, `useCollectionVariables`, `createColumnHelper`, and types such as `Column`, `UseDataTableReturn`.
|
|
389
396
|
|
|
390
|
-
**Purpose:** Production list screens over GraphQL **connections**. Owns toolbar filter chips (**`DataTable.Filters`** from column `filter` configs), header sort, **`DataTable.Pagination`** (cursor-first; First/Last when `total` is provided), loading skeleton/error row, **`onClickRow`**, **`rowActions`** (kebab column), **`onSelectionChange`** (checkbox column), **column pinning** (`pin: "left" | "right"`) and built-in **column settings** (`<DataTable.Toolbar columnSettings>` — user show/hide + reorder + pin, persisted per-user via **`tableId`**).
|
|
397
|
+
**Purpose:** Production list screens over GraphQL **connections**. Owns toolbar filter chips (**`DataTable.Filters`** from column `filter` configs), header sort, **`DataTable.Pagination`** (cursor-first; First/Last when `total` is provided), loading skeleton/error row, **`onClickRow`**, **`rowActions`** (kebab column), **`onSelectionChange`** (checkbox column), **expandable rows** (**`rowExpansion`** — a chevron column plus a full-width detail panel per row; `render` with optional `canExpand` / `getLabel`, and `expandedIds` + `onChange` for controlled mode), **column pinning** (`pin: "left" | "right"`) and built-in **column settings** (`<DataTable.Toolbar columnSettings>` — user show/hide + reorder + pin, persisted per-user via **`tableId`**).
|
|
391
398
|
|
|
392
399
|
**Primitives:** Builds on low-level **`Table`**; do not reinvent pagination/filters manually unless the dataset is trivial.
|
|
393
400
|
|
|
@@ -643,6 +650,26 @@ const table = useDataTable({
|
|
|
643
650
|
**API:** `InputProps` — extends native `<input>` props.
|
|
644
651
|
**Used in patterns:** all `form/*`.
|
|
645
652
|
|
|
653
|
+
### `Textarea`
|
|
654
|
+
|
|
655
|
+
> Full API: [https://raw.githubusercontent.com/tailor-platform/app-shell/refs/heads/main/docs/components/textarea.md](https://raw.githubusercontent.com/tailor-platform/app-shell/refs/heads/main/docs/components/textarea.md)
|
|
656
|
+
|
|
657
|
+
**Import:** `import { Textarea } from '@tailor-platform/app-shell'`
|
|
658
|
+
**Purpose:** Multi-line text input. Maps to spec field types: `text`, long-form `string`. Use instead of `Input` whenever the value is prose (notes, descriptions, replies, reasons).
|
|
659
|
+
**API:** `TextareaProps` — Base UI's field control (`value`, `defaultValue`, `onChange`, `onValueChange`, `disabled`, `required`, `readOnly`, `name`, aria-\*) rendered as a `<textarea>`, plus `rows`. `cols` / `wrap` are not accepted — the control is `w-full`, so neither can take effect.
|
|
660
|
+
**Sizing:** no fixed height — `rows` sets the visible line count and the user can drag it taller. `min-h-16` is a hard floor, so `rows` only takes effect from 3 up. Width is the parent's job: the control is `w-full`, and `cols` is not accepted because it could never win against that. Do **not** reach for `Input` and a height override; `Input` is locked to `h-9`, and an `astw:h-*` override from a consuming app resolves to nothing unless that exact utility was compiled into the package CSS.
|
|
661
|
+
**Field integration:** drops straight into `Field.Root` for label/description/error wiring exactly like `Input` and `Checkbox` — no bespoke `error` prop.
|
|
662
|
+
**Example:**
|
|
663
|
+
|
|
664
|
+
```tsx
|
|
665
|
+
<Field.Root name="reason">
|
|
666
|
+
<Field.Label>Reason</Field.Label>
|
|
667
|
+
<Textarea rows={4} placeholder="Why is this being rejected?" />
|
|
668
|
+
</Field.Root>
|
|
669
|
+
```
|
|
670
|
+
|
|
671
|
+
**Used in patterns:** `form/composer`, `form/*` (long-text fields).
|
|
672
|
+
|
|
646
673
|
### `Checkbox`
|
|
647
674
|
|
|
648
675
|
**Import:** `import { Checkbox } from '@tailor-platform/app-shell'`
|
|
@@ -730,6 +757,32 @@ Types for authoring guard functions used by `WithGuard` and `appShellPageProps.g
|
|
|
730
757
|
**Purpose:** Re-exported from `react-router`. Use the AppShell barrel — never import from `react-router` directly.
|
|
731
758
|
**Used in patterns:** all (navigation, route params, query state).
|
|
732
759
|
|
|
760
|
+
### `useMatch`, `useResolvedPath`, `useNavigation`
|
|
761
|
+
|
|
762
|
+
**Import:** `import { useMatch, useResolvedPath, useNavigation } from '@tailor-platform/app-shell'`
|
|
763
|
+
**Purpose:** `useMatch` tests a pattern against the current location (active states); `useResolvedPath` resolves a relative path; `useNavigation` exposes the in-flight navigation for pending UI.
|
|
764
|
+
**Used in patterns:** navigation shells, list→detail transitions.
|
|
765
|
+
|
|
766
|
+
### `useBlocker`, `useBeforeUnload`
|
|
767
|
+
|
|
768
|
+
**Import:** `import { useBlocker, useBeforeUnload } from '@tailor-platform/app-shell'`
|
|
769
|
+
**Purpose:** Guard navigation away from unsaved work — `useBlocker` for in-app navigation, `useBeforeUnload` for closing or reloading the tab.
|
|
770
|
+
**Used in patterns:** form-heavy screens.
|
|
771
|
+
|
|
772
|
+
### Types
|
|
773
|
+
|
|
774
|
+
**Import:** `import type { Location, NavigateFunction, NavigateOptions, To, Params, PathMatch, LinkProps, NavLinkProps, Navigation, Blocker, BlockerFunction } from '@tailor-platform/app-shell'`
|
|
775
|
+
**Purpose:** The React Router types that go with the hooks above, so app code never imports types from `react-router` either.
|
|
776
|
+
|
|
777
|
+
### Not exported
|
|
778
|
+
|
|
779
|
+
`createBrowserRouter`, `RouterProvider`, `MemoryRouter`, `Routes`, `Route` — AppShell builds the router; a second one nested inside it breaks navigation. `useLoaderData`, `Form`, `useSubmit`, `useFetcher`, `useActionData` — AppShell does not wire up React Router's data layer. Load data in the page component or the app's data layer.
|
|
780
|
+
|
|
781
|
+
### Testing
|
|
782
|
+
|
|
783
|
+
**Import:** `import { AppShell, TestRouter } from '@tailor-platform/app-shell/testing'`
|
|
784
|
+
**Purpose:** Test routing without a `react-router` dependency. `AppShell` from this entry also accepts `memory` / `initialEntries`, for mounting a page at a fixed URL; `TestRouter` gives a single component router context, and takes `path` when that component reads the route (`useParams` is `{}` without it).
|
|
785
|
+
|
|
733
786
|
### `createTypedPaths`
|
|
734
787
|
|
|
735
788
|
**Import:** `import { createTypedPaths } from '@tailor-platform/app-shell'`
|