Blueprint Process Section
An engineering-blueprint take on the how-it-works layout — on graph paper, each step is a numbered, annotated station, and as you scroll the dashed leader lines, dimension callouts, and section marks are drawn in order as SVG stroke animations.
Bring this into your project
Run this command in your project folder. The CLI adds the source and dependencies; then follow the usage example below.
npx webberui@latest add blueprint-process-section.enPlayground
Tune the props live — the code snippet updates as you go, so you can dial in the look you want before copying it.
<BlueprintProcessSection/>
The complete example includes the preview layout and data. Install the component first, then paste this file into your project.
Installation
npx webberui@latest add https://webberui.com/r/blueprint-process-section.en.jsonOr, once registries are configured in components.json, install it as @webberui/blueprint-process-section.
Usage
Describe the process as a steps array; the component numbers each step as station 01…n automatically and draws the rail, leader lines, dimension callouts, and section marks in order as it scrolls into the viewport.
import { BlueprintProcessSection } from "@/components/ui/blueprint-process-section";
<BlueprintProcessSection
eyebrow="How it works"
title="Four steps to the drawing"
description="Follow the rail station by station, the way you would read an engineering blueprint."
steps={[
{ title: "Survey and requirements", description: "Start measuring from semantic tokens." },
{ title: "Tracing and prototype", description: "Turn the sketch into a running prototype." },
{ title: "Assembly and integration", description: "The source lands straight in your project." },
{ title: "Ship and sign-off", description: "reduced-motion support is built in." },
]}
/>;Nested scroll container
If the component sits inside a custom overflow-y-auto container, pass that container's ref to root so viewport detection uses the container (rather than the whole window) as its basis:
const scrollerRef = React.useRef<HTMLDivElement>(null);
<div ref={scrollerRef} className="h-[300px] overflow-y-auto">
<BlueprintProcessSection root={scrollerRef} steps={steps} />
</div>;Labels and icons
Each step can override the tag on its dimension callout plate (STEP 0n by default) and bring in a lucide icon through icon:
import { Ruler } from "lucide-react";
<BlueprintProcessSection
steps={[
{ title: "Survey", tag: "A-01", icon: <Ruler />, description: "…" },
]}
/>;Dimension callout DimensionCallout
The same file also exports DimensionCallout by name: a dimension line with arrowheads at both ends, extension lines, and a value label. On entry the lines draw in order via pathLength and the value fades in. Place it beside any element on the graph paper — without length it fills the parent's width horizontally (or height vertically), and extensionSide sets which side the extension lines point toward the measured element.
import { DimensionCallout } from "@/components/ui/blueprint-process-section";
<div className="w-60">
<DimensionCallout value="240 px" />
<div className="h-20 rounded border">Card component</div>
</div>;
<DimensionCallout value="80" orientation="vertical" extensionSide="start" length={80} />;Props
BlueprintProcessSection
| Prop | Type | Default | Description |
|---|---|---|---|
steps | BlueprintStep[] | — | List of steps, numbered automatically in order as stations 01…n |
eyebrow | React.ReactNode | — | Engineering-style eyebrow above the heading block (monospace) |
title | React.ReactNode | — | Main section title |
description | React.ReactNode | — | Section description |
gridSize | number | 22 | Spacing of the graph-paper grid lines (px) |
drawDuration | number | 0.65 | Duration of drawing a single annotation (seconds) |
stagger | number | 0.14 | Interval between the annotations drawn in order within one station (seconds) |
delay | number | 0 | Delay before a station starts once it enters the viewport (seconds) |
once | boolean | true | Play the drawing animation only the first time the element enters the viewport |
root | React.RefObject<HTMLElement | null> | — | Ref of the nested scroll container, used as the root for viewport detection |
className | string | — | Custom classes for the outer section |
BlueprintStep
| Field | Type | Description |
|---|---|---|
title | React.ReactNode | Step title |
description | React.ReactNode | Step description (optional) |
tag | string | Short label on the dimension callout plate (optional, STEP 0n by default) |
icon | React.ReactNode | Small icon before the title (optional) |
id | string | Custom key / identifier (optional, defaults to the index) |
DimensionCallout
| Prop | Type | Default | Description |
|---|---|---|---|
value | React.ReactNode | — | Value label, e.g. 320 px; rendered as real text |
orientation | "horizontal" | "vertical" | "horizontal" | Dimension line direction: horizontal measures width, vertical measures height |
length | number | — | Dimension line length (px); fills the parent when omitted |
extension | number | 10 | Extension line length (px), i.e. the distance from the dimension line to the measured element |
extensionSide | "start" | "end" | "end" | Direction the extension lines point toward the measured element: end is down/right, start is up/left |
drawDuration | number | 0.6 | Line drawing duration (seconds) |
delay | number | 0 | Delay before drawing starts once it enters the viewport (seconds) |
once | boolean | true | Play the drawing animation only the first time it enters the viewport |
root | React.RefObject<HTMLElement | null> | — | Ref of the nested scroll container, used as the root for viewport detection |
className | string | — | Custom classes for the outer container |
How it works
- Each station measures the real pixel dimensions of its own row with a
ResizeObserver, and the annotation layer<svg>maps coordinates 1:1 through itsviewBox, so circles and tick marks never distort when scaled. - The rail, dimension callouts, and section marks appear one by one as
pathLengthdraws from 0 to 1; the dashed leader lines instead expand from the node toward the drawing frame withscaleX, which preserves the dash pattern (pathLengthwould overridestrokeDasharray). - The rail runs through the full height of a row and joins seamlessly between rows, with short cap lines added at the top of the first row and the bottom of the last, so it reads as one continuous measurement datum line.
- The graph-paper ground switches its light/dark grid line color through the CSS variable
--wb-grid, and the grid spacing is controlled bygridSize. DimensionCalloutdraws extension lines → dimension line → arrowheads in order withpathLength, spaced by a fraction ofdrawDuration, and the value fades in once the lines are half drawn; the value plate covers the middle of the dimension line, like writing the number into a broken dimension line on a drawing. Withoutlengthit measures its parent with aResizeObserverand draws no lines until measured.
Accessibility
- The steps are laid out semantically as
<ol>/<li>with<h3>titles, so the reading order is the station order; the annotation layer (rail, leader lines, dimensions, section marks) is decorative (aria-hidden) and does not interfere with screen readers. - Node numbers, labels, and section codes are all drawn inside the decorative
<svg>; the semantics are carried by the list order and the headings, so nothing is announced twice. - The lines of
DimensionCalloutare a decorative<svg>(aria-hidden); the value is plain text that screen readers announce — write something like "Width 240 px" invaluewhen you need fuller semantics. - When the user has "reduce motion" enabled at the system level, all annotations (including
DimensionCallout) are shown directly in their final state with no drawing animation, and the content and layout are completely unchanged.
Trophy Case
An achievement trophy wall — a grid of glass cabinets displays your achievements; unlocking one raises the trophy, sweeps a highlight across it, and bursts a little confetti, while hovering lets you examine it in 3D and see its requirement and progress.
Spec Label Section
A product spec section styled like a nutrition label — rows stamp themselves in one by one as it scrolls into the window, and any row can expand to show notes and supporting links.