SetupWizard
Multi-step first-run wizard with a server-decided completion gate, plus a guided connect step that waits live for an agent to enroll.
Code
import { SetupWizard } from "@fadymondy/nasaq/web";export function Setup({ done, canFinish }: { done: string[]; canFinish: boolean }) { return ( <SetupWizard title="Set up your workspace" completed={done} canFinish={canFinish} gateMessage={canFinish ? undefined : "Connect an agent first."} steps={[ { id: "name", title: "Name", content: <input aria-label="Name" /> }, { id: "agent", title: "Agent", content: <p>Run the command.</p> }, ]} onStepComplete={async (id) => api.saveStep(id)} onFinish={async () => api.finish()} /> );}declare const api: { saveStep(id: string): Promise<void>; finish(): Promise<void> };Onboarding · beta
Live examples and controls: SetupWizard in the lab.
Install
npx shadcn@latest add https://docs.nasaqui.com/r/setup-wizard.jsonOwns the order, gating and completion of a first-run flow. Each step body is your own form. The server decides when
setup may finish: pass canFinish and completed from it. AgentEnrollWait is a ready-made step body for connecting
an agent: it shows the command, then waits live until the agent checks in.
When to use
- First-run setup of a workspace, project or integration.
- Guided connection of a machine or agent.
When not to use
- A single form: use a form.
- Ongoing settings: use a settings page.
Import
import { AgentEnrollWait, SetupWizard } from "@fadymondy/nasaq/web";
// inside this monorepo: "@nasaq/web"Quick start
import { SetupWizard } from "@fadymondy/nasaq/web";
export function Setup({ done, canFinish }: { done: string[]; canFinish: boolean }) {
return (
<SetupWizard
title="Set up your workspace"
completed={done}
canFinish={canFinish}
gateMessage={canFinish ? undefined : "Connect an agent first."}
steps={[
{ id: "name", title: "Name", content: <input aria-label="Name" /> },
{ id: "agent", title: "Agent", content: <p>Run the command.</p> },
]}
onStepComplete={async (id) => api.saveStep(id)}
onFinish={async () => api.finish()}
/>
);
}
declare const api: { saveStep(id: string): Promise<void>; finish(): Promise<void> };Anatomy
SetupWizard data-slot="setup-wizard"
├─ header (title, description)
├─ Stepper rail (md+) | Progress bar (mobile)
├─ current step: title, description, Optional badge, content
├─ error / gate message role="alert"
├─ Back · Skip · Continue | Finish
└─ done screen title, description, doneActionAPI
SetupWizard: div props (except children, title) plus:
| Prop | Type | Default | Description |
|---|---|---|---|
steps | SetupStep[] | required | { id, title, description?, optional?, ready?, content }. |
current / defaultCurrent / onCurrentChange | Zero-based step. | ||
completed | string[] | Step ids the server counts done. Required steps missing here block Finish. | |
onStepComplete | (id) => AuthSubmitResult | Promise | Runs on Continue. { error } keeps the step. | |
canFinish / gateMessage | boolean / string | true | The server verdict, and the reason if false. |
onFinish | () => AuthSubmitResult | Promise | required | |
title, description, doneTitle, doneDescription, doneAction, labels |
AgentEnrollWait: command, status (waiting, connected, timeout, failed), agent
({ name, host, version, system }), elapsed, error, onRetry, hint, labels. Poll on the host and feed it.
Examples
A step that holds Continue until the agent connects
import { AgentEnrollWait, type SetupStep } from "@fadymondy/nasaq/web";
export const step = (status: "waiting" | "connected"): SetupStep => ({
id: "agent",
title: "Connect an agent",
ready: status === "connected",
content: <AgentEnrollWait command="curl -fsSL https://get.example.com | sh" status={status} />,
});Accessibility
- The rail is a list with
aria-current="step". Moving forward or back focuses the new step heading. - Status changes in
AgentEnrollWaitare announced politely; errors userole="alert". - Buttons show a spinner and
aria-busywhile a step saves.
RTL & i18n
- English and Arabic are built in; pass
labelsto override. - Back and Continue arrows mirror; the command is always left to right and copyable.
Styling & tokens
- Built from
Stepper,Progress,Button,Alert,CopyFieldandSpinner; tokens only.
Do / Don't
- Do let the server, not the client, decide when setup is complete.
- Do mark truly optional steps
optional. - Don't hide why Finish is blocked: set
gateMessage. - Don't poll faster than every couple of seconds.
Related
Lab
https://docs.nasaqui.com/?path=/docs/components-onboarding-pages-setup-wizard--docs
OnboardingFlow
The flow after sign-up: welcome, profile, workspace, invites, preferences, first integration and a review, with skip, back and progress that resumes after a reload.
AlertDialog
Modal that interrupts to ask for an explicit answer before a consequential action, plus a ConfirmButton shorthand. Wraps Base UI AlertDialog.