Workflow
Multi-step + decision flows: WizardPage (stepped form), ReviewApprovalPage (queue → approval pipeline), TimelinePage (event rail), QueuePage (work queue with a scoreboard), ConflictResolutionPage (theirs/yours merge) and DiffPage (side-by-side diff). ActivityFeedPage is a configured preset of TimelinePage.
Each owns its flow chrome (step rail, approval pipeline, decision bar) and takes ReactNode slots; the interactive parts (selection, decision handlers, bulk-action bars) ride caller-passed client islands.
WizardPage
A stepped flow page: a ProgressSteps rail over the current step's body, with an optional context aside.
Onboard a rescuer
- Account
- Profile
- Review
- steps (required)
- The step-rail model (numbered circles + connectors), forwarded to <ProgressSteps>.
- stepsOrientation / children
- stepsOrientation 'horizontal' (default) | 'vertical'; children is the current step's body (→ RecordPage main).
- aside / asideWidth
- Optional context rail (help / summary) → RecordPage aside (default 340px); the body splits when set. Server-safe.
ReviewApprovalPage
A review console: a pending-item queue rail beside the selected item's detail, with an approval pipeline rendered atop it.
Adoption applications
Dana Whitfield
Applying to adopt Biscuit
- Applicant
- Dana Whitfield
- Adopting
- Biscuit
- Home
- Fenced yard · Owns home · No other dogs
- References
- 2 of 2 vouched
- queue (required) / detail (required)
- queue is the review-queue rail (→ ListDetailLayout list); detail is the selected item's body.
- flow
- The approval pipeline (ReviewApprovalStep[] with state done/current/rejected/pending) → an <ApprovalFlow> rendered atop the detail pane.
- server-safe
- The shell renders server-side; the queue selection + decision controls are caller-passed client islands.
TimelinePage
A chronological page: the surface <Timeline> rail with an optional intro band and metadata aside, over the RecordPage.
Luna — case timeline
Intake Mar 2, 2026 · currently in foster with the Rivera family · 4 events
- Mar 2, 2026Intake
Surrendered from a research-facility release; logged into the roster as Luna.
- Mar 5, 2026Vet exam
Full health check, spay, and first vaccinations cleared. Microchip scanned and registered.
- Mar 9, 2026Foster placement
Placed with the Rivera family in Oakland for socialization and decompression.
- Expected late JuneAdoption
Two applications under review; meet-and-greet to be scheduled once cleared.
- items (required)
- The event entries — the surface <Timeline> model (TimelineEntry[]).
- framed / intro / aside
- framed wraps each entry in a flat Surface card; intro renders above the timeline (summary / filters); aside is a metadata rail (default 340px).
- server-safe
- TimelineEntry.icon is a rendered element (not a component reference), so the whole page renders server-side.
QueuePage
A work-queue page: a StatGrid scoreboard band over a filterable queue table, closed by pagination and an on-selection bulk-action bar.
Foster requests
| Requester | Dog | Region | Submitted | Status | |
|---|---|---|---|---|---|
| Dana Whitfield | Biscuit | Bay Area | 2h ago | Pending | |
| Marcus Lee | Pepper | Sacramento | 5h ago | In review | |
| Priya Anand | Waffles | Bay Area | 1d ago | Pending | |
| Theo Brandt | Mochi | Central Valley | 1d ago | Overdue | |
| Lena Ortiz | Scout | Sacramento | 2d ago | In review | |
| Sam Okafor | Juniper | North Coast | 2d ago | Placed | |
| Hana Kim | Tofu | Bay Area | 3d ago | Pending | |
| Owen Reyes | Clover | Central Valley | 3d ago | Pending |
Showing 1–8 of 24
- table (required)
- The queue table / grid → ResourceIndexPage table.
- stats / toolbar / facets
- stats are StatTile children wrapped in a StatGrid scoreboard band under the header; toolbar is the search / filter / selection band; facets is an optional rail (default 240px).
- footer
- Pagination / row counts. The selection bulk-action bar is a surface <BottomBar> client island.
ConflictResolutionPage
A merge console: a conflict-list rail beside a field-by-field theirs/yours resolution pane, closed by an apply/skip footer.
Resolve sync conflicts
Maria Rivera
3 fields differ between the NVDA form and the WhatsApp sheet.
Phone
NVDA form
(510) 555-0182
WhatsApp sheet
(510) 555-9921
ZIP
NVDA form
94601
WhatsApp sheet
94610
Team
NVDA form
Bay Area
WhatsApp sheet
East Bay
- list / detail
- list is the conflict-list rail (unresolved records); detail is the resolution pane (field-by-field theirs/yours, keep/merge controls). Omit either → STUB placeholder.
- listWidth / listEnd / fullHeight
- Rail width (default 360px), listEnd moves it trailing, fullHeight fills the viewport below the admin nav (inbox-style).
- footer
- 'Apply resolutions' / skip-all. Server-safe shell.
DiffPage
A revision-compare page: a side-by-side / unified diff canvas with a change-summary aside and restore/approve actions, over the DocumentLayout.
Welcome email — v3 → v4
templates/welcome-email.txt · unified · v3 → v4
Hi {{first_name}}, - Thanks for signing up to help dogs.+ Welcome to Save the Dogs — you're officially a rescuer. + Your nearest team is already active in your area.+ We'll match you to a foster within 48 hours. Click below to finish setting up your portal: - [ Log in ]+ [ Activate my portal ] — The Save the Dogs teamv4 is live · edited by you on Jun 27, 2026.
- viewer
- The diff canvas — side-by-side / unified (caller-passed; any diff renderer lives HERE). → DocumentLayout viewer. Omit → STUB placeholder.
- aside / asideWidth
- Change-summary / revision rail (version picker, +added/-removed counts); default 320px.
- footer
- 'Restore' / 'Approve change' actions. Server-safe shell.
ActivityFeedPage
This is TimelinePage configured as an activity stream — the same vertical rail, but entries read 'actor + action + relative time' instead of project milestones.
import { TimelinePage } from "@/components/ds/recipes";
import { UserPlus, RefreshCw } from "lucide-react";
<TimelinePage
title="Activity"
items={[
{ id: "1", when: "2m ago", title: "Jordan added a foster", state: "current", icon: <UserPlus className="size-4" /> },
{ id: "2", when: "1h ago", title: "Sync imported 12 rescuers", icon: <RefreshCw className="size-4" /> },
]}
/>
// free-body variant:
<TimelinePage title="Activity"><Feed compact items={activity} /></TimelinePage>