Showcase frame

The one frame for everything that plays or reacts: a head with the claim, the showcase, its playback controls and its honesty caption at the foot.

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

Do and don't

Do: Mini audit

Rendered by showcase-frame.ts

Open example: Showcase frame · Do: Mini audit Use the full-page example to follow page links.

Claim, then the thing that proves it.

Do: Score us

Rendered by showcase-frame.ts

Open example: Showcase frame · Do: Score us Use the full-page example to follow page links.

Same frame.

Do: Existing metadata arrangement

Rendered by showcase-frame.ts

Open example: Showcase frame · Do: Existing metadata arrangement Use the full-page example to follow page links.

Owns the same metadata and lede positions.

Do: Native labelled group

Rendered by showcase-frame.ts

Open example: Showcase frame · Do: Native labelled group Use the full-page example to follow page links.

No extra section/head; implementation owns controls and lifecycle.

Don't: No caption

Rendered by showcase-frame.ts

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

Every showcase says where its data comes from.

Don't: Own controls

Rendered by showcase-frame.ts

Open example: Showcase frame · Don't: Own controls Use the full-page example to follow page links.

One set of playback controls.

Rules

RuleWhyCheck
Preserve native binding, label and caption placement; managed/static bindings never coexist.Shared construction must retain real runtime selectors and readable fallback.Automated: tests/unit/frame-api-compatibility.test.ts
Every self-playing element sits in this frame.One frame, one meaning (D-SITE-008).Automated: scripts/site/system/check-pages.ts (data-pl-controls only inside a frame)

API

PropTypeRequiredDefaultWhat it does
variantframed | nativeNo"framed"Existing section/head or an owned native div/figure root without added chrome.
asdiv | figureNoNative root only; V4/list/screen families keep their semantic contracts.
classNamestringNoExisting native root class list.
langen | jaNoExplicit source language.
staticDemostringNoStatic-only binding, exclusive with demo; constructor never mounts controls.
headingIdstringNoExplicit framed heading ID, default id-title.
leadingClassstringNoExisting class before demo, preserving native ordering.
headClassstringNoExisting inner head class.
afterTitlehtmlNoExisting explanation/source after title inside its inner div.
headMetahtmlNoExisting metadata sibling in demo-head.
ledePlacementinside-head | after-headNo"inside-head"Existing lede location.
dataobjectNoNative scalar data-* only; binding keys reserved. No style/events/arbitrary attrs.
rolegroupNoOptional native group requires an actual name.
labelstringNoNative text name, exclusive with labelledBy.
labelledBystringNoActual native body/caption label IDs.
captionobjectNoCaption props; native figure requires figcaption, div accepts p/span.
afterCaptionhtmlNoExisting content after caption; no generated behavior.
idstringNoRequired framed section ID; optional native ID.
demostringNoManaged data-demo name, exclusive with staticDemo; framed form needs one binding.
titlestringNoRequired framed claim; native form retains body labels.
ledehtmlNoOne line.
bodyhtmlYesThe showcase.
extraClassstringNodemo-<name>.

Contract details

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

Identity

AspectValue
Idshowcase-frame
LayerOrganisms
Categorymedia
OwnerSite system lead
Statusstable
Version1.1.0
Sourceapps/showcase/site/system/organisms/showcase-frame.ts (private repository; the contract and the render function are this one module)
VersionDateChange
1.1.02026-10-29Add existing native-root and legacy-head arrangements; preserve default frame and caller-owned lifecycle.

Use when

  • Every self-playing or interactive element. Why: Readers learn one frame means 'this runs'; one set of controls everywhere (D-SITE-008).

Do not use when

  • For static figures. Why: Figures use the Figure frame.

Anatomy

PartWhat it is
rootFramed section.demo or native div/figure with exclusive managed/static binding; caller IDs are never generated
headFramed only: heading, source/meta slots and explicitly placed lede
bodyThe showcase
controlsNative child implementation owns playback, clocks and lifecycle; this constructor owns no behavior
captionCaption (honesty)

