Circular Progress with Checklist

Progress

Complete your setup

Finish these tasks to unlock all features.

67%

4

Complete

2

remaining

  • Create your account
  • Verify email address
  • Add profile picture
  • Set up two-factor auth
  • Connect payment method
  • Invite team members
About this block

Circular Progress with ChecklistPRO

Visual progress tracker featuring a circular percentage indicator with completion stats and task list. Perfect for profile setup flows that encourage users to reach 100% completion.

Onboarding12: Circular Progress with Checklist

Profile-completion screen built around a hand-drawn SVG progress ring, a completed/remaining stat pair, and a checklist card beneath it. Like the other checklist-style onboarding blocks, completion is entirely data-driven: there is no click handler to check off a task.

Upgrade to Pro

Pro blocks install through the shadcn CLI with your license key and ship their full source. Docs and live previews stay open to everyone, so you can read every block's details first.

Upgrade Now

Installation

Swap YOUR_EMAIL and YOUR_KEY for the email and license key on your account. Find your license key on your account page.

Radix flavor

bash
npx shadcn add "https://ui.beste.co/r/onboarding12?email=YOUR_EMAIL&license_key=YOUR_KEY"

Base UI flavor

bash
npx shadcn add "https://ui.beste.co/r-base/onboarding12?email=YOUR_EMAIL&license_key=YOUR_KEY"

This installs the block to components/beste/block/onboarding12.tsx and the badge and button shadcn/ui primitives it depends on.

Quick start

The installed file exports onboarding12Demo alongside the block: the exact props behind the preview above. Spread it to get a working progress ring in one line.

tsx
import { Onboarding12, onboarding12Demo } from "@/components/beste/block/onboarding12";

export default function OnboardingPage() {
  return <Onboarding12 {...onboarding12Demo} />;
}

Then replace the demo with your own props. Written out, a trimmed setup looks like this:

tsx
import { Onboarding12 } from "@/components/beste/block/onboarding12";

export default function OnboardingPage() {
  return (
    <Onboarding12
      badge={{ label: "Progress", variant: "secondary" }}
      heading="Complete your setup"
      description="Finish these tasks to unlock all features."
      tasks={[
        { id: "1", title: "Create your account", completed: true },
        { id: "2", title: "Verify email address", completed: true },
        { id: "3", title: "Connect payment method", completed: false },
        { id: "4", title: "Invite team members", completed: false },
      ]}
      labels={{ complete: "Complete", remaining: "remaining" }}
      buttons={[{ label: "Continue Setup", href: "/setup" }]}
    />
  );
}

Props

PropTypeDefaultDescription
badge{ label: string; variant?: "default" | "secondary" | "outline" }Small badge above the heading
headingstringMain headline
descriptionstringSupporting copy below the heading
tasksTask[][]Checklist items, each with its own completion flag
labels{ complete?: string; remaining?: string }{}Words under the completed/remaining stat numbers
buttonsButtonConfig[][]CTA row below the checklist
classNamestringExtra classes for the outer <section>
ts
type Task = {
  id: string;
  title: string;
  completed: boolean;
};

type ButtonConfig = {
  label: string;
  href: string;
  variant?: "default" | "secondary" | "outline" | "ghost";
};

Behavior notes

  • Progress is entirely derived from tasks[].completed; there is no click handler to check off a task, so animating the ring means changing the tasks prop and letting the ring's own transition-all duration-500 animate the stroke change.
  • The ring is a hand-built inline CircularProgress component: a muted background circle plus a primary-colored circle whose strokeDashoffset is computed from percentage, with the whole <svg> rotated -90 degrees so the arc starts at 12 o'clock instead of 3 o'clock.
  • The completed/remaining stat pair sits directly below the ring, separated by a vertical h-12 w-px divider; both numbers are derived from the same tasks.filter((t) => t.completed) count used to draw the ring.
  • Completed tasks get a strikethrough label; the task list uses divide-y on the <ul> for row separators rather than a border on each <li>.
  • If tasks is empty the component returns null rather than rendering an empty shell.
  • The percentage guards against division by zero (totalCount > 0 ? ... : 0), though in practice this path is unreachable in the rendered UI since an empty tasks array triggers the early null return first.

More Onboarding blocks

View all Onboarding
PRO

onboarding7

Progress Bar with Task Checklist

Card-based progress tracker showing completion percentage and a checklist of tasks with visual status. Perfect for gamified onboarding that motivates users to finish setup.

PRO

onboarding5

Horizontal Steps with Progress Line

Multi-step progress indicator with numbered circles connected by a progress line. Perfect for account setup wizards that show users their completion status.

PRO

onboarding33

Interactive Setup Checklist

A setup panel pairing a soft progress column, where an oversized percentage and accent bar react to what is ticked, with hairline checklist rows that each carry a description and a jump-in link.

PRO

onboarding39

Thirty Day Milestones

An onboarding section setting out four dated milestones as bordered cards, each closing on the figure it should hit, above a soft panel that floats a live progress metric on an image tile.

FREE

onboarding9

Step Cards with Numbered Indicators

Animated step wizard with square numbered indicators and content cards for each step. Perfect for product walkthroughs that guide users through key features.

PRO

onboarding6

Vertical Timeline Steps

Vertical timeline layout with step indicators, descriptions, and a connecting progress line. Perfect for workspace setup flows with detailed step explanations.