Figure with caption

Frames a static figure (a diagram, a record read at build time, a screenshot) with its title, its provenance and its caption.

Molecule · stable · v1.2.0 · owner: Site system lead · contract 19 of 20 points (open: figma)

Do and don't

Do: A record read at build time

Rendered by figure-frame.ts

Open example: Figure with caption · Do: A record read at build time Use the full-page example to follow page links.

Title, provenance and source.

Do: A screenshot

Rendered by figure-frame.ts

Open example: Figure with caption · Do: A screenshot Use the full-page example to follow page links.

It says the records are sample.

Do: Native labelled diagram

Rendered by figure-frame.ts

Open example: Figure with caption · Do: Native labelled diagram Use the full-page example to follow page links.

Constructor owns figure/caption; native organism keeps its content layout.

Do: Native-owned evidence root

Rendered by figure-frame.ts

Open example: Figure with caption · Do: Native-owned evidence root Use the full-page example to follow page links.

Owns the existing static figure and caption association without adding visual styling or a live binding.

Don't: No caption

Rendered by figure-frame.ts

Open example: Figure with caption · Don't: No caption Use the full-page example to follow page links.

A figure without its source cannot be checked.

Don't: A self-playing element in a figure frame

Rendered by figure-frame.ts

Open example: Figure with caption · Don't: A self-playing element in a figure frame Use the full-page example to follow page links.

Anything that plays goes in the ShowcaseFrame with playback controls.

Rules

RuleWhyCheck
Native form preserves actual labels, source caption and visual binding without playback or an added head.Reuse must retain the real figure and enhancement selector.Automated: tests/unit/frame-api-compatibility.test.ts
Every figure has a caption with its data source.Evidence must be checkable.Automated: scripts/site/system/check-pages.ts (figure without figcaption)
Figures do not play; showcases do.One frame for evidence, one for experiences: the reader learns what each means.Automated: scripts/site/system/check-pages.ts (data-pl-controls only inside a showcase frame)

API

PropTypeRequiredDefaultWhat it does
classNamestringNoNative variant only: exact existing root class list without a visual prefix; nonempty class tokens, mutually exclusive with kind.
variantframed | nativeNo"framed"Existing head/box or native captioned figure without extra chrome.
idstringNoCaller-owned root ID.
langen | jaNoExplicit source language.
labelledBystringNoActual body/caption label IDs; dangling references refused.
visualobjectNoExisting {name,variant} data-visual binding, not data-demo.
captionOptionsobjectNoCaption kind/label/claim/state and native id/lang/extraClass; tag stays figcaption.
titlestringNoRequired framed title; native form retains its body label.
tagstringNoProvenance: Sample data, Recorded server output, a version.
bodyhtmlYesThe figure markup (an organism or an image).
captionhtmlYesWhat it shows and where the data comes from.
kindstringNoThe figure organism's class added after visual (contract-x, screen-shot); exclusive with native className.

Contract details

The full contract: identity, anatomy, variants, states, tokens, layout, motion, accessibility, content, tests

Identity

AspectValue
Idfigure-frame
LayerMolecules
Categorymedia
OwnerSite system lead
Statusstable
Version1.2.0
Sourceapps/showcase/site/system/molecules/figure-frame.ts (private repository; the contract and the render function are this one module)
VersionDateChange
1.2.02026-10-29Add explicit native-owned root classes without adding visual; default and kind-based frames unchanged.
1.1.02026-10-29Add native captioned figure and typed root metadata; default output unchanged.
1.0.02026-10-26Every diagram and screenshot sits in one frame: a head with title and provenance tag, the figure, and its caption.

Use when

  • A diagram or real artefact supports a claim. Why: One frame makes every figure recognisable as evidence.
  • A screenshot of the product. Why: The frame states it is a real screen with sample records.

Do not use when

  • For something that plays or reacts. Why: Self-playing elements sit in the ShowcaseFrame, with playback controls.
  • Without a caption. Why: Every figure says what it shows and where its data comes from (D-SITE-007).

Anatomy

PartWhat it is
rootfigure.visual (+ kind) by default; native className owns the exact existing root classes
framediv.visual-frame
headFramed only: div.visual-head with h3 and Tag; native body retains its own label
bodyThe figure itself
captionfigcaption

Made of: heading, tag, caption, tokens:colour.

