First Use
betaA setup checklist for someone's first visit: steps with their actions, progress dots with a count, and a dismiss button.
Preview
Set up your workspace
2 of 4 done
Add your name and photo (done)
Invite your team (done)
Connect your calendar (not done)
Meetings show up next to your tasks, so you can plan around them.
Create your first project (not done)
A project keeps tasks, files, and people together.
not started, tone brand
Set up your workspace
0 of 4 done
Add your name and photo (not done)
Invite your team (not done)
Connect your calendar (not done)
Meetings show up next to your tasks, so you can plan around them.
Create your first project (not done)
A project keeps tasks, files, and people together.
complete
Set up your workspace
4 of 4 done
You're all set
Your workspace is ready. Dismiss this card when you are done with it.
loading
Set up your workspace
Loading setup steps
not dismissible
Finish your account
1 of 2 done
Invite your team (done)
Connect your calendar (not done)
Meetings show up next to your tasks, so you can plan around them.
narrow container
Set up your workspace
2 of 4 done
Add your name and photo (done)
Invite your team (done)
Connect your calendar (not done)
Meetings show up next to your tasks, so you can plan around them.
Create your first project (not done)
A project keeps tasks, files, and people together.
Install
1. Add the registry to
components.json, once per app. Without it, the shadcn CLI looks up@txbrendanin a public list that txbrendan/ui does not control.npx shadcn@latest registry add "@txbrendan=https://txbrendan.dev/r/{name}.json"2. Add the theme, once per app. It replaces your color tokens with ones checked for contrast.
npx shadcn@latest add @txbrendan/theme3. Add the block. It also adds every component it uses. Its own files go in your
componentsfolder, and they are yours to edit.npx shadcn@latest add @txbrendan/first-use
Use it for
- The top of a new account's home page: three to six steps that get someone to a working setup.
- Mark a step done from real data, like a project that exists, not from a click on its button.
- Give each step one action that takes people straight to it. The checklist shows it until the step is done.
- Save the dismissal in onDismiss, so the card stays hidden on the next visit.
- Set loading while you find out which steps are done, so the card does not flash the wrong ones.
Avoid it for
- A tour of the interface. Put help where people need it, next to the thing it explains.
- A list or page with nothing in it yet. Use Empty State.
- Steps people must finish before they can use the app. Put those in the sign-up flow.
- More than six steps. Cut it down, or split it into stages.
Props
- steps
The checklist, in order. Each id must be unique. The first step that is not done is the current step. Steps can be done in any order. The dots fill in one per done step, from the left, so they show how many are done, not which. Past eight steps, only the count shows.
{ id: string; title: ReactNode; description?: ReactNode; done?: boolean; action?: ReactNode }[]
- title
The card's heading.
ReactNode · default "Set up your workspace"
- description
One line under the title: what finishing the steps gets people.
ReactNode
- headingLevel
The title's heading level, so it fits under the heading above it.
1 | 2 | 3 | 4 | 5 | 6 · default 2
- tone
Color of the done marks, the current step's ring, and the progress dots.
"neutral" | "brand" | "danger" | "success" | "warning" · default "neutral"
- loading
Shows placeholder steps while you find out which are done.
boolean · default false
- loadingText
What the status line tells screen readers while loading.
string · default "Loading setup steps"
- dismissible
Shows the dismiss button.
boolean · default true
- dismissLabel
The dismiss button's name for screen readers.
string · default "Dismiss"
- onDismiss
Called when people dismiss the card, after it hides. Save this, so it stays hidden next time.
() => void
- completeTitle
Shown in place of the steps once every step is done, or when there are no steps.
ReactNode · default "You're all set"
- completeDescription
One line under completeTitle.
ReactNode · default "You finished every step."
- className
Extra classes on the outer section, which holds the container query.
string
| Prop | Type | Default | What it does |
|---|---|---|---|
| steps | { id: string; title: ReactNode; description?: ReactNode; done?: boolean; action?: ReactNode }[] | - | The checklist, in order. Each id must be unique. The first step that is not done is the current step. Steps can be done in any order. The dots fill in one per done step, from the left, so they show how many are done, not which. Past eight steps, only the count shows. |
| title | ReactNode | "Set up your workspace" | The card's heading. |
| description | ReactNode | - | One line under the title: what finishing the steps gets people. |
| headingLevel | 1 | 2 | 3 | 4 | 5 | 6 | 2 | The title's heading level, so it fits under the heading above it. |
| tone | "neutral" | "brand" | "danger" | "success" | "warning" | "neutral" | Color of the done marks, the current step's ring, and the progress dots. |
| loading | boolean | false | Shows placeholder steps while you find out which are done. |
| loadingText | string | "Loading setup steps" | What the status line tells screen readers while loading. |
| dismissible | boolean | true | Shows the dismiss button. |
| dismissLabel | string | "Dismiss" | The dismiss button's name for screen readers. |
| onDismiss | () => void | - | Called when people dismiss the card, after it hides. Save this, so it stays hidden next time. |
| completeTitle | ReactNode | "You're all set" | Shown in place of the steps once every step is done, or when there are no steps. |
| completeDescription | ReactNode | "You finished every step." | One line under completeTitle. |
| className | string | - | Extra classes on the outer section, which holds the container query. |
Accessibility
- The card is a section named by its title, which is a real heading, an h2 by default. Set headingLevel to fit your page.
- The steps are an ordered list. The current step has aria-current="step", and every step's text ends with (done) or (not done) for screen readers.
- The check marks and rings are hidden from screen readers, since the text already says each step's state.
- A status line says "2 of 4 done", and loadingText while loading. It stays on the page, so screen readers hear each new count.
- The dots and the count beside them are hidden from screen readers, since the status line says the same count. The dots are not buttons, so nothing focusable is hidden.
- Forced colors mode drops fills. There the dots hide and the count shows alone, done marks keep their circle as a border, and loading shows loadingText as words.
- The dismiss button is named by dismissLabel and described by the title. Dismissing removes the card, so focus falls back to the page. If that matters, move focus in onDismiss.
Examples
A new workspace
<FirstUse
title="Set up your workspace"
description="Four steps, about five minutes."
steps={[
{ id: "profile", title: "Add your name and photo", done: true },
{ id: "team", title: "Invite your team", done: true },
{
id: "calendar",
title: "Connect your calendar",
description: "Meetings show up next to your tasks.",
action: <Button size="sm">Connect</Button>,
},
{
id: "project",
title: "Create your first project",
action: <Button size="sm" emphasis="outline">New project</Button>,
},
]}
onDismiss={() => saveSetting("setupGuideHidden", true)}
/>While you check which steps are done
<FirstUse steps={steps ?? []} loading={steps === undefined} />Keep it until the steps are done
<FirstUse steps={steps} dismissible={false} tone="brand" />