Setup Checklist with Progress Sidebar

Setup

Launch-ready in a single afternoon

A pragmatic checklist that keeps your rollout predictable: configure essentials, validate data, and go live with confidence.

Connect your data sources

5–10 min
Done
Authenticate and validate read permissions. We'll auto-detect schemas and suggest sane defaults.

Configure roles & access

10–15 min
In progress
Define who can view, edit, and publish. Invite teammates and set approval rules.

Apply templates & standards

15–25 min
Todo
Start from curated templates and enforce consistent typography, spacing, and brand colors across pages.

Enable monitoring

10 min
Todo
Track uptime and core events. Set alerts for broken links, failed forms, and slow pages.
About this block

Setup Checklist with Progress SidebarFREE

Multi-step checklist with status indicators, ETAs, and a sticky sidebar showing completion progress and key stats. Perfect for onboarding flows, implementation guides, or setup wizards.

Feature22: Setup Checklist with Progress Sidebar

Two-column onboarding layout: a list of status-tagged setup steps on the left (each optionally a link, with an ETA and a done/in-progress/todo pill), and a sticky sidebar on the right showing a computed completion percentage, a progress bar, key stats, and CTA buttons.

Free block

This block is free. No license or account is required: install it with the CLI and use it in unlimited projects.

Installation

Radix flavor

bash
npx shadcn add "https://ui.beste.co/r/feature22"

Base UI flavor

bash
npx shadcn add "https://ui.beste.co/r-base/feature22"

This installs the block to components/beste/block/feature22.tsx and the shadcn/ui badge, button, and progress components it depends on.

Quick start

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

tsx
import { Feature22, feature22Demo } from "@/components/beste/block/feature22";

export default function Page() {
  return <Feature22 {...feature22Demo} />;
}

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

tsx
import { Plug, ShieldCheck, Wand2 } from "lucide-react";
import { Feature22 } from "@/components/beste/block/feature22";

export default function Page() {
  return (
    <Feature22
      badge={{ label: "Setup", variant: "secondary" }}
      heading="Launch-ready in a single afternoon"
      description="Configure essentials, validate data, and go live with confidence."
      steps={[
        {
          id: "step-1",
          icon: <Plug className="size-6 md:size-8" />,
          title: "Connect your data sources",
          eta: "5-10 min",
          status: "done",
          href: "/setup/connect",
        },
        {
          id: "step-2",
          icon: <ShieldCheck className="size-6 md:size-8" />,
          title: "Configure roles & access",
          eta: "10-15 min",
          status: "in_progress",
        },
        {
          id: "step-3",
          icon: <Wand2 className="size-6 md:size-8" />,
          title: "Apply templates & standards",
          eta: "15-25 min",
          status: "todo",
        },
      ]}
      stats={[{ id: "stat-1", label: "Avg. time to first publish", value: "45 min" }]}
      buttons={[{ id: "btn-1", label: "Start a guided setup", href: "/setup" }]}
    />
  );
}

Props

PropTypeDefaultDescription
badge{ label: string; variant?: "default" | "secondary" | "outline" }–Badge above the heading
headingstring–Section heading
descriptionstring–Section intro text
progressLabelstring"Progress"Label above the sidebar's percentage readout
stepsCompletedLabelstring"steps completed"Suffix after the done/total count in the sidebar
stepsStep[][]Checklist rows on the left
statsStat[][]Key-number rows inside the sidebar
buttonsButtonItem[][]CTA buttons at the bottom of the sidebar
classNamestring–Extra classes for the outer <section>
ts
type StepStatus = "done" | "in_progress" | "todo";

type Step = {
  id: string;
  icon?: React.ReactNode;
  title: string;
  description?: string;
  eta?: string;
  status?: StepStatus;
  href?: string;
};

type Stat = {
  id: string;
  label: string;
  value: string;
  description?: string;
};

type ButtonItem = {
  id: string;
  label: string;
  href?: string;
  variant?: "default" | "secondary" | "outline" | "ghost" | "link" | "destructive";
};

Behavior notes

  • The component returns null when steps is empty (if (steps.length === 0) return null;), so an empty checklist renders nothing at all rather than an empty section shell, unlike the other blocks in this batch.
  • Completion percentage is computed with useMemo, counting steps whose status is "done" against steps.length; the same progressPercent value drives both the sidebar's numeric readout and the Progress bar.
  • A step with href set renders as a full-width Link wrapping the whole card (hover:opacity-80 on hover); a step without href renders as a plain, non-interactive div with identical markup otherwise.
  • The sidebar is lg:sticky lg:top-6, so it stays pinned in view while the step list scrolls past it on large screens; below lg the layout drops to a single column (the lg:grid-cols-[1.35fr_0.65fr] split only applies at lg and up) and the sidebar simply stacks after the steps.
  • icon is typed as React.ReactNode, a pre-rendered element such as <Plug className="size-6 md:size-8" />, rather than the LucideIcon component-reference pattern (icon?: LucideIcon) used by the other blocks in this batch, so callers size and style the icon themselves before passing it in.

More Feature blocks

View all Feature
PRO

feature60

Feature Walkthrough with Sticky Navigation

PRO

feature164

Scroll-Spy Sticky Sidebar Feature

PRO

feature158

Notification Status List