Steps
Two-title intro on the left, numbered steps with a dashed vertical rail on the right.
How itworks.
Browse the catalog
Open the blocks directory, find a section that fits the page you are building.
Copy the source
Drop the source file into your repo. It carries no runtime — just React and Tailwind.
Edit freely
No upstream contract. Rename, restyle, restructure — your copy is your contract.
Stay informed
The changelog calls out any upstream change worth mirroring. Updates are opt-in.
import { Steps } from '@/foundations/blocks/steps';
export default function StepsPreview() {
return (
<Steps
eyebrow="How it"
title="works."
steps={[
{
title: 'Browse the catalog',
description:
'Open the blocks directory, find a section that fits the page you are building.',
},
{
title: 'Copy the source',
description:
'Drop the source file into your repo. It carries no runtime — just React and Tailwind.',
},
{
title: 'Edit freely',
description:
'No upstream contract. Rename, restyle, restructure — your copy is your contract.',
},
{
title: 'Stay informed',
description:
'The changelog calls out any upstream change worth mirroring. Updates are opt-in.',
},
]}
/>
);
}
export const meta = {
layout: 'fullscreen',
}; Dependencies
Source Code
import { Container } from '@/components/container';
import { cn } from '@/lib/utils/classnames';
interface StepItem {
title: React.ReactNode;
description: React.ReactNode;
}
interface StepsProps
extends Omit<React.ComponentPropsWithRef<'section'>, 'title'> {
/** First line of the title (rendered in foreground-secondary). */
eyebrow: React.ReactNode;
/** Second line of the title (rendered in default foreground). */
title: React.ReactNode;
steps: StepItem[];
}
const Steps = ({
ref,
className,
eyebrow,
title,
steps,
...rest
}: StepsProps) => (
<section
ref={ref}
className={cn('w-full py-16 md:py-24', className)}
{...rest}
>
<Container>
<div className="flex flex-col gap-12 lg:flex-row lg:gap-16">
<div className="lg:flex-1">
<h2 className="max-w-md text-balance text-4xl md:text-5xl">
<span className="block text-foreground-secondary">{eyebrow}</span>
{title}
</h2>
</div>
<div className="relative lg:flex-1 lg:border-border lg:border-l lg:border-dashed lg:pl-12">
{steps.map((step, i) => (
<div key={i} className="mb-12 last:mb-0">
<span
className={cn(
'mb-4 flex size-8 items-center justify-center rounded-full border border-border bg-background text-xs tabular-nums',
'lg:absolute lg:-left-4'
)}
>
{i + 1}
</span>
<div className="max-w-xl text-2xl">
<h3 className="leading-tight">{step.title}</h3>
<p className="mt-1 text-foreground-secondary leading-tight">
{step.description}
</p>
</div>
</div>
))}
</div>
</div>
</Container>
</section>
);
export type { StepItem, StepsProps };
export { Steps }; Steps is the “how it works” block — a two-line title on the left, a list of
numbered steps on the right, joined by a dashed vertical rail on lg+.
Anatomy
<Steps
eyebrow="How it"
title="works."
steps={[
{ title: 'Pick a block', description: 'Browse the catalog.' },
{ title: 'Copy the source', description: 'It lands in your repo.' },
{ title: 'Edit freely', description: 'No upstream contract.' },
]}
/>
API Reference
Extends the section element.
| Prop | Default | Type |
|---|---|---|
eyebrow * | - | ReactNode |
title * | - | ReactNode |
steps * | - | StepItem[] |
StepItem
interface StepItem {
title: React.ReactNode;
description: React.ReactNode;
}
Examples
Default
How itworks.
Browse the catalog
Open the blocks directory, find a section that fits the page you are building.
Copy the source
Drop the source file into your repo. It carries no runtime — just React and Tailwind.
Edit freely
No upstream contract. Rename, restyle, restructure — your copy is your contract.
Stay informed
The changelog calls out any upstream change worth mirroring. Updates are opt-in.
import { Steps } from '@/foundations/blocks/steps';
export default function StepsPreview() {
return (
<Steps
eyebrow="How it"
title="works."
steps={[
{
title: 'Browse the catalog',
description:
'Open the blocks directory, find a section that fits the page you are building.',
},
{
title: 'Copy the source',
description:
'Drop the source file into your repo. It carries no runtime — just React and Tailwind.',
},
{
title: 'Edit freely',
description:
'No upstream contract. Rename, restyle, restructure — your copy is your contract.',
},
{
title: 'Stay informed',
description:
'The changelog calls out any upstream change worth mirroring. Updates are opt-in.',
},
]}
/>
);
}
export const meta = {
layout: 'fullscreen',
}; Previous
Stat Grid
Next
Text with Media