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-checklistAlso 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:
'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
}}
/>
)
}Description
A getting-started checklist that floats at the bottom of an app: a progress ring, one open step at a time with its action, and finished steps gliding down to Done. It minimizes to a pill that keeps the count.
A setup step where each choice shows what it builds: three deployment shapes as cards with a small isometric plan that builds when chosen. A sentence says what the choice means, and Continue saves it.
A setup step for plugging your sources in. An isometric power strip shows each connected source as a plug in its color, the one still backfilling hovering over its socket, and empty sockets for the rest. Each tile shows a source's day as a small histogram with events a day, how far a backfill has come, or the coverage it would add and a Connect button; the foot sums the coverage on a segmented meter beside Skip for now and Continue.
The first source for an empty library, drawn as a floor plan; a data warehouse by default. Choice cards (database, event stream, files here; a photo library or a CRM with your own sources) reshape what is waiting to land, and the primary action connects the chosen source.
Four empty states in one card: no projects yet, no results, no access and offline. Each says what is missing, why, and the one thing to do next, with an isometric scene that assembles as it scrolls into view.
A full page for the moments between real pages: welcome, empty workspace, 404, maintenance, payment done and offline. One composition keeps them looking like a family; the story shows the welcome state.
Code
Checklist, the Checklist story: the files youj add writes.
blocks/app
Reference
Props18 props, 1 types
Props
| Prop | Type | |
|---|---|---|
defaultCompleted | string[]Ids of the steps done when the card opens, uncontrolled. Default: the first step. | – |
completed | string[]Ids of the done steps, controlled. Pair it with | – |
onCompletedChange | (ids: string[]) => voidCalled with the done ids after a step completes. | – |
defaultMinimized | booleanStarts folded into the pill, uncontrolled. default false | false |
minimized | booleanFolded into the pill, controlled. Pair it with | – |
onMinimizedChange | (minimized: boolean) => voidCalled when the card folds or unfolds. | – |
embedded | booleanInside a host app: no faux app, page landmark or h1; the card sits where the host lays it out. Default true; | – |
fill | booleanTake the whole width it's given instead of stopping at its natural width (672px at 100% scale). default false | false |
product | stringThe product its copy names. Prefer default "Fern" | "Fern" |
brand | { name: string; logo?: ReactNode }The product the copy names. Default: Fern. | – |
steps | ChecklistStep[]The steps, in order. Default: the demo's five, from workspace to domain. | – |
onComplete | (step: ChecklistStep) => Promise<unknown> | unknownDoes 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 | () => voidCalled when the finished checklist is dismissed. | – |
headingLevel | 1 | 2 | 3The card title's level. default 2 | 2 |
locale | stringFormats the percentage. Default: the provider's locale. | – |
copy | Partial<ChecklistCopy>Any of the card's strings, to rewrite or translate. | – |
classNames | { list?: string }Classes for its parts: | – |
theme | ThemeInput | – |
ChecklistStep
| Prop | Type | |
|---|---|---|
idRequired | string | – |
titleRequired | string | – |
descriptionRequired | stringA line of why, under the open step's title. | – |
actionRequired | stringThe button that does the step. | – |
icon | ReactNodeSits 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.
regiontitlestepsDoneminimizepillpillCountopenPilldonedoneSrworkingfailedallSetallSetBodydismissshowannounceStepannounceAllpageBuilt from5 components
Built from
Components used
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.