MediaTabs
Peer tabs driving a synced media panel — the home Services and Industries bands.
MediaTabs renders a set of peer categories as a TabBar rail; the active tab reveals its description and crossfades its media into a synced panel. It auto-advances while in view, pauses on hover and focus, and yields to a click or keypress.
It has one visual appearance — orientation, mediaPosition, variant, autoplay, and pauseOnHover are behavior and placement knobs, not distinct variants.
MediaTabs
Use when: Peer categories, each with its own media — the home Services / Industries bands.
Don't: An ordered sequence (a process), or peers with no media to sync.
<MediaTabs tabs={...} />SyncedMediaSteps
Use when: An ordered sequence (a process) where each step drives its own media.
Don't: Peer categories the reader picks between — that's MediaTabs.
<SyncedMediaSteps steps={...} />TabBar
Use when: Peer categories with no media panel to sync.
Don't: Each tab needs a synced media panel — that's MediaTabs.
<TabBar items={...} />Use it for
- The home "Services" (Marketing / Back-office) and "Industries" (Dental / Real Estate / Small Business) bands — switching between peer categories, each with its own media
- Any tabbed band where the reader should be able to sit still and watch it advance, or take over with the mouse or keyboard
The peer-vs-sequence split is the load-bearing choice, and it drives a different ARIA contract (tabs use a roving tabindex; the accordion behind SyncedMediaSteps keeps every trigger in the Tab sequence) — see Accessibility. Reach for a plain TabBar when there is no media to sync.
Import
import { MediaTabs } from '@brikdesigns/bds';Default
Campaigns, content, and the site that carries them.
Intake, scheduling, billing — wired so the front of house can move.
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 tab and defaults to the --duration-autoplay token (10s). It is deliberately one value read by two consumers: the progress cue animates over it in CSS, and the component reads the resolved custom property back to set its advance timer — so the cue cannot drift away from the advance.
<MediaTabs tabs={tabs} interval="6s" />Accessibility
- Keyboard contract is the WAI-ARIA tabs pattern, delegated to
TabBar. The rail exposes exactly one tab in the page Tab sequence (roving tabindex); Arrow / Home / End move focus and activate — Left/Right when horizontal, Up/Down whenorientation="vertical". - Each tab is a real
role="tab"<button>carryingaria-selectedandaria-controls; each panel is arole="tabpanel"labelled by its tab, hidden while inactive. TabBargains this contract only when its items carrycontrols, so existing label-only tab bars keep their current behaviour.- The progress cue is
aria-hidden— it is a dwell cue, not a measurement, and carries noprogressbarrole. - Under
prefers-reduced-motion: reduceautoplay is disabled in JS, the progress cue is hidden, and the media swap and description reveal are instant. The active tab 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 |
|---|---|---|
tabs | MediaTabData[] | — (required) |
activeTab | string | — (uncontrolled) |
onActiveTabChange | (id: string) => void | — |
defaultActiveTab | string | first tab's id |
autoplay | boolean | true |
interval | number | string | — (falls back to --bds-media-tabs-interval, 10s) |
pauseOnHover | boolean | true |
orientation | 'horizontal' | 'vertical' | 'vertical' |
mediaPosition | 'start' | 'end' | 'end' |
variant | 'text' | 'text-underline' | 'tab' | 'box' | 'tab' |
showProgress | boolean | true |
Inherits all native <div> attributes (className, style, data-*, …).
Each entry in tabs is a MediaTabData: { id: string; label: string; description?: ReactNode; media: ReactNode; disabled?: boolean }.
Related
- Storybook playground
- SyncedMediaSteps — the ordered-sequence (accordion) sibling
- TabBar — the tab rail MediaTabs nests
- Motion tokens —
--duration-autoplay,--duration-xl,--ease-spring-soft - Display Choice — tabs vs accordion: which one a set of content gets, and the tie-breaks.