MenuClose

Block Comparison — React Page Block

Before/after comparison with a draggable reveal handle — keyboard (arrow keys, Home/End), touch and screen readers all work because the handle is a real range input.

View source
PreviewReact
Starting live preview

Usage

import { BlockComparison } from "@/components/BlockComparison";

export function BeforeAfter() {
  return (
    <BlockComparison
      title="Drag to see the redesign."
      before={<img src="/before.png" alt="Before the redesign" />}
      after={<img src="/after.png" alt="After the redesign" />}
      beforeLabel="Old site"
      afterLabel="Our work"
      {...{
        title: "A new look. The same good coffee.",
        defaultPosition: 50,
        accent: "#d5ed9a",
        scheme: "dark"
      }}
    />
  );
}
Implementation notes & API

Purpose: before/after comparison slider. Copy it, ship it — every string, link and color arrives through props. Runtime: pure DOM + CSS. No WebGPU, canvas, animation library or external assets; SSR-safe on first render. Theming: root custom properties (--vb-bg, --vb-fg, --vb-accent, --vb-border, --vb-radius, --vb-container) or the accent/scheme/className/style props. scheme flips the dark default to light. Guardrails: responsive via container queries down to 320px; interactive behavior degrades on touch; prefers-reduced-motion drops entrance/scroll motion while content stays complete. The overlay range input owns interaction (drag, touch, keyboard, aria-valuetext); the visible handle is pointer-events:none decoration.

PropertyTypeNotes / default
eyebrow / title / descriptionReactNodeSection header
before / afterReactNodeThe two layers; defaults are CSS demo panels
beforeLabel / afterLabelstringChip labels (and the slider's accessible name)
defaultPositionnumber0-100 handle start; user moves are uncontrolled
captionReactNodeNote under the stage
scheme"dark" | "light"dark
accentstring (hex)Sets --vb-accent for the whole block
className / stylestring / CSSPropertiesApplied to the section root
childrenReactNodeReplaces the default content entirely
View source on GitHubFree for commercial projects · MIT