Used in: cloth-diagram, conformance-table, contract-excerpt, coverage-map, decision-list, design-md-excerpt, drift-palette, flow-diagram, flow-layers, product-screen, repo-tree, system-of-systems, takenote-card, token-chain, job-section.

Variants

VariantWhenWhy
native captionedAn existing diagram/card has its own body label and layout.Retains its source caption without another box or a new root class when className is explicit.
diagramA diagram drawn from data.Same head and caption as every figure.
screenshotA product screen.Tagged 'Real screen, sample records'.

States

StateRendered or not applicable
defaultdefault
hoverNot applicable: A figure is not interactive, so it has no hover state.
focus-visibleNot applicable: A figure does not take focus; links and buttons inside it carry their own focus ring.
activeNot applicable: A figure cannot be pressed.
disabledNot applicable: A figure has nothing to disable.
loadingNot applicable: A figure is rendered at build time and is complete when the page loads.
emptyNot applicable: A figure is not rendered without content; the builder skips it.
errorNot applicable: A figure shows no data that can fail.
currentNot applicable: A figure has no current item.
visitedNot applicable: A figure is not a link.
expandedNot applicable: A figure does not open or close.

Tokens

PartToken
frame.background--surface
frame.border-top--rule-frame --ink
head.font--type-strong
caption.font--type-small
--figure-frame-background-surfacevar(--surface)
--figure-frame-border-top-rule-framevar(--rule-frame)
--figure-frame-border-top-inkvar(--ink)
--figure-frame-padding-space-8var(--space-8)
--figure-frame-padding-space-6var(--space-6)
--figure-frame-margin-top-space-5var(--space-5)
--figure-frame-font-type-smallvar(--type-small)
--figure-frame-color-ink-2var(--ink-2)
--figure-frame-gap-space-4var(--space-4)
--figure-frame-gap-space-7var(--space-7)
--figure-frame-margin-bottom-space-6var(--space-6)
--figure-frame-font-type-h3var(--type-h3)
--figure-frame-font-size-fs-bodyvar(--fs-body)
--figure-frame-border-rule-hairvar(--rule-hair)
--figure-frame-border-linevar(--line)
--figure-frame-background-cottonvar(--cotton)

Layout

AspectValue
breakpointsRequired review at 390, 768, 1024 and 1440 px; execution is not implied by this declaration; full column width; wide figures break out of prose to the page width.
wrappingHead wraps under 600 px: tag below title.
textExpansionJapanese captions wrap.

Spacing and rhythm

AspectValue
internal--space-7 frame padding; --space-5 under the head.
external--space-9 above and below in prose.
rhythmInside a section, after the text it supports.

Motion

AspectValue
NoneStatic figures do not move; moving ones are showcases.

Runtime and reuse

  1. Render-only element; mount any registered child enhancements separately. Preserve required Site CSS, fonts, responsive and locale rules from nativeElement.

Accessibility passport

AspectValue
rolefigure, named by its figcaption
nameThe caption
keyboardInteractive parts inside are focusable.
focusIn reading order.
screenReaderReads the title, the figure's text alternative and the caption.
contrastInk on surface 14:1.
targetNot a target.

Content

SlotLengthVoice
title8 wordsWhat it is
caption2 sentencesWhat it shows and where the data comes from

Good: “One contract: Button · Loom Base 1.0.0, MIT · Read from packages/base/contracts when this page is built.”

Bad: “Figure 1”

Japanese: Captions are translated with the page; the screen itself is English UI and the caption says so.

Icons and illustrations

None: this element uses no icon or illustration of its own.

Decisions and exceptions

Usage

79 uses across the built pages (measured by npm run site:system).

Tests

AspectValue
unittests/unit/site-system.test.ts: renders every do and don't example through the registry and checks the classes it owns
visualNot yet: there are no screenshot baselines; the Library page is checked for sideways scroll at 1440 px by tests/site/system.spec.ts
a11ytests/site/system.spec.ts: axe (0 serious or critical) on the element's Library page in light and dark
parityscripts/site/system/check.ts: Library examples are rendered by the same render function the site imports

Figma

not-yet: The Loom Site Figma library is the last stage of the plan; this element is not mapped yet.

Open in Storybook

Start with a conversation about your system.

We read your system, show you what we found, and agree with your team what to fix first.