MenuClose

Block Feature Tabs — React Page Block

Feature tabs where the list, copy and illustration switch together. WAI-ARIA tabs pattern with arrow keys; a scrollable strip above the stage on touch layouts.

View source
PreviewReact
Starting live preview

Usage

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

export function Surfaces() {
  return (
    <BlockFeatureTabs
      title="One graph. Three ways to look at it."
      tabs={[
        { label: "Plan", description: "Sketch the release as a graph." },
        { label: "Ship", description: "Flags with staged rollouts." },
        { label: "Review", description: "Replay the week on one timeline." },
      ]}
      {...{
        title: "Every part of the release. In reach.",
        accent: "#d5ed9a",
        scheme: "dark"
      }}
    />
  );
}
Implementation notes & API

Purpose: interactive feature tabs. 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. Keyboard: Left/Right (and Up/Down) cycle, Home/End jump, Tab moves into the panel; the panel is focusable and labeled by the active tab. Each tab's default illustration is a CSS scene; pass media per tab for real screenshots.

PropertyTypeNotes / default
eyebrow / title / descriptionReactNodeSection header
tabsreadonly FeatureTab[]{ label, description, media?, href? }
action{ label, href? , onClick? } | nullPer-tab action; tab.href wins when set
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