Made of: heading, text, playback-controls, caption.

Used in: academy-lesson, agent-check, autonomy-demo, before-after, contact-form, conversations, cost-calculator, drift-hero, first-90, health-check, jobs-strip, layers-demo, ops-board, proof-shift, read-your-stylesheet, replay, repo-change, score-us, stage-finder, survey.

Variants

VariantWhenWhy
framedShared demo head and body.Default output unchanged.
nativeExisting group/figure has native layout.Constructor owns root, binding, label and caption without another box.

States

StateRendered or not applicable
defaultThe final state.
hoverControls show hover.
focus-visible--focus on controls.
activePlaying.
disabledNot applicable: Controls hide rather than disable.
loadingBuild-time final state until the script runs.
emptyNot applicable: A showcase without data fails the build.
errorNot applicable: Nothing fetched at run time.
currentThe current step named in words.
visitedNot applicable: Not a link.
expandedNot applicable: Does not open.

Tokens

PartToken
frame.background--surface
frame.border-top--rule-frame --ink
--showcase-frame-gap-space-7var(--space-7)
--showcase-frame-margin-top-space-10var(--space-10)
--showcase-frame-margin-top-space-13var(--space-13)
--showcase-frame-padding-space-7var(--space-7)
--showcase-frame-padding-space-9var(--space-9)
--showcase-frame-background-surfacevar(--surface)
--showcase-frame-border-linevar(--line)
--showcase-frame-border-radius-radiusvar(--radius)
--showcase-frame-gap-space-5var(--space-5)
--showcase-frame-gap-space-3var(--space-3)
--showcase-frame-font-size-fs-h3var(--fs-h3)
--showcase-frame-letter-spacing-ls-h2var(--ls-h2)
--showcase-frame-color-ink-2var(--ink-2)
--showcase-frame-font-size-fs-smallvar(--fs-small)
--showcase-frame-font-type-labelvar(--type-label)
--showcase-frame-padding-space-6var(--space-6)
--showcase-frame-color-inkvar(--ink)
--showcase-frame-border-top-rulevar(--rule)
--showcase-frame-border-top-inkvar(--ink)
--showcase-frame-transition-dur-moderatevar(--dur-moderate)
--showcase-frame-transition-ease-standardvar(--ease-standard)
--showcase-frame-font-type-h3var(--type-h3)
--showcase-frame-letter-spacing-ls-h3var(--ls-h3)
--showcase-frame-transition-dur-slowvar(--dur-slow)
--showcase-frame-outline-color-inkvar(--ink)
--showcase-frame-margin-top-space-8var(--space-8)

Layout

AspectValue
breakpointsRequired review at 390, 768, 1024 and 1440 px; execution is not implied by this declaration; columns stack under 768 px; the wrap keeps a 16 px gutter on phones.
wrappingText wraps; nothing scrolls sideways.
textExpansionJapanese runs 20 to 40% longer; headings break between phrases (jaBreaks) and blocks grow downwards.

Spacing and rhythm

AspectValue
internal--space-7 padding.
externalFull width of its section.
rhythmOne per section, after the claim.

Motion

AspectValue
movesThe showcase inside, never the frame.
triggerIts controls or entering view.
durationAs the showcase.
easing--ease-standard
interruptibleAlways.
reducedNo autoplay.
whyThe frame holds still so the content can move.

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
roleFramed section named by its generated heading; native role/name preserve the caller contract
nameExplicit framed heading ID or native body/caption label
keyboardNo listeners or focus changes; child controls retain native behavior
focusNo new focus stop or live announcement
screenReaderRead in source order; decorative weaving is aria-hidden.
contrastInk on cotton 14:1; text on every dye field 4.5:1 or better (checked by check-brand).
targetLinks and buttons are 44 px tall.

Content

SlotLengthVoice
title12 wordsThe claim the showcase proves

Good: “Your stylesheet already knows where the system is loosening.”

Bad: “Demo”

Japanese: From the i18n tables of each showcase.

Icons and illustrations

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

Decisions and exceptions

Usage

67 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.