Resolved: light

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

Step 2 of 3
  1. Account
  2. Profile
  3. Review
<WizardPage> — TitleBar + step badge · ProgressSteps rail · current step form · Back / Next footer
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

Review
SubmittedVet checkReviewApproved

Dana Whitfield

Applying to adopt Biscuit

Applicant
Dana Whitfield
Adopting
Biscuit
Home
Fenced yard · Owns home · No other dogs
References
2 of 2 vouched
<ReviewApprovalPage> — queue rail · ApprovalFlow pipeline · application facts · approve / reject decision bar
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

In foster

Intake Mar 2, 2026 · currently in foster with the Rivera family · 4 events

  1. Mar 2, 2026
    Intake

    Surrendered from a research-facility release; logged into the roster as Luna.

  2. Mar 5, 2026
    Vet exam

    Full health check, spay, and first vaccinations cleared. Microchip scanned and registered.

  3. Mar 9, 2026
    Foster placement

    Placed with the Rivera family in Oakland for socialization and decompression.

  4. Expected late June
    Adoption

    Two applications under review; meet-and-greet to be scheduled once cleared.

<TimelinePage> — TitleBar + status badge · intro summary band · framed event Timeline · metadata aside
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

Pending
24
awaiting triage
In review
8
being vetted
Placed today
12+3
vs yesterday
Overdue
3+1
past SLA
RequesterDogRegionSubmittedStatus
Dana WhitfieldBiscuitBay Area2h agoPending
Marcus LeePepperSacramento5h agoIn review
Priya AnandWafflesBay Area1d agoPending
Theo BrandtMochiCentral Valley1d agoOverdue
Lena OrtizScoutSacramento2d agoIn review
Sam OkaforJuniperNorth Coast2d agoPlaced
Hana KimTofuBay Area3d agoPending
Owen ReyesCloverCentral Valley3d agoPending

Showing 1–8 of 24

<QueuePage> — StatGrid scoreboard · filter toolbar · selectable queue table · selection-driven BottomBar bulk bar
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

4 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

Resolution for Phone

ZIP

NVDA form

94601

WhatsApp sheet

94610

Resolution for ZIP

Team

NVDA form

Bay Area

WhatsApp sheet

East Bay

Resolution for Team
ConflictResolutionPage — TitleBar · conflict list | resolution pane · apply footer
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

+12 / −5

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 team

v4 is live · edited by you on Jun 27, 2026.

<DiffPage> — TitleBar · unified-diff canvas (added green · removed red · context muted) + revision picker / change-summary aside · Restore footer. The real diff renderer lives in the `viewer` slot (static stand-in here).
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.

tsx
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>