Skip to content

Onboarding & states

Getting started and the in-between pages: checklists, setup choices, first sources, empty and illustrated states.

Installation & usage

npx @youj/cli add app-checklist

Also installs async-button, button, collapse, counter, icon-check, icon-chevron-down, icon-git-branch, icon-globe, icon-minimize, icon-party-popper, icon-rocket, icon-user-plus, icon-wand, icon-x, presence-list, typography, use-announcer, youj-core, youj-presets, youj-ui-core.

The CLI copies the block to blocks/app/checklist.tsx with every component it uses, so it’s yours to edit.

Every prop is optional and falls back to the demo, so it renders as you see it until you pass your own. Give it your data, rewrite or translate its strings through copy, and connect its actions:

checklist-view.tsx
'use client'

import { Checklist, type ChecklistProps } from '@/blocks/app/checklist'

export function ChecklistView({ completed, steps }: Pick<ChecklistProps, 'completed' | 'steps'>) {
  return (
    <Checklist
      completed={completed}
      steps={steps}
      copy={{ region: 'Getting started' }}
      onCompletedChange={(ids) => {
        // your code
      }}
      onMinimizedChange={(minimized) => {
        // your code
      }}
      onComplete={async (step) => {
        // await your API here; the block shows progress until it settles
      }}
    />
  )
}

Reference

Props18 props, 1 types

Props

Checklist props
PropType
defaultCompletedstring[]

Ids of the steps done when the card opens, uncontrolled. Default: the first step.

–
completedstring[]

Ids of the done steps, controlled. Pair it with onCompletedChange.

–
onCompletedChange(ids: string[]) => void

Called with the done ids after a step completes.

–
defaultMinimizedboolean

Starts folded into the pill, uncontrolled.

default false

false
minimizedboolean

Folded into the pill, controlled. Pair it with onMinimizedChange.

–
onMinimizedChange(minimized: boolean) => void

Called when the card folds or unfolds.

–
embeddedboolean

Inside a host app: no faux app, page landmark or h1; the card sits where the host lays it out. Default true; false draws its own page around it (a centered canvas and an h1).

–
fillboolean

Take the whole width it's given instead of stopping at its natural width (672px at 100% scale).

default false

false
productstring

The product its copy names. Prefer brand.

default "Fern"

"Fern"
brand{ name: string; logo?: ReactNode }

The product the copy names. Default: Fern.

–
stepsChecklistStep[]

The steps, in order. Default: the demo's five, from workspace to domain.

–
onComplete(step: ChecklistStep) => Promise<unknown> | unknown

Does a step's work when its action is pressed; resolve to mark it done, throw to show why it failed. Default: a short demo wait.

–
onDismiss() => void

Called when the finished checklist is dismissed.

–
headingLevel1 | 2 | 3

The card title's level.

default 2

2
localestring

Formats the percentage. Default: the provider's locale.

–
copyPartial<ChecklistCopy>

Any of the card's strings, to rewrite or translate.

–
classNames{ list?: string }

Classes for its parts: list is the region the steps scroll in (its height, 306px at 100%, holds the card's size as steps open, close and finish).

–
themeThemeInput–

ChecklistStep

ChecklistStep props
PropType
idRequiredstring–
titleRequiredstring–
descriptionRequiredstring

A line of why, under the open step's title.

–
actionRequiredstring

The button that does the step.

–
iconReactNode

Sits before the action's label.

–
Strings18 keys for copy

Strings

copy takes any of these keys; the rest keep their defaults. A key whose text holds a value (a count, a name) takes a function.

regiontitlestepsDoneminimizepillpillCountopenPilldonedoneSrworkingfailedallSetallSetBodydismissshowannounceStepannounceAllpage
Built from5 components
Accessibilitystatus, pictures, choices, motion

Accessibility

The checklist is a section labelled by its title and each change is announced. Its title heading follows headingLevel.

Setup picker uses a radio group, so the arrow keys move between the cards and the choice is announced. The isometric plans are decorative.

Connect sources keeps its drawing decorative (hidden from assistive tech) and says everything in the tiles: a named list where each tile has its source's name, its state in words ("Connected", a backfill percentage, or the coverage it adds) and a Connect button named for the source. The histograms are decorative too; the line under each says the number. The coverage meter is a meter named Coverage, and connecting announces the result in a polite live region.

Every state has a plain title and sentence, and the illustrated pages are a section or main named by their heading. The isometric scenes are pictures: they are aria-hidden, and the words beside them carry the meaning.

In the gallery the offline state follows the browser's online state and announces changes in a role="status" paragraph. In the first data source block the three choices are a labelled radio group, so the arrow keys move between them and the chosen one is announced; the primary action's label follows the choice.

Under reduced motion the scenes appear finished and still, nothing bobs or drops, and the choice reshapes in place.

Under reduced motion rows, rings and steps change in place, the chosen plan is simply built and the bar jumps to its new split.