SyncedMediaSteps
Accordion-style step sequence driving a synced media panel — process and how-it-works bands.
SyncedMediaSteps renders an ordered sequence of steps as an <ol> of accordion rows. The active row reveals its description and crossfades its media into a panel beside the list. It auto-advances while in view, pauses on hover and focus, and yields to a click.
It has one visual appearance — mediaPosition, autoplay, pauseOnHover, and showStepNumbers are behavior and placement knobs, not distinct variants.
SyncedMediaSteps
Use when: An ordered sequence (a process), each step with its own media — how-it-works bands.
Don't: Peer categories, or a sequence with no media to sync.
<SyncedMediaSteps steps={...} />MediaTabs
Use when: Peer categories the reader picks between, each with its own media.
Don't: The items are an ordered sequence — that's SyncedMediaSteps.
<MediaTabs tabs={...} />Accordion
Use when: An ordered or choose-among sequence with no media to sync.
Don't: Each step needs a synced media panel — that's SyncedMediaSteps.
<Accordion items={...} />Use it for
- A "how it works" or process band where the steps are ordered and each one has its own visual
- Any sequence where the reader should be able to sit still and watch it advance, or take over and click
The sequence-vs-peer split is the load-bearing choice, and it drives a different ARIA contract (the accordion here keeps every trigger in the Tab sequence; MediaTabs uses a roving tabindex) — see Accessibility. Reach for a plain Accordion when there is no media to sync.
Import
import { SyncedMediaSteps } from '@brikdesigns/bds';Default
Map the surfaces and agree what ships first.
Tokens, then components, then pages.
Media is the consumer's responsibility for alt text, loading="lazy", and video poster frames. Inactive media stays mounted so the crossfade has both frames to work with.
Timing
interval sets the dwell time per step and defaults to the --duration-autoplay token (10s). It is deliberately one value read by two consumers: the countdown bar animates over it in CSS, and the component reads the resolved custom property back to set its advance timer — so the bar cannot drift away from the advance.
<SyncedMediaSteps steps={steps} interval="6s" />Accessibility
- Keyboard contract is the accordion pattern, not tabs. Every step trigger is a real
<button>in the page Tab sequence, per the WAI-ARIA APG accordion pattern — "all focusable elements in the accordion are included in the page Tab sequence". A roving tabindex belongs to the tabs pattern. - Each trigger carries
aria-expandedandaria-controls; each panel is aregionlabelled by its trigger. - Collapsed descriptions and inactive media use
visibility: hidden, so they leave both the accessibility tree and the tab order rather than staying readable while invisible. - The countdown bar is
aria-hidden— it is a dwell cue, not a measurement, and carries noprogressbarrole. - Under
prefers-reduced-motion: reduceautoplay is disabled in JS, the countdown is hidden, and the media swap and description reveal are instant. The active step still reads correctly, statically. - The component provides no accessible name of its own; wrap it with a heading in the surrounding page, same as any other content band.
API
| Prop | Type | Default |
|---|---|---|
steps | SyncedMediaStepData[] | — (required) |
activeStep | string | — (uncontrolled) |
onActiveStepChange | (id: string) => void | — |
defaultActiveStep | string | first step's id |
autoplay | boolean | true |
interval | number | string | — (falls back to --bds-synced-media-steps-interval, 10s) |
pauseOnHover | boolean | true |
mediaPosition | 'start' | 'end' | 'end' |
showStepNumbers | boolean | true |
showCountdown | boolean | true |
Inherits all native <div> attributes (className, style, data-*, …).
Each entry in steps is a SyncedMediaStepData: { id: string; title: ReactNode; description?: ReactNode; media: ReactNode }.
Related
- Storybook playground
- Accordion — collapsible sections with no synced media
- Motion tokens —
--duration-autoplay,--duration-xl,--ease-spring-soft - MediaTabs — the peer-category (tabs) sibling
- Display Choice — tabs vs accordion: which one a set of content gets, and the tie-breaks.