Skip to content

Setup assistant

A setup checklist with actions, step progress and expandable substeps.

Sales Setup Assistant

Complete all the steps below to finish setting up Sales Cloud.
  1. Complete

    Add your sales team

    Ellen Hart and Priya Raman can sign in to the Sales app.

    Complete

  2. 2

    Review the source and the mapping before you import accounts.

    1 of 3 substeps complete

    10 mins

    1. Complete

      Review source accounts

      Check Edge Communications and Burlington Textiles for duplicates.

    2. Active

      Confirm the field mapping

      Match Account Name, Billing Address and Account Owner.

    3. Approve a sample import

      Check the sample before the remaining accounts import.

  3. 3

    Turn on Opportunity Teams

    Let reps add the teammates who work each deal with them.

    Not started

  4. 4

    Review lead assignment

    Confirm that new web leads reach the right sales rep.

    Not started

    5 mins

Installation

pnpm dlx shadcn@latest add @wisty/setup-assistant

The CLI installs the Radix or Base UI file to match your project, with what it builds on: alert, button, card, progress-indicator, progress-ring, skeleton, switch.

If your project doesn't have Wisty UI's theme yet, add it once with npx shadcn@latest add @wisty/cosmos. Until then, components keep shadcn's default look. Installation has the details.

When to use

Use it

  • On a Setup or onboarding page that walks an admin through numbered steps, like Lightning's Setup Assistant for Sales Cloud or Service Cloud.
  • When each step shows how far along it is, with a button, a link or a switch that does it.
  • When a step breaks into substeps done in order, shown when the step expands.
  • When a card's header counts how many steps are done.

Don't use it

  • For a record's stage or status. Use Path.
  • For a wizard's position, moved by Back and Next. Use Progress indicator.
  • For one task's percent on its own. Use Progress ring.
  • For substeps that can be done in any order inside one step. Split them into steps.
  • To install or configure features in an org. The block only shows what the app reports.

Usage

import {
  SetupAssistant,
  SetupAssistantList,
  SetupAssistantSummary,
} from "@/components/wisty/setup-assistant"
SetupAssistant
├── SetupAssistantSummary
└── SetupAssistantList
<SetupAssistant steps={steps} aria-label="Sales Setup Assistant">
  <SetupAssistantList />
</SetupAssistant>

SetupAssistantSummary shows how many steps are done, as words and a bar. Put it in your card's header and SetupAssistantList in its body, with SetupAssistant around the card and headingLevel={3} under the card's h2. Leave the summary out for a list inside an existing section.

<SetupAssistant
  steps={steps}
  aria-label="Sales Setup Assistant"
  onAction={(action, target) => openSetupFlow(action.value, target)}
  onToggleChange={(stepId, checked) => saveSetting(stepId, checked)}
>
  <SetupAssistantList />
</SetupAssistant>

A step is a task with a button or link, a setting with a switch, or a sequence of substeps. onAction and onToggleChange only ask for the work. Replace the step's progress, or the switch's checked, in steps once the work succeeds. A link never completes a step. For a sequence, completed counts finished substeps from the first: the next one is current, and later ones wait. value, defaultValue and onValueChange hold which sequences are open, apart from their progress.

Examples

Steps without progress

Untracked steps with no rings, a setup page, a guide and a switch, without a card or summary.

  1. Set up Email-to-Case

    Turn customer emails to your support address into cases.

  2. Learn how agents use Knowledge

    See how articles help agents answer common questions.

  3. Turn on Feed Tracking for cases

    Show changes to a case's status and owner in its feed.

Progress not fully available

Available steps stay visible, unknown progress is named, a setting with no handler reads On as text, and no overall percentage is guessed.

Sales Setup Assistant

Setup progress2 of 4 shown steps complete. Overall progress unavailable.
Some setup steps couldn't be read. Showing the steps that could.
  1. 1

    Add your sales team

    Give each sales rep access to the Sales app.

    Team access couldn't be checked.

  2. 2

    Review the source and the mapping before you import accounts.

    Account preparation progress is unavailable.

    10 mins

    1. Review source accounts

      Review Source
    2. Confirm the field mapping

      Review Mapping
    3. Approve a sample import

      Review Sample
  3. Complete

    Turn on Opportunity Teams

    Let reps add the teammates who work each deal with them.

    Complete

    Turn on Opportunity Teams: On

  4. Complete

    Review lead assignment

    Confirm that new web leads reach the right sales rep.

    Complete

    5 mins

