Skip to content

Wizard / process steps

In review
Live · web

Create session · Basics

  1. 1Basics
  2. 2Model
  3. 3Review

Basics

Name the session and choose its harness. The harness is immutable after creation.

Shown on the session chip and in the switcher.

Harness

On step 1 of 3 (Basics). The island is live.

// Web: React, consuming @dizyx/nockerl-tokens. (Web is the laggard platform. Spec + live demo,
// not yet exported from @dizyx/nockerl-react; promotion is tracked.)
// The Wizard is the FLOW: it renders a NockerlStepper indicator + the active step's
// content + the Back/Next/Finish footer, and gates advance on each step's
// `isValid`. The shipped "Create session" flow (SessionCreationForm) is the
// content this models.
export function CreateSessionWizard({ onFinish }: { onFinish: (v: SessionValues) => void }) {
return (
<Wizard
label="Create session"
onFinish={onFinish} // fired from the last step's Finish
steps={[
{
label: 'Basics',
isValid: (v) => v.name.trim().length > 0, // gates Next
render: (v, set) => (
<>
<NockerlTextField label="Session name" required value={v.name} onChange={(name) => set({ name })} />
<NockerlRadioGroup label="Harness" value={v.engine} onChange={(engine) => set({ engine })}
options={[{ value: 'cloud-agent', label: 'Cloud Agent' }, { value: 'api-server', label: 'Local Engine' }]} />
</>
),
},
{
label: 'Model',
isValid: (v) => v.provider.length > 0,
render: (v, set) => (
<>
<NockerlSelect label="Provider" value={v.provider} onChange={(provider) => set({ provider })}
placeholder="Select a provider"
options={[{ value: 'cloud-personal', label: 'cloud-personal' }, { value: 'cloud-work', label: 'cloud-work' }]} />
<NockerlSelect label="Model" value={v.model} onChange={(model) => set({ model })}
helperText="Leave as provider default to inherit the registry pick."
options={[{ value: '', label: 'Provider default' }, { value: 'Large 2.0', label: 'Large 2.0' }]} />
</>
),
},
{ label: 'Review', render: (v) => <ReviewSummary values={v} /> }, // final step → Finish
]}
/>
);
}
PropTypeDefaultDescription
steps *WizardStep[]Ordered steps. Each is { label, render, isValid? }. render(values, set) draws the step body; isValid(values) gates Next (omit for an always-passable step like Review).
onFinish *(values: T) => voidFired when Finish is pressed on the last step. Receives the accumulated values.
labelstringAccessible name for the flow region (e.g. 'Create session'); also drives the header eyebrow.
currentnumberControlled active step index. Omit to let the Wizard own its step state internally.
onStepChange(index: number) => voidNotified on every Back / Next / indicator-jump. Pair with current for a controlled flow.
allowJumpBackbooleantrueWhen true, completed discs in the indicator are clickable to jump back. Forward jumps are never allowed (gating).
finishingbooleanfalseHolds the Finish button with a spinner + aria-busy while the create call is in flight.
Cross-platform drift (tracked for reconciliation)

The Wizard is the guided flow, not the indicator:

  • Wizard vs Stepper: the Wizard is the whole flow. It renders the step indicator plus each step’s content plus the Back / Next / Finish footer plus validation gating. The Stepper is only the discs + connectors the Wizard shows at the top; a Wizard uses a Stepper.
  • This page documents an intended API. The canonical “Create session” flow is a single page: web SessionCreationForm and Android SessionCreationSheet (one bottom sheet, not paged), with Voice’s OnboardingView as a status checklist rather than a Back/Next flow. The demo therefore reproduces those real fields (Name → harness → Provider → Model), while the paged container above is designed from the laws + Stepper + Form-layout vocabulary. The note at the foot of this page carries per-platform status.
  • Step content is the Form layout vocabulary (recessed wells, required *, inline errors); the Wizard adds only the orchestration (indicator + navigation + gating + review).