Skip to content

Commit a0d63eb

Browse files
Update App Shell pages (#68)
Co-authored-by: anukiransolur <3693214+anukiransolur@users.noreply.github.com>
1 parent 1d93eb7 commit a0d63eb

5 files changed

Lines changed: 156 additions & 10 deletions

File tree

Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
---
2+
title: useOverrideBreadcrumb
3+
description: Hook for dynamically overriding breadcrumb titles from within page components
4+
---
5+
6+
# useOverrideBreadcrumb
7+
8+
React hook to dynamically override the breadcrumb title for the current page. Useful for displaying data-driven titles (e.g., record names fetched from an API) instead of static route-based titles.
9+
10+
## Signature
11+
12+
```typescript
13+
function useOverrideBreadcrumb(title: string | undefined): void;
14+
```
15+
16+
## Parameters
17+
18+
### `title`
19+
20+
- **Type:** `string | undefined`
21+
- **Required:** Yes
22+
- **Description:** The title to display in the breadcrumb for the current path. When `undefined`, any previous override is removed and the default title (from `defineResource`) is restored.
23+
24+
## Usage
25+
26+
### With `defineResource`
27+
28+
```tsx
29+
import { useOverrideBreadcrumb } from "@tailor-platform/app-shell";
30+
31+
defineResource({
32+
path: ":id",
33+
component: () => {
34+
const { id } = useParams();
35+
const { data } = useQuery(GET_ORDER, { variables: { id } });
36+
37+
// Update breadcrumb with the order name
38+
useOverrideBreadcrumb(data?.order?.name);
39+
40+
return <OrderDetail />;
41+
},
42+
});
43+
```
44+
45+
### With file-based routing
46+
47+
```tsx
48+
import { useOverrideBreadcrumb, useParams } from "@tailor-platform/app-shell";
49+
50+
const OrderDetailPage = () => {
51+
const { id } = useParams();
52+
const { data } = useQuery(GET_ORDER, { variables: { id } });
53+
54+
// Update breadcrumb with the order name
55+
useOverrideBreadcrumb(data?.order?.name);
56+
57+
return <div>...</div>;
58+
};
59+
60+
export default OrderDetailPage;
61+
```
62+
63+
## Notes
64+
65+
- The hook updates reactively — pass the result of a data-fetching query directly and the breadcrumb updates when the data resolves.
66+
- When `title` is `undefined` (e.g., while data is loading), the override is cleared and the default title is shown.
67+
- The override is automatically cleaned up when the component unmounts.
68+
69+
## Related
70+
71+
- [defineResource](define-resource) - Define routes and their default breadcrumb titles
72+
- [Routing and Navigation](../concepts/routing-navigation) - Overview of breadcrumb behavior

docs/app-shell/components/autocomplete.md

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -91,13 +91,13 @@ const cities: City[] = [
9191

9292
## Async Suggestions
9393

94-
Use `Autocomplete.Async` to fetch suggestions as the user types. The fetcher is called on each keystroke (debounced).
94+
Use `Autocomplete.Async` to fetch suggestions as the user types. The fetcher is called on each keystroke (debounced). When the dropdown first opens or the input is cleared, the fetcher receives `null` as the query — return initial/default suggestions for `null`, or return an empty array to show nothing until the user starts typing.
9595

9696
```tsx
9797
import { type AutocompleteAsyncFetcher } from "@tailor-platform/app-shell";
9898

9999
const fetcher: AutocompleteAsyncFetcher<string> = async (query, { signal }) => {
100-
const res = await fetch(`/api/suggestions?q=${query}`, { signal });
100+
const res = await fetch(`/api/suggestions?q=${query ?? ""}`, { signal });
101101
return res.json();
102102
};
103103

@@ -121,11 +121,14 @@ Accepts all the same props as `Autocomplete` except `items`, plus:
121121

122122
```ts
123123
type AutocompleteAsyncFetcher<T> =
124-
| ((query: string, options: { signal: AbortSignal }) => Promise<T[]>)
125-
| { fn: (query: string, options: { signal: AbortSignal }) => Promise<T[]>; debounceMs: number };
124+
| ((query: string | null, options: { signal: AbortSignal }) => Promise<T[]>)
125+
| {
126+
fn: (query: string | null, options: { signal: AbortSignal }) => Promise<T[]>;
127+
debounceMs: number;
128+
};
126129
```
127130

128-
Pass `{ fn, debounceMs }` to customize the debounce delay. Errors thrown by the fetcher are silently caught — handle errors inside the fetcher.
131+
`query` is `null` when the user has not typed anything (e.g. the dropdown was just opened or the input was cleared). Pass `{ fn, debounceMs }` to customize the debounce delay. Errors thrown by the fetcher are silently caught — handle errors inside the fetcher.
129132

130133
## Low-level Primitives
131134

docs/app-shell/components/combobox.md

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -117,13 +117,13 @@ const [tags, setTags] = useState<Tag[]>([
117117

118118
## Async Loading
119119

120-
Use `Combobox.Async` to load items from an API. The fetcher is called on each keystroke (debounced).
120+
Use `Combobox.Async` to load items from an API. The fetcher is called on each keystroke (debounced). When the dropdown first opens or the input is cleared, the fetcher receives `null` as the query — return initial/default items for `null`, or return an empty array to show nothing until the user starts typing.
121121

122122
```tsx
123123
import { type ComboboxAsyncFetcher } from "@tailor-platform/app-shell";
124124

125125
const fetcher: ComboboxAsyncFetcher<User> = async (query, { signal }) => {
126-
const res = await fetch(`/api/users?q=${query}`, { signal });
126+
const res = await fetch(`/api/users?q=${query ?? ""}`, { signal });
127127
return res.json();
128128
};
129129

@@ -150,11 +150,14 @@ Accepts all the same props as `Combobox` except `items`, plus:
150150

151151
```ts
152152
type ComboboxAsyncFetcher<T> =
153-
| ((query: string, options: { signal: AbortSignal }) => Promise<T[]>)
154-
| { fn: (query: string, options: { signal: AbortSignal }) => Promise<T[]>; debounceMs: number };
153+
| ((query: string | null, options: { signal: AbortSignal }) => Promise<T[]>)
154+
| {
155+
fn: (query: string | null, options: { signal: AbortSignal }) => Promise<T[]>;
156+
debounceMs: number;
157+
};
155158
```
156159

157-
Pass `{ fn, debounceMs }` to customize the debounce delay. Errors thrown by the fetcher are silently caught — handle errors inside the fetcher.
160+
`query` is `null` when the user has not typed anything (e.g. the dropdown was just opened or the input was cleared). Pass `{ fn, debounceMs }` to customize the debounce delay. Errors thrown by the fetcher are silently caught — handle errors inside the fetcher.
158161

159162
## Low-level Primitives
160163

docs/app-shell/concepts/routing-navigation.md

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,49 @@ const MyComponent = () => {
4949
};
5050
```
5151

52+
## Breadcrumbs
53+
54+
AppShell automatically generates breadcrumbs from your module and resource hierarchy. Each path segment corresponds to a breadcrumb item, using the `title` (or `meta.breadcrumbTitle`) defined in `defineModule` / `defineResource`.
55+
56+
### Static Breadcrumb Titles
57+
58+
Set a fixed breadcrumb title via `meta.breadcrumbTitle`:
59+
60+
```tsx
61+
defineResource({
62+
path: ":id",
63+
meta: {
64+
breadcrumbTitle: (segment) => `Order #${segment}`,
65+
},
66+
component: OrderDetailPage,
67+
});
68+
// Breadcrumb shows: "Orders > Order #12345"
69+
```
70+
71+
### Dynamic Breadcrumb Titles
72+
73+
Use the `useOverrideBreadcrumb` hook to replace a breadcrumb segment with a data-driven value from within the rendered page component:
74+
75+
```tsx
76+
import { useOverrideBreadcrumb } from "@tailor-platform/app-shell";
77+
78+
defineResource({
79+
path: ":id",
80+
component: () => {
81+
const { data } = useQuery(GET_ORDER, { variables: { id } });
82+
83+
// Breadcrumb updates reactively once data loads
84+
useOverrideBreadcrumb(data?.order?.name);
85+
86+
return <OrderDetail />;
87+
},
88+
});
89+
```
90+
91+
While `title` is `undefined` (e.g., loading), the override is cleared and the static title is shown. The override is automatically cleaned up on unmount.
92+
93+
See [useOverrideBreadcrumb](../api/use-override-breadcrumb) for the full API reference.
94+
5295
## Command Palette for Quick Navigation
5396

5497
AppShell includes a `CommandPalette` component that provides keyboard-driven quick navigation to any page in your application.

docs/app-shell/concepts/styling-theming.md

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,3 +35,28 @@ In CSS, the order of style-definition affects the final styles which are compute
3535
To avoid this situation, and to ensure correct style resolution, AppShell components use a class prefix "astw" (AppShell TailWind) to avoid clashes.
3636

3737
This is important to note for developing in AppShell.
38+
39+
## Z-Index Layering
40+
41+
AppShell defines CSS custom properties for z-index values so you can adjust the stacking order to integrate with other libraries or overlays in your application.
42+
43+
These properties are defined in `:root` and can be overridden in your own CSS:
44+
45+
| Property | Default | Used for |
46+
| ------------------ | ------- | ------------------------------------------------------------------- |
47+
| `--z-sidebar` | `10` | The sidebar panel |
48+
| `--z-sidebar-rail` | `20` | The sidebar collapse rail / toggle button |
49+
| `--z-popup` | `50` | Portal-based popups (Menu, Select, Combobox, Autocomplete, Tooltip) |
50+
| `--z-overlay` | `50` | Modal overlays (Dialog, Sheet) |
51+
52+
### Example: Raising popup z-index
53+
54+
```css
55+
/* your-app/globals.css */
56+
@import "@tailor-platform/app-shell/theme.css";
57+
@import "tailwindcss";
58+
59+
:root {
60+
--z-popup: 100;
61+
}
62+
```

0 commit comments

Comments
 (0)