@tailor-platform/app-shell 1.15.0 → 1.17.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (109) hide show
  1. package/dist/app-shell-core.css +1 -1
  2. package/dist/app-shell.d.ts +811 -131
  3. package/dist/app-shell.js +7155 -5797
  4. package/dist/{appshell-DLVBFo5J.js → appshell-CahhZy7v.js} +656 -524
  5. package/dist/semantic-contrast.test.ts +154 -0
  6. package/dist/style-entry.d.ts +147 -92
  7. package/dist/testing.d.ts +152 -95
  8. package/dist/testing.js +1 -1
  9. package/dist/theme-bridge.test.ts +101 -1
  10. package/dist/theme.bridge.css +91 -0
  11. package/dist/theme.css +6 -1
  12. package/dist/themes/_template.css +7 -1
  13. package/dist/themes/bloom.css +0 -6
  14. package/dist/themes/cream.css +0 -6
  15. package/dist/themes/default.css +389 -69
  16. package/dist/vite-plugin.d.ts +147 -92
  17. package/package.json +8 -8
  18. package/skills/app-shell-patterns/SKILL.md +108 -19
  19. package/skills/app-shell-patterns/references/api/create-ai-gateway-client.md +115 -0
  20. package/skills/app-shell-patterns/references/api/create-typed-paths.md +117 -0
  21. package/skills/app-shell-patterns/references/api/define-i18n-labels.md +143 -0
  22. package/skills/app-shell-patterns/references/api/define-module.md +247 -0
  23. package/skills/app-shell-patterns/references/api/define-resource.md +307 -0
  24. package/skills/app-shell-patterns/references/api/guards/hidden.md +202 -0
  25. package/skills/app-shell-patterns/references/api/guards/overview.md +354 -0
  26. package/skills/app-shell-patterns/references/api/guards/pass.md +129 -0
  27. package/skills/app-shell-patterns/references/api/guards/redirect-to.md +307 -0
  28. package/skills/app-shell-patterns/references/api/router/use-location.md +240 -0
  29. package/skills/app-shell-patterns/references/api/router/use-navigate.md +138 -0
  30. package/skills/app-shell-patterns/references/api/router/use-params.md +218 -0
  31. package/skills/app-shell-patterns/references/api/use-ai-chat.md +110 -0
  32. package/skills/app-shell-patterns/references/api/use-app-shell-config.md +132 -0
  33. package/skills/app-shell-patterns/references/api/use-app-shell-data.md +150 -0
  34. package/skills/app-shell-patterns/references/api/use-app-shell.md +150 -0
  35. package/skills/app-shell-patterns/references/api/use-auth.md +145 -0
  36. package/skills/app-shell-patterns/references/api/use-override-breadcrumb.md +74 -0
  37. package/skills/app-shell-patterns/references/api/use-page-meta.md +96 -0
  38. package/skills/app-shell-patterns/references/api/use-register-command-palette-actions.md +90 -0
  39. package/skills/app-shell-patterns/references/api/use-resolved-locale.md +67 -0
  40. package/skills/app-shell-patterns/references/api/use-route-error.md +214 -0
  41. package/skills/app-shell-patterns/references/api/use-theme.md +108 -0
  42. package/skills/app-shell-patterns/references/api/use-time-zone.md +80 -0
  43. package/skills/app-shell-patterns/references/api/use-toast.md +104 -0
  44. package/skills/app-shell-patterns/references/components/action-panel.md +168 -0
  45. package/skills/app-shell-patterns/references/components/activity-card.md +142 -0
  46. package/skills/app-shell-patterns/references/components/ai-chat.md +315 -0
  47. package/skills/app-shell-patterns/references/components/alert.md +202 -0
  48. package/skills/app-shell-patterns/references/components/app-shell.md +530 -0
  49. package/skills/app-shell-patterns/references/components/appearance-switcher.md +87 -0
  50. package/skills/app-shell-patterns/references/components/attachment.md +138 -0
  51. package/skills/app-shell-patterns/references/components/autocomplete.md +278 -0
  52. package/skills/app-shell-patterns/references/components/avatar.md +80 -0
  53. package/skills/app-shell-patterns/references/components/badge.md +309 -0
  54. package/skills/app-shell-patterns/references/components/button.md +164 -0
  55. package/skills/app-shell-patterns/references/components/card.md +181 -0
  56. package/skills/app-shell-patterns/references/components/checkbox.md +169 -0
  57. package/skills/app-shell-patterns/references/components/combobox.md +318 -0
  58. package/skills/app-shell-patterns/references/components/command-palette.md +413 -0
  59. package/skills/app-shell-patterns/references/components/csv-importer.md +214 -0
  60. package/skills/app-shell-patterns/references/components/data-table.md +1168 -0
  61. package/skills/app-shell-patterns/references/components/date-picker.md +259 -0
  62. package/skills/app-shell-patterns/references/components/default-header.md +75 -0
  63. package/skills/app-shell-patterns/references/components/default-sidebar.md +136 -0
  64. package/skills/app-shell-patterns/references/components/description-card.md +569 -0
  65. package/skills/app-shell-patterns/references/components/dialog.md +164 -0
  66. package/skills/app-shell-patterns/references/components/document-progress-card.md +154 -0
  67. package/skills/app-shell-patterns/references/components/filter-rail.md +165 -0
  68. package/skills/app-shell-patterns/references/components/form.md +378 -0
  69. package/skills/app-shell-patterns/references/components/global-header-layout.md +132 -0
  70. package/skills/app-shell-patterns/references/components/grid.md +184 -0
  71. package/skills/app-shell-patterns/references/components/input.md +83 -0
  72. package/skills/app-shell-patterns/references/components/layout.md +539 -0
  73. package/skills/app-shell-patterns/references/components/menu.md +218 -0
  74. package/skills/app-shell-patterns/references/components/metric-card.md +94 -0
  75. package/skills/app-shell-patterns/references/components/select.md +283 -0
  76. package/skills/app-shell-patterns/references/components/sheet.md +237 -0
  77. package/skills/app-shell-patterns/references/components/sidebar-group.md +472 -0
  78. package/skills/app-shell-patterns/references/components/sidebar-item.md +458 -0
  79. package/skills/app-shell-patterns/references/components/sidebar-layout.md +258 -0
  80. package/skills/app-shell-patterns/references/components/sidebar-section.md +114 -0
  81. package/skills/app-shell-patterns/references/components/spinner.md +81 -0
  82. package/skills/app-shell-patterns/references/components/table.md +188 -0
  83. package/skills/app-shell-patterns/references/components/tabs.md +158 -0
  84. package/skills/app-shell-patterns/references/components/textarea.md +122 -0
  85. package/skills/app-shell-patterns/references/components/timeline.md +317 -0
  86. package/skills/app-shell-patterns/references/components/toolbar.md +138 -0
  87. package/skills/app-shell-patterns/references/components/tooltip.md +144 -0
  88. package/skills/app-shell-patterns/references/components/with-guard.md +445 -0
  89. package/skills/app-shell-patterns/references/concepts/authentication.md +301 -0
  90. package/skills/app-shell-patterns/references/concepts/custom-components.md +59 -0
  91. package/skills/app-shell-patterns/references/concepts/file-based-routing.md +356 -0
  92. package/skills/app-shell-patterns/references/{fundamental → concepts}/graphql.md +31 -18
  93. package/skills/app-shell-patterns/references/concepts/modules-and-resources.md +229 -0
  94. package/skills/app-shell-patterns/references/concepts/routing-navigation.md +425 -0
  95. package/skills/app-shell-patterns/references/concepts/sidebar-navigation.md +420 -0
  96. package/skills/app-shell-patterns/references/concepts/styling-theming.md +785 -0
  97. package/skills/app-shell-patterns/references/migrations.md +55 -0
  98. package/skills/app-shell-patterns/references/pages/{detail.md → document-detail.md} +10 -33
  99. package/skills/app-shell-patterns/references/patterns/form-composer.md +43 -45
  100. package/skills/app-shell-patterns/references/patterns/form-modal.md +37 -92
  101. package/skills/app-shell-patterns/references/patterns/form-sectioned.md +12 -38
  102. package/skills/app-shell-patterns/references/patterns/form-single-page.md +11 -32
  103. package/skills/app-shell-patterns/references/patterns/form-wizard.md +12 -53
  104. package/skills/app-shell-patterns/references/patterns/interaction-confirm.md +11 -27
  105. package/skills/app-shell-patterns/references/patterns/interaction-multi-select.md +136 -139
  106. package/skills/app-shell-patterns/references/patterns/interaction-toast.md +10 -34
  107. package/skills/app-shell-patterns/references/patterns/list-dense-scan.md +13 -88
  108. package/skills/app-shell-patterns/references/fundamental/components.md +0 -1009
  109. package/skills/app-shell-patterns/references/fundamental/design-system.md +0 -440
