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.
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 spec-label-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.
<SpecLabelSection/>
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/spec-label-section.en.jsonOr, once registries are configured in components.json, install it as @webberui/spec-label-section.
Usage
import {
SpecLabelSection,
type SpecItem,
} from "@/components/ui/spec-label-section";
const items: SpecItem[] = [
{
id: "battery",
label: "Battery life",
value: "38",
unit: "hours",
emphasis: true,
detail: "Measured in continuous playback with active noise cancelling on at 50% volume.",
links: [{ label: "Test method", href: "#" }],
},
{ id: "weight", label: "Weight", value: "248", unit: "g" },
];
<SpecLabelSection
title="Specs at a glance"
subtitle="Model NC-900 · per pair"
items={items}
/>;Props
SpecLabelSection
| Prop | Type | Default | Description |
|---|---|---|---|
items | SpecItem[] | — | Spec item data |
title | React.ReactNode | — | Section title, also used as the aria label |
subtitle | React.ReactNode | — | Subtitle below the title (model, serving size, and so on) |
featureHeading | React.ReactNode | "Item" | Column header: title of the feature column |
valueHeading | React.ReactNode | "Spec" | Column header: title of the value column |
footnote | React.ReactNode | — | Small footnote at the bottom (separated by a thick rule) |
openIds | string[] | — | Controlled mode: array of currently expanded row ids |
defaultOpenIds | string[] | [] | Initial array of expanded ids in uncontrolled mode |
onOpenChange | (ids: string[]) => void | — | Fires when the expanded state changes |
stagger | number | 0.08 | Interval between each row's stamp-in (seconds) |
delay | number | 0 | Delay before the reveal starts (seconds) |
duration | number | 0.3 | Expand / collapse duration (seconds) |
once | boolean | true | Play only the first time the element enters the viewport |
SpecItem
| Field | Type | Description |
|---|---|---|
id | string | Unique key, used to match controlled expansion — keep it stable |
label | React.ReactNode | Feature / item name (left side of the row) |
value | React.ReactNode | Main value (format it yourself) |
unit | React.ReactNode | Unit after the value (at a smaller size) |
emphasis | boolean | Emphasize this row with a thick rule and a larger number |
detail | React.ReactNode | Explanatory note shown once expanded |
links | SpecEvidenceLink[] | Supporting links shown once expanded |
SpecEvidenceLink
| Field | Type | Description |
|---|---|---|
label | React.ReactNode | Link text |
href | string | Link URL (opens in a new tab) |
How it works
- Stamp-in: when the whole table scrolls into the window, each row settles down from a slightly larger scale, accompanied by a fade in and a touch of blur, stamping in row by row according to
stagger. Setonce={false}to replay it every time it enters the viewport. - Thick and thin rules: the outer frame, the signature thick black bar, and the bottom edge of the header are thick rules; ordinary rows are separated by thin gray lines, while
emphasisrows switch to a thick black rule and enlarge the value, mimicking the hierarchy of a nutrition label. - Expandable rows: rows that carry
detailorlinksshow an indicator arrow and are clickable, expanding the note and supporting links below the row with a height transition; rows with neither render as static, non-interactive rows. - Controlled and uncontrolled: when
openIdsis not passed, the component manages the expanded state itself (usedefaultOpenIdsto set the initial one); passingopenIdsmakes it fully controlled, synchronized throughonOpenChange. Multiple rows may be expanded at once.
Accessibility
- Expandable rows are native
<button>s carryingaria-expandedandaria-controls; they are keyboard focusable and toggle with Enter / Space. - The expanded block is a
role="region"that points back at its trigger row througharia-labelledby. - When
titleis provided, the section is associated with its heading througharia-labelledby. - Supporting links open with
target="_blank"and carryrel="noopener noreferrer". - When the user has "reduce motion" enabled at the system level, the stamp-in and the expand transition are disabled and a static table is shown directly.
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.
Milestone Unlock Meter
A full-bleed progress meter — the liquid level rises to fill the whole section from data or scroll, and every time it crosses a threshold the matching milestone card pops open, unlocked and lit.