Back to components
Content
Page previewSteps List
A structured checklist for setup, onboarding, and release flows.
Source
This is the component source that shadcn installs into a consuming project.
import { CheckIcon } from "lucide-react"
import { Badge } from "@/components/ui/badge"
import {
Card,
CardContent,
CardDescription,
CardHeader,
CardTitle,
} from "@/components/ui/card"
import { Separator } from "@/components/ui/separator"
type StepListItem = {
title: string
description: string
}
type StepsListCopy = {
badge: string
title: string
description: string
doneLabel: string
steps: [StepListItem, StepListItem, StepListItem]
}
type StepsListProps = {
copy?: StepsListCopy
}
const defaultCopy: StepsListCopy = {
badge: "Workflow",
title: "Publish checklist",
description: "Use this pattern for onboarding, release flow, or setup progress.",
doneLabel: "Done",
steps: [
{
title: "Design the block",
description: "Compose existing primitives and keep the public props small.",
},
{
title: "Build registry JSON",
description: "Generate installable artifacts for every component item.",
},
{
title: "Verify installation",
description: "Install into a clean app before sharing the registry URL.",
},
],
}
export function StepsList({ copy = defaultCopy }: StepsListProps) {
return (
<Card className="w-full max-w-xl">
<CardHeader>
<Badge className="w-fit" variant="secondary">
{copy.badge}
</Badge>
<CardTitle>{copy.title}</CardTitle>
<CardDescription>{copy.description}</CardDescription>
</CardHeader>
<CardContent className="flex flex-col gap-4">
{copy.steps.map((step, index) => (
<div key={step.title} className="flex flex-col gap-4">
<div className="flex gap-3">
<div className="flex size-7 shrink-0 items-center justify-center rounded-full border bg-background text-xs font-medium">
{index + 1}
</div>
<div className="flex min-w-0 flex-1 flex-col gap-1">
<div className="flex flex-wrap items-center gap-2">
<h3 className="text-sm font-medium">{step.title}</h3>
{index === 0 ? (
<Badge variant="outline">
<CheckIcon />
{copy.doneLabel}
</Badge>
) : null}
</div>
<p className="text-sm leading-6 text-muted-foreground">
{step.description}
</p>
</div>
</div>
{index < copy.steps.length - 1 ? <Separator /> : null}
</div>
))}
</CardContent>
</Card>
)
}