@@ -0,0 +1,420 @@
1
+ ---
2
+ title: Sidebar Navigation
3
+ description: Learn how to customize sidebar navigation with auto-generation or composition mode
4
+ ---
5
+
6
+ <!-- GENERATED by docs-kit from docs-src/concepts/sidebar-navigation.docs.outline.md — do not edit by hand. -->
7
+
8
+ # Sidebar Navigation
9
+
10
+ AppShell provides flexible sidebar navigation with two modes:
11
+
12
+ - **Auto-generation mode**: Automatically generates navigation from module/resource definitions
13
+ - **Composition mode**: Full control over sidebar structure using declarative components
14
+
15
+ ## Quick Start
16
+
17
+ ### Auto-generation Mode (Default)
18
+
19
+ The simplest way to use the sidebar - navigation items are automatically generated from your module definitions:
20
+
21
+ ```tsx
22
+ import { AppShell, SidebarLayout } from "@tailor-platform/app-shell";
23
+
24
+ const App = () => (
25
+ <AppShell modules={modules}>
26
+ <SidebarLayout />
27
+ </AppShell>
28
+ );
29
+ ```
30
+
31
+ ### Composition Mode
32
+
33
+ For full control over sidebar structure, pass children to `DefaultSidebar` via the `sidebar` prop:
34
+
35
+ ```tsx
36
+ import {
37
+ AppShell,
38
+ SidebarLayout,
39
+ DefaultSidebar,
40
+ SidebarItem,
41
+ SidebarGroup,
42
+ SidebarSeparator,
43
+ } from "@tailor-platform/app-shell";
44
+ import { Package, Settings } from "lucide-react";
45
+
46
+ const App = () => (
47
+ <AppShell modules={modules}>
48
+ <SidebarLayout
49
+ sidebar={
50
+ <DefaultSidebar>
51
+ <SidebarItem to="/dashboard" />
52
+ <SidebarSeparator />
53
+ <SidebarGroup title="Products" icon={<Package />}>
54
+ <SidebarItem to="/products/all" />
55
+ <SidebarItem to="/products/categories" />
56
+ </SidebarGroup>
57
+ <SidebarItem to="/settings" icon={<Settings />} />
58
+ </DefaultSidebar>
59
+ }
60
+ />
61
+ </AppShell>
62
+ );
63
+ ```
64
+
65
+ ---
66
+
67
+ ## Components
68
+
69
+ ### SidebarItem
70
+
71
+ A navigation item that automatically resolves title and icon from resource definitions.
72
+
73
+ #### Props
74
+
75
+ | Prop | Type | Required | Description |
76
+ | ---------- | ----------------- | -------- | ------------------------------------------------------------------------------- |
77
+ | `to` | `string` | Yes | Target URL. External URLs (http://...) are rendered as external links |
78
+ | `title` | `LocalizedString` | No | Override title (i18n supported). When omitted, auto-resolved from resource meta |
79
+ | `icon` | `ReactNode` | No | Override icon. When omitted, auto-resolved from resource meta |
80
+ | `external` | `boolean` | No | Opens link in new tab with external link icon |
81
+ | `render` | `function` | No | Custom render function for full UI control |
82
+
83
+ #### Examples
84
+
85
+ ```tsx
86
+ // Auto-resolved from resource meta
87
+ <SidebarItem to="/dashboard" />
88
+
89
+ // Override title and icon
90
+ <SidebarItem to="/" title="Home" icon={<Home />} />
91
+
92
+ // External link
93
+ <SidebarItem to="https://docs.example.com" external />
94
+
95
+ // Custom rendering with render prop
96
+ <SidebarItem
97
+ to="/tasks"
98
+ render={({ title, icon, isActive }) => (
99
+ <div className={isActive ? "font-bold" : ""}>
100
+ {icon}
101
+ <span>{title}</span>
102
+ <Badge>5</Badge>
103
+ </div>
104
+ )}
105
+ />
106
+ ```
107
+
108
+ #### Render Prop
109
+
110
+ When using the `render` prop, you receive `SidebarItemRenderProps`:
111
+
112
+ | Property | Type | Description |
113
+ | ---------- | ------------------------ | ----------------------------------------------- |
114
+ | `title` | `string` | Resolved title (from override or resource meta) |
115
+ | `url` | `string` | Target URL |
116
+ | `icon` | `ReactNode \| undefined` | Resolved icon |
117
+ | `isActive` | `boolean` | Whether this item is currently active |
118
+
119
+ ---
120
+
121
+ ### SidebarGroup
122
+
123
+ A collapsible group for organizing navigation items.
124
+
125
+ #### Props
126
+
127
+ | Prop | Type | Required | Description |
128
+ | ------------- | ----------------- | -------- | ---------------------------------------------- |
129
+ | `title` | `LocalizedString` | Yes | Group title (supports i18n) |
130
+ | `icon` | `ReactNode` | No | Group icon |
131
+ | `to` | `string` | No | When specified, title becomes a clickable link |
132
+ | `defaultOpen` | `boolean` | No | Initial expanded state. Default: `true` |
133
+ | `children` | `ReactNode` | Yes | Child items (SidebarItem, SidebarGroup, etc.) |
134
+
135
+ #### Examples
136
+
137
+ ```tsx
138
+ // Basic group
139
+ <SidebarGroup title="Products" icon={<Package />}>
140
+ <SidebarItem to="/products/all" />
141
+ <SidebarItem to="/products/categories" />
142
+ </SidebarGroup>
143
+
144
+ // Clickable group header
145
+ <SidebarGroup title="Settings" icon={<Settings />} to="/settings">
146
+ <SidebarItem to="/settings/profile" />
147
+ <SidebarItem to="/settings/security" />
148
+ </SidebarGroup>
149
+
150
+ // Initially collapsed
151
+ <SidebarGroup title="Archives" defaultOpen={false}>
152
+ <SidebarItem to="/archives/2024" />
153
+ <SidebarItem to="/archives/2023" />
154
+ </SidebarGroup>
155
+
156
+ // Nested groups
157
+ <SidebarGroup title="Products" icon={<Package />}>
158
+ <SidebarItem to="/products/all" />
159
+ <SidebarGroup title="Archives" defaultOpen={false}>
160
+ <SidebarItem to="/products/archives/2024" />
161
+ <SidebarItem to="/products/archives/2023" />
162
+ </SidebarGroup>
163
+ </SidebarGroup>
164
+ ```
165
+
166
+ #### i18n Support
167
+
168
+ Group titles support localized strings:
169
+
170
+ ```tsx
171
+ import { defineI18nLabels } from "@tailor-platform/app-shell";
172
+
173
+ const labels = defineI18nLabels({
174
+ en: { products: "Products" },
175
+ ja: { products: "製品" },
176
+ });
177
+
178
+ <SidebarGroup title={labels.t("products")} icon={<Package />}>
179
+ <SidebarItem to="/products/all" />
180
+ </SidebarGroup>;
181
+ ```
182
+
183
+ ---
184
+
185
+ ### SidebarSection
186
+
187
+ A static heading for a run of flat navigation items. Unlike `SidebarGroup`, a section is neither collapsible nor navigable, and its items keep top-level styling. In the icon rail the heading is hidden.
188
+
189
+ #### Props
190
+
191
+ | Prop | Type | Required | Description |
192
+ | ---------- | ----------------- | -------- | --------------------------------- |
193
+ | `title` | `LocalizedString` | Yes | Section heading (supports i18n) |
194
+ | `children` | `ReactNode` | Yes | Child items (usually SidebarItem) |
195
+
196
+ #### Example
197
+
198
+ ```tsx
199
+ <DefaultSidebar>
200
+ <SidebarItem to="/overview" />
201
+ <SidebarSeparator />
202
+ <SidebarSection title="Services">
203
+ <SidebarItem to="/ai-gateways" />
204
+ <SidebarItem to="/applications" />
205
+ </SidebarSection>
206
+ <SidebarSeparator />
207
+ <SidebarSection title="Logs">
208
+ <SidebarItem to="/activity-logs" />
209
+ </SidebarSection>
210
+ </DefaultSidebar>
211
+ ```
212
+
213
+ Use `SidebarGroup` when users should be able to collapse the items or when they belong under a parent page; use `SidebarSection` when you only need a label above items that stay visible.
214
+
215
+ ---
216
+
217
+ ### SidebarSeparator
218
+
219
+ A visual divider between sidebar sections.
220
+
221
+ #### Props
222
+
223
+ This component takes no props.
224
+
225
+ #### Example
226
+
227
+ ```tsx
228
+ <DefaultSidebar>
229
+ <SidebarItem to="/dashboard" />
230
+ <SidebarSeparator />
231
+ <SidebarItem to="/settings" />
232
+ </DefaultSidebar>
233
+ ```
234
+
235
+ ---
236
+
237
+ ### DefaultSidebar
238
+
239
+ The main sidebar container that supports both auto-generation and composition modes.
240
+
241
+ #### Props
242
+
243
+ | Prop | Type | Required | Description |
244
+ | ---------- | ----------- | -------- | --------------------------------------- |
245
+ | `header` | `ReactNode` | No | Custom header content |
246
+ | `footer` | `ReactNode` | No | Custom footer content |
247
+ | `children` | `ReactNode` | No | When provided, enables composition mode |
248
+
249
+ #### Examples
250
+
251
+ ```tsx
252
+ // Auto-generation mode
253
+ <DefaultSidebar />
254
+
255
+ // With custom header and footer
256
+ <DefaultSidebar
257
+ header={<Logo />}
258
+ footer={<UserMenu />}
259
+ />
260
+
261
+ // Composition mode with custom navigation
262
+ <DefaultSidebar header={<Logo />}>
263
+ <SidebarItem to="/dashboard" />
264
+ <SidebarGroup title="Products">
265
+ <SidebarItem to="/products/all" />
266
+ </SidebarGroup>
267
+ </DefaultSidebar>
268
+ ```
269
+
270
+ ---
271
+
272
+ ## Hooks
273
+
274
+ ### usePageMeta
275
+
276
+ A hook to retrieve page metadata (title, icon) for a given URL path.
277
+
278
+ #### Signature
279
+
280
+ ```typescript
281
+ const usePageMeta: (path: string) => PageMeta | null;
282
+
283
+ type PageMeta = {
284
+ title: string;
285
+ icon?: ReactNode;
286
+ };
287
+ ```
288
+
289
+ #### Parameters
290
+
291
+ | Parameter | Type | Description |
292
+ | --------- | -------- | ------------------------------------------------- |
293
+ | `path` | `string` | URL path to find meta for (e.g., "/products/all") |
294
+
295
+ #### Returns
296
+
297
+ - `PageMeta` - Object containing `title` and optional `icon` if found
298
+ - `null` - For external links or when path is not found
299
+
300
+ #### Example
301
+
302
+ ```tsx
303
+ import { usePageMeta } from "@tailor-platform/app-shell";
304
+
305
+ const MyComponent = () => {
306
+ const pageMeta = usePageMeta("/products/all");
307
+
308
+ if (!pageMeta) {
309
+ return <span>Unknown Page</span>;
310
+ }
311
+
312
+ return (
313
+ <div>
314
+ {pageMeta.icon}
315
+ <span>{pageMeta.title}</span>
316
+ </div>
317
+ );
318
+ };
319
+ ```
320
+
321
+ ---
322
+
323
+ ## Access Control
324
+
325
+ ### Auto-generation Mode
326
+
327
+ In auto-generation mode, `guards` defined in `defineModule`/`defineResource` are automatically evaluated. Modules/resources that return `hidden()` will not appear in the sidebar.
328
+
329
+ ```tsx
330
+ import { defineModule, defineResource, pass, hidden } from "@tailor-platform/app-shell";
331
+
332
+ const adminModule = defineModule({
333
+ path: "admin",
334
+ meta: { title: "Admin" },
335
+ // If this guard returns hidden(), the module won't appear in sidebar
336
+ guards: [({ context }) => (context.currentUser.role === "admin" ? pass() : hidden())],
337
+ resources: [
338
+ defineResource({
339
+ path: "users",
340
+ meta: { title: "Users" },
341
+ component: () => <div>Users</div>,
342
+ }),
343
+ ],
344
+ });
345
+
346
+ // Used with auto-generation mode
347
+ <DefaultSidebar />;
348
+ ```
349
+
350
+ ### Composition Mode
351
+
352
+ In composition mode, use the `WithGuard` component to control visibility of sidebar items. This allows you to reuse the same guard logic used in route definitions.
353
+
354
+ ```tsx
355
+ import { WithGuard, pass, hidden } from "@tailor-platform/app-shell";
356
+
357
+ // Define a guard function
358
+ const isAdminGuard = ({ context }) => (context.currentUser.role === "admin" ? pass() : hidden());
359
+
360
+ <DefaultSidebar>
361
+ <SidebarItem to="/dashboard" />
362
+
363
+ {/* Wrap items with WithGuard for conditional visibility */}
364
+ <WithGuard guards={[isAdminGuard]}>
365
+ <SidebarGroup title="Admin" icon={<Shield />}>
366
+ <SidebarItem to="/admin/users" />
367
+ <SidebarItem to="/admin/settings" />
368
+ </SidebarGroup>
369
+ </WithGuard>
370
+ </DefaultSidebar>;
371
+ ```
372
+
373
+ #### Curried Guards
374
+
375
+ For parameterized guards, use the curried pattern:
376
+
377
+ ```tsx
378
+ // Define a curried guard factory
379
+ const hasRole =
380
+ (role: string) =>
381
+ ({ context }) =>
382
+ context.currentUser.role === role ? pass() : hidden();
383
+
384
+ <DefaultSidebar>
385
+ <WithGuard guards={[hasRole("admin")]}>
386
+ <SidebarItem to="/admin" />
387
+ </WithGuard>
388
+
389
+ <WithGuard guards={[hasRole("manager")]}>
390
+ <SidebarItem to="/reports" />
391
+ </WithGuard>
392
+ </DefaultSidebar>;
393
+ ```
394
+
395
+ > **Note**: Route-level access control (e.g., redirects) still works via `guards` in `defineResource`, even in composition mode. `WithGuard` only controls visibility—it does not prevent navigation to protected routes.
396
+
397
+ ---
398
+
399
+ ## Migration from Auto-generation
400
+
401
+ If you're currently using auto-generated navigation and want to customize it:
402
+
403
+ 1. **Keep auto-generation for most items**, add custom items where needed:
404
+
405
+ ```tsx
406
+ // Before: Pure auto-generation
407
+ <DefaultSidebar />
408
+
409
+ // After: Composition with similar structure
410
+ <DefaultSidebar>
411
+ <SidebarItem to="/dashboard" />
412
+ <SidebarItem to="/products" />
413
+ <SidebarSeparator />
414
+ <SidebarItem to="https://docs.example.com" title="Documentation" external />
415
+ </DefaultSidebar>
416
+ ```
417
+
418
+ 2. **Title and icon are auto-resolved** from your resource definitions, so you don't need to specify them unless you want to override.
419
+
420
+ 3. **External links** can now be added directly in the sidebar.