No setup steps

A complete empty checklist says there are no steps to show, without claiming setup is finished.

Sales Setup Assistant

Setup progressNo setup steps to show.

No setup steps to show.

Setup unavailable

An unavailable checklist explains what couldn't be read instead of showing an empty list.

Sales Setup Assistant

Setup progressSetup progress unavailable.

Setup steps couldn't be loaded. Try again in a few minutes.

Loading setup

Placeholder rows hold the list's shape while setup loads, without an invented completion value.

Sales Setup Assistant

Setup progressLoading setup progress…
Loading setup steps

API reference

PartBuilt onDescription
SetupAssistant<section> (opens in a new tab)A setup checklist's data and expanded steps, shared by its summary and list.
SetupAssistantSummary<div> (opens in a new tab)How many steps are done, as words and a bar, or why that isn't known.
SetupAssistantList<div> (opens in a new tab)The numbered steps, with their rings, actions and substeps.

SetupAssistant

A setup checklist's data and expanded steps, shared by its summary and list.

PropTypeDefaultDescription
aria-labelstringNames the checklist, like "Sales Setup Assistant".
aria-labelledbystringThe id of the visible title that names the checklist.
steps*readonly SetupAssistantStep[] | nullThe steps as read, in order. null when they couldn't be read.
partial{ message: string } | neverSet when some steps couldn't be read: the notice above the ones that could.
unavailableMessagenever | stringWhy the steps couldn't be read. Default "Setup steps aren't available."
loadingbooleanfalseMarks the checklist busy: placeholder rows with no steps, or the steps kept while they reload.
valuereadonly string[]The ids of the open sequences, when controlled.
defaultValuereadonly string[]The ids of the sequences open at first.
onValueChange(value: string[]) => voidCalled with the open sequences' ids, in step order.
onAction( action: SetupAssistantButtonAction, target: SetupAssistantActionTarget ) => voidAsks the app to do a button's work. Buttons render only with it.
onToggleChange(stepId: string, checked: boolean) => voidAsks the app to change a setting. Without it, settings show On or Off as text.
headingLevel2 | 3 | 4 | 5 | 62The step titles' heading level. Default 2, 3 under a card's h2 title.

SetupAssistantSummary

How many steps are done, as words and a bar, or why that isn't known.

PropTypeDefaultDescription
labelstring"Setup progress"Names the bar, shown above it.

SetupAssistantButtonActiontype

A button that asks the app to do a step's work, through onAction.

MemberTypeDefaultDescription
type*"button"Draws an outline brand button.
value*stringIdentifies the action in onAction: "confirm-mapping".
label*stringThe button's words: "Confirm mapping".
disabledbooleanShows the button but doesn't let it run.

SetupAssistantLinkActiontype

A link to a setup page, an article or a video. Following it never completes a step.

MemberTypeDefaultDescription
type*"link"Navigates with href, without calling onAction.
value*stringIdentifies the action: "manage-users".
label*stringThe link's words: "View on Trailhead".
href*stringWhere the link goes.
variant"link" | "outline-brand""link" draws text, "outline-brand" a button that opens a setup page. Default "link".
disabledbooleanShows the link as weak text, or a disabled button, that goes nowhere.

SetupAssistantToggletype

A switch that turns a setting on or off, through onToggleChange.

type SetupAssistantToggle = {
  type: "toggle"
  value: string
  label: string
  disabled?: boolean
} & (
  | {
      checked: boolean
      unavailableLabel?: never
    }
  | {
      checked: null
      unavailableLabel: string
    }
)

SetupAssistantControltype

type SetupAssistantControl =
  | SetupAssistantButtonAction
  | SetupAssistantLinkAction
  | SetupAssistantToggle

SetupAssistantActionTargettype

What an action is for: a step, or one of a sequence's substeps.

MemberTypeDefaultDescription
stepId*stringThe step's id.
substepIdstringThe substep's id, when the action is a substep's.

