Before/After Comparison Toggle
A comparison section with a pill-style Before/After toggle above a list of feature items. Switching the toggle swaps in the other set of items, and each row fades and slides in on its own staggered delay so the new list animates in item by item rather than popping in all at once.
Docs
Installation
A real shadcn registry command, not a copy-paste stand-in: it fetches this block plus its dependencies and any missing npm packages, and installs them straight into your project.
npx shadcn add https://staaarter.com/r/before-after-comparison-toggle.jsonPrefer not to use the CLI? Copy the source from the Code toggle above into src/components/blocks/feature/feature102.tsx instead.
Usage
The file also exports feature102Demo, the exact props behind the preview above. Spread it to get a working section in one line, then replace it with your own data.
import { Feature102, feature102Demo } from "@/components/blocks/feature/feature102"; export default function Page() { return <Feature102 {...feature102Demo} />; }
Props
| Prop | Type | Default | Description |
|---|---|---|---|
| eyebrow | string | undefined | Small label above the heading; omitted entirely when unset. |
| heading | ReactNode | none | Section heading. |
| description | string | undefined | Supporting copy under the heading. |
| beforeLabel | string | "Before" | Label on the toggle's first segment. |
| afterLabel | string | "After" | Label on the toggle's second segment. |
| before | ComparisonItem[] | none | Items shown while the toggle is set to "before". |
| after | ComparisonItem[] | none | Items shown while the toggle is set to "after". |
| className | string | undefined | Extra classes for the outer section element. |
Types
type ComparisonItem = { title: string; description: string; };
Behavior notes
- Real client-side state: clicking a toggle segment sets useState<"before" | "after">, which swaps the rendered item list and the toggle's own visual state (aria-pressed and background) between the two segments.
- "use client" component, so its demo props live in the sibling feature102.demo.tsx file per this repo's client/demo-file-split rule, not in feature102.tsx itself.
- The staggered fade-in is real: each row is keyed by `${mode}-${item.title}`, so switching modes remounts every row and replays a `tw-animate-css` enter animation (fade + slight slide) with a per-index `animationDelay` set inline (`index * 80ms`), producing a genuine staggered reveal rather than a single simultaneous fade.
- The pill toggle is a two-segment `role="group"` of native buttons with `aria-pressed` on each segment, not a single checkbox, so both the pressed segment and the underlying state stay in sync for assistive tech.
- Each row's leading icon (check for "after", x for "before") is purely decorative styling driven by the current mode, not per-item data.
More Feature Blocks
View all →Full-Bleed Workspace Band
Two-column header above a full-bleed image band with a live view switcher, closing on three numbered captions.
Center-Line Journey Timeline
Vertical hairline timeline alternating stages either side, dropping a phone frame on one step.
Figure-Led Evidence Rows
Tall image with a floating before-and-after card, leading into oversized-figure evidence rows.
Staircase Asset Trio
Three image tiles stepping down the page in a staircase, each floating a different live asset.
Sticky Reference List
Sticky heading column beside three labelled groups of checked capabilities, closing on a footnote.
Day Timeline Rows
Hairline rows walking through one working day, stamped with time and a live approval card inline.