Flow
Runs steps in one place, keeping what was typed and moving focus for you.
SourcePackage @kerf-js/veneer
Preview
tsx
import { state } from '@kerf-js/core'import { Button, Flow, Input, Row, Select, Stack, Text} from '@kerf-js/veneer'export function NewProject() { const step = state('repo') const name = state('storefront') const at = () => WIZARD.indexOf(step.value) const back = () => { if (at() > 0) step.value = WIZARD[at() - 1]! } const steps = [ { id: 'repo', label: 'Repository', render: () => ( <Input label="Project name" data-autofocus value={name.value} onInput={(e) => (name.value = e.currentTarget.value) } /> ), }, { id: 'build', label: 'Build', render: () => ( <Select label="Framework" options={FRAMEWORKS} defaultValue="kerf" /> ), }, { id: 'review', label: 'Review', render: () => ( <Text> Ready to deploy {name.value} to eu-west. </Text> ), }, ] return ( <Stack gap="group"> <Text role="label">Step {at() + 1} of 3</Text> <Flow steps={steps} step={step} /> <Row gap="related" justify="end" > <Button emphasis="ghost" tone="neutral" aria-disabled={at() === 0 ? 'true' : undefined} onClick={back} > Back </Button> <Button onClick={() => (step.value = WIZARD[(at() + 1) % 3]!) } > {at() === 2 ? 'Deploy' : 'Continue'} </Button> </Row> </Stack> )}const FRAMEWORKS = [ { value: 'vite', label: 'Vite' }, { value: 'next', label: 'Next.js' }, { value: 'kerf', label: 'kerf' },]const WIZARD = ['repo', 'build', 'review']Installation
npm install @kerf-js/veneerUsage
tsx
import { Flow } from '@kerf-js/veneer'When to use
Use it for
- A task that takes a few steps on one screen
Reach for something else
- Tabs, when people can go to any part in any order
Accessibility
- The step is announced on arrival, and focus goes to
data-autofocusor the step's title.
API Reference
| Prop | Type | Default | Description |
|---|---|---|---|
steps | FlowStep[] | — | An id, a label to announce, and render. |
step | string | State<string> | — | The current id: a state, or a value. |
defaultStep | string | — | The first step, when you do not own it. |
history | string | boolean | — | Keeps the step in the URL. true uses ?step=. |
announce | boolean | false | Says "Step 2 of 4, Shipping" politely. |
| Event | Type | Default | Description |
|---|---|---|---|
onStepChange | ((id: string) => void) | — | Called on each change. |
Parts
Every element carries a stable name, so you can style it from your own CSS: [data-scope="flow"] [data-part="step"]
step