Skip to content
kerfjsGitHub

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/veneer

Usage

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-autofocus or the step's title.

API Reference

PropTypeDefaultDescription
stepsFlowStep[]—An id, a label to announce, and render.
stepstring | State<string>—The current id: a state, or a value.
defaultStepstring—The first step, when you do not own it.
historystring | boolean—Keeps the step in the URL. true uses ?step=.
announcebooleanfalseSays "Step 2 of 4, Shipping" politely.
EventTypeDefaultDescription
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

RelatedTourCheckout