SetupAssistantTaskProgresstype

A task's progress. Unknown never counts as not started.

type SetupAssistantTaskProgress =
  | { value: "untracked" }
  | { value: "not-started"; label: string }
  | { value: "in-progress"; label: string; percent: number | null }
  | { value: "complete"; label: string }
  | { value: "unknown"; label: string }

SetupAssistantSequenceProgresstype

A sequence's progress: how many substeps are done, counted from the first.

type SetupAssistantSequenceProgress =
  | { value: "known"; completed: number }
  | { value: "unknown"; label: string }

SetupAssistantSubsteptype

One substep of a sequence. Substeps are done in order.

MemberTypeDefaultDescription
id*stringUnique within its sequence.
label*stringWhat to do: "Confirm field mapping".
descriptionstringA line under the label.
actionSetupAssistantButtonAction | SetupAssistantLinkActionA button or link for the substep. Later substeps' actions wait for earlier ones.

SetupAssistantTasktype

A step done in one go, with an optional button or link.

type SetupAssistantTask = SetupAssistantStepContent & {
  kind: "task"
  progress: SetupAssistantTaskProgress
  action?: SetupAssistantButtonAction | SetupAssistantLinkAction
}

SetupAssistantSettingtype

A step that turns a setting on with a switch.

type SetupAssistantSetting = SetupAssistantStepContent & {
  kind: "setting"
  tracked: boolean
  action: SetupAssistantToggle
}

SetupAssistantSequencetype

A step that expands into substeps done in order. Its ring counts them.

type SetupAssistantSequence = SetupAssistantStepContent & {
  kind: "sequence"
  progress: SetupAssistantSequenceProgress
  substeps: readonly [SetupAssistantSubstep, ...SetupAssistantSubstep[]]
}

SetupAssistantSteptype

type SetupAssistantStep =
  | SetupAssistantTask
  | SetupAssistantSetting
  | SetupAssistantSequence

SetupAssistantReadtype

The steps as read: a list, partial when some couldn't be read, or null when none could.

type SetupAssistantRead =
  | {
      steps: readonly SetupAssistantStep[]
      partial?: { message: string }
      unavailableMessage?: never
    }
  | {
      steps: null
      partial?: never
      unavailableMessage?: string
    }

Accessibility

  • Each step's title is a heading at headingLevel, 2 by default. Set it one below the heading the list sits under.
  • A sequence opens from its chevron and from its title. Both report aria-expanded and point at the substeps with aria-controls.
  • Each ring is named "Step 2: Prepare your account data" and described by the step's progress label. Unknown progress shows its label on the page, and a setting that couldn't be read shows its unavailableLabel in place of the switch.
  • A switch is named by its toggle's label. The On and Off beside it are hidden from screen readers, which hear the switch's state. Without onToggleChange there's no switch, and screen readers hear the label before the On or Off text.
  • A link with disabled, or a later substep's link, is plain text with no href, so it takes no focus. With the button look it's a disabled button.
  • If your app closes an open sequence while focus is inside it, move focus to its title first.

Responsive behavior

  • The block takes its container's width. Below 32rem, a step's action and estimate move under its description.
  • Titles, descriptions and substeps wrap instead of truncating. Give the card a max-w-* so lines stay readable on a wide page.

Rules

  • Keep completion in steps, written by your app. Nothing in the block completes a step by itself.
  • Pass an unknown progress with a label when you couldn't read it, never not-started or 0. For a setting, pass checked: null with an unavailableLabel, never false. Unknown never counts as done or not done.
  • Pass partial with a message when only some steps could be read, and steps={null} when none could, never a shorter or empty list: an empty list says there are none.
  • Pass loading while the steps load, never an empty list. To reload steps already shown, keep passing them with loading: the rows stay, and the summary says progress is updating instead of showing a bar that may be stale.
  • Give every step a unique id, and every substep one unique within its step. Ids keep the open sequences and callbacks pointed at the right row when steps reorder.
  • estimatedTime is a label. It never weighs progress, and the summary counts finished steps.
  • Buttons render only with onAction, and switches only with onToggleChange. Without it, a setting shows its confirmed state as On or Off text.
  • Never pass asChild or render.