Xzero UI
Pro library

Onboarding surveyPro

A post-signup onboarding survey where each question gets its own step of large option cards, picked with keys 1 to 4 and Enter. A short personalization checklist then ticks off and lands on an editable "You're all set" summary.

$ pnpm dlx shadcn@4.23.0 add @xzero-ui-pro/onboarding-survey
Live · keyboard ready

Drop it in right after sign-up and pass your own questions (two to four options each, with 16px icons or mono brand marks). Store picks from onAnswer as they happen. Put your real setup work in personalize(answers, signal): the last checklist item waits for it, and if it rejects, the card shows the error with Try again. Route on with onComplete(answers). setupSteps sets the checklist labels to match the answers. With no props it plays a sample run that stops on the first click or key press.

When to use

When not to use

Installation

Register both Xzero UI namespaces in your project's components.json:

{
  "registries": {
    "@xzero-ui": "https://mcp.xzero.co.uk/r/{name}.json",
    "@xzero-ui-pro": "https://mcp.xzero.co.uk/r/pro/{name}.json"
  }
}
npx shadcn@4.23.0 add @xzero-ui-pro/onboarding-survey

Install xzero-foundation once, and import @/components/xzero/foundation.css in your app root. No Xzero token is used by this snapshot. For sample portraits, photos, fonts, or logos, download https://mcp.xzero.co.uk/install-assets.mjs and run node xzero-install-assets.mjs <receiving-project>.

Usage

import { OnboardingSurvey } from "@/components/xzero/blocks/onboarding-survey/onboarding-survey";

export function Welcome() {
  return (
    <OnboardingSurvey
      questions={questions}
      onAnswer={(id, value) => analytics.track("onboarding_answer", { id, value })}
      personalize={async (answers, signal) => {
        await fetch("/api/workspace/personalize", { method: "POST", body: JSON.stringify(answers), signal });
      }}
      onComplete={() => router.push("/inbox")}
    />
  );
}

API reference

OnboardingSurvey

A post-signup survey card: one question per step on large option cards, a slim progress bar, keys 1 to 9 and Enter, then a personalization checklist that lands on an editable summary. With no props it plays a sample run until someone interacts.

PropTypeDefaultDescription
questionsOnboardingSurveyQuestion[]onboardingSurveySampleQuestionsOne question per step: { id, title, description?, label?, options: { value, label, description?, icon? }[] }. Two to four options read best; label names the summary row.
defaultAnswersRecord<string, string>–Answers to start from, keyed by question id. Start over resets to these.
setupStepsstring[] | (answers) => string[]–Checklist labels for the personalization step. Defaults to steps derived from the sample answers, or three generic steps for custom questions.
personalize(answers, signal: AbortSignal) => Promise<void>–Your real setup work, started when the last question is answered. The last checklist item waits for it; a rejection shows its message with Try again. The signal aborts when the person goes back or the card unmounts.
onAnswer(questionId, value: string | undefined, answers) => void–Fires on every pick. value is undefined when a question is skipped.
onComplete(answers) => void | Promise<void>–Runs when the finish button is pressed; the button shows a spinner while a returned promise is pending. Without it the finish is simulated.
autoPlaybooleantrue for the sample questionsPlays a sample run (number key, then Enter) and loops. Stops for good on the first pointer or key press, pauses off screen and never runs with reduced motion.
doneTitlestring"You're all set"Title of the final step.
doneDescriptionstring"Your workspace is ready. Change any answer below."Line under the final title.
finishLabelstring"Open workspace"Label of the finish button.
aria-labelstring"Onboarding survey"Accessible name of the card.
classNamestring–Extra class on the card.

Keyboard interactions

KeysAction
1 to 9Pick the matching option on the current question.
EnterContinue once an option is picked.
Arrow keysMove between options in the radio group and pick as you go.
TabMove through the selected option, Skip, Back and the main action.
SpacePick the focused option or press the focused button.

Accessibility

Motion

Responsive behavior

Performance

Notes for AI

Guidance for AI tools

Blocks are complete, self-contained screens with sample data. Replace the sample data and connect the callbacks described above. Follow the declared prop types and do not invent props. Keep keyboard access, reduced motion support, and both light and dark themes intact when adapting it.

Full library index: https://ui.xzero.co.uk/llms.txt

Browse all components