A checklist docked in the corner of your product for the first minutes after setup: each item opens the part of the app that does it, and ticks when the app says it happened, in any order. Built on Onboarding Checklist and the Onboarding core step engine.
When to use
- After sign-up and setup, inside the product: a handful of first actions (a project, an invite, an integration) people do in the real UI, not in a wizard.
- When the actions happen in different places and in any order, so each must tick where it really happens.
- When progress should survive a reload and the checklist should get out of the way, folded into a ring, until it is done.
When not to use
- Questions to answer before the product is usable: a step-by-step flow on Onboarding Shell, such as Workspace Setup.
- A list on a settings or home page that ticks when its own button is pressed: Onboarding Checklist on its own.
- Pointing at one control at a time: a tour with a spotlight.
Installation
npx shadcn add @eased-pro/first-run-checklistNeeds the @eased-pro registry and your Pro token in components.json. Create a token and copy the setup from your account .
Usage
import { FirstRunChecklist, useFirstRunChecklist } from "@/components/eased/first-run-checklist/first-run-checklist";const ITEMS = [ { id: "project", title: "Create your first project", description: "Projects hold your issues and docs.", action: "New project", minutes: 1 }, { id: "invite", title: "Invite your team", action: "Invite people", minutes: 1 }, { id: "github", title: "Connect GitHub", action: "Connect GitHub", minutes: 2 },] as const;export function GettingStarted() { const router = useRouter(); const checklist = useFirstRunChecklist({ items: ITEMS, persist: { key: `lumen:first-run:${user.id}` }, onComplete: () => api.markSetUp(), }); // Wherever the action really happens: checklist.complete("project") useEvent("project.created", () => checklist.complete("project")); return ( <FirstRunChecklist checklist={checklist} onOpen={(id) => router.push(`/start/${id}`)} next={[{ id: "cycles", label: "Plan your first cycle", onSelect: () => router.push("/cycles") }]} className="fixed bottom-4 end-4" /> );}Share the controller through context or your store, so the page where a project is created can call complete("project").
Examples
Start folded
Show the ring button first, and let people open the list when they want it.
<FirstRunChecklist checklist={checklist} defaultCollapsed className="fixed bottom-4 end-4" />Keep the done state on your server
persist takes any StepsStorage, so progress can follow someone across devices.
useFirstRunChecklist({ items: ITEMS, persist: { key: user.id, storage: { get: (k) => api.getProgress(k), set: (k, v) => api.saveProgress(k, v), remove: (k) => api.clearProgress(k) }, },});API reference
useFirstRunChecklist
| Option | Type | Default | Description |
|---|---|---|---|
items | FirstRunItem[] | { id, title, description?, action?, minutes?, when? }. action is the open item's button; when(data) leaves an item out. | |
persist | StepsPersist | off | Save progress across reloads. The finished state is kept too: clearOnComplete defaults to false here. |
onComplete | () => void | Promise | Runs once every item is done. Record there that this person is set up. |
Returns { flow, done, complete(id), undo(id) }. flow is the useSteps flow underneath: complete is its mark(id, "complete"), and it calls finish() when the last item lands.
FirstRunChecklist
| Prop | Type | Default | Description |
|---|---|---|---|
checklist | FirstRunController | From useFirstRunChecklist. | |
onOpen | (id) => void | An item's action was chosen: open that part of your app. The item ticks when you call complete, not here. | |
next | FirstRunNext[] | [] | { id, label, description?, onSelect? }, shown under "You’re set up". |
title | string | "Get started" | |
doneTitle | string | "You’re set up" | |
collapsed | boolean | Controlled: folded into the ring button. | |
defaultCollapsed | boolean | false | |
onCollapsedChange | (collapsed: boolean) => void | ||
locale | string | For the count. | |
className | string | "" | Position it, e.g. fixed bottom-4 end-4. |
Keyboard
| Key | Action |
|---|---|
Tab | Moves through the hide button, each item's tick and label, and the open item's action. |
Enter / Space | On a label, opens that item; on its action, opens the part of the app; on a tick, marks it done or not. |
Accessibility
- The panel is a labelled region; each item's tick is a checkbox named by its label, so it can be marked done by hand.
- The line under the title ("3 steps left, about 4 min") is a polite live region, so a tick made elsewhere in the app is announced.
- The folded button says how many are done ("Get started, 2 of 5 done") and is
aria-expanded="false"; folding and opening move focus between it and the hide button. - An item's action leaves focus alone, so your
onOpencan move it into the part of the app it opened; the item stays open until you callcomplete.
Motion
The signature is the checklist reacting to the app: when an action happens elsewhere, the matching item's tick draws, its label strikes through left to right, the ring fills on smooth and the count rolls, with the next item unfolding. The panel and the ring button swap from the bottom corner (rise 6px from 0.97 on the enter curve; leave 3px to 0.98 in 100ms), and the folded ring keeps filling. Once everything is done the list folds into its Done pill, the title swaps to "You’re set up" and what's next opens under it on a height spring. Reduced motion: states change at once and the swaps fade.
Notes for AI
Use it inside the product after setup. Call complete(id) where each action really happens (the create handler, the invite response, the OAuth callback), never from onOpen. Give persist a key per person.
Don't rebuild the list, ring or ticks: they are Onboarding Checklist's. Don't put it in a dialog or a page; it is a floating dock, positioned with className.
Related
- Onboarding Checklist: the list, ring and ticks under this dock.
- Workspace Setup: the flow before it.
- Onboarding Shell: the step engine and frame for wizard-style flows.
- Onboarding set: Workspace Setup, Team Invite and this checklist chained into one first run.