Skip to main content

Design system components

MediaPlayer

Video player with controls over the frame, after streaming players: an optional title at the top left, the time remaining over a hairline progress line with a hover frame preview, and volume, back and forward 10 s, play, captions and full screen. Controls fade while playing and return on pointer, keyboard focus or pause.

Status: beta. Group: media. Markdown version: /design-system/components/media-player.md

When to use

MediaPlayer plays a single video with controls that match the site instead of the browser default. The Garage Junction case study plays its radio spot through it on the radio blue with controlsPosition="below", so the card's own blue band runs on into the section. Pages rebrand it with the --media-player-* custom properties in theming.vars, for example --media-player-backdrop and --media-player-ink on a brand surface.

When not to use

  • Do not use it for background or decorative loops without sound; use a muted autoplay video instead.
  • Do not use it for audio-only media; it is built around a video frame.

Look-alikes

The contract names no look-alike with a deciding condition.

Props

MediaPlayer props
PropTypeDefaultDescriptionRequired
sourcesMediaPlayerSource[]noneMedia files in order of preference; the browser plays the first it supports.Yes
labelstringnoneAccessible name of the media, such as "Garage Junction radio spot".Yes
titlestringnoneTitle shown over the top left of the frame with the controls.No
subtitlestringnoneSecond line under the title, such as an artist or a date.No
posterstringnoneStill image shown before playback starts.No
descriptionIdstringnoneId of an element that describes the media; set as aria-describedby on the video.No
preload"none" | "metadata" | "auto"metadataHow much to load before playback.No
controlsPosition"overlay" | "below"overlayWhere the controls sit: over the bottom of the frame on a scrim, or below it, always visible, for artwork whose bottom edge must stay clear.No
hideSeekPreviewbooleanfalseHide the frame preview shown above the progress line on mouse hover. The preview loads its own copy of the media on first hover.No
childrenReactNodenoneOptional <track> elements; captions or subtitles add a captions toggle.No

Variants

  • Allowed controlsPosition values: overlay, below (default overlay).
  • Allowed preload values: none, metadata, auto (default metadata).

Invalid combinations

The contract records no invalid combinations.

Keyboard

MediaPlayer keyboard behaviour
KeyBehaviour
TabMoves through the playback slider, mute, volume, back, play, forward, captions (when a track exists) and full screen.
GeneralOn the playback slider, Left and Right arrows move 5 s, Page Up and Page Down move 10 s, Home and End jump to the ends.
Enter or SpaceActivates a button.
GeneralThe overlay controls never fade while one of them has keyboard focus; under reduced motion they never fade.

Rules

Every item under When not to use is a MUST NOT. MUST and SHOULD follow RFC 2119.

MediaPlayer rules
LevelRuleHow it is checked
MUSTARIA: The video is named by label and described by descriptionId when given.Not yet verified: no evidence record. WCAG 4.1.2.
MUSTARIA: Controls sit in a group named after the media, such as "Radio spot controls" (translated).Not yet verified: no evidence record. WCAG 4.1.2.
MUSTARIA: Play and mute name the action they will take next; back and forward name the jump; the captions toggle reports aria-pressed.Not yet verified: no evidence record. WCAG 4.1.2.
MUSTARIA: The playback slider reports its position in words through aria-valuetext, such as 0:05 of 0:34; the volume slider reports a localised percentage.Not yet verified: no evidence record. WCAG 4.1.2.
MUSTARIA: Back and forward announce the new position through a polite live region.Not yet verified: no evidence record. WCAG 4.1.2.
MUSTRequired stories produce no axe violations at the configured severity.Automated by npm run test:stories:matrix:ci. WCAG 2.5.8.
MUSTThe accessibility tree (role, name, state) matches the committed snapshot for every required story.Automated by npm run test:stories:matrix:ci. WCAG 1.3.1, 4.1.2.
MUSTThe component remains legible and operable under a real browser forced-colors: active pass.Automated by npm run test:stories:hc.
MUSTEvery documented keyboard interaction works as specified.Not yet verified: no evidence record. WCAG 2.1.1, 2.1.2.
MUSTA human completed an end-to-end accessibility review of this component.Manual review, last on 2026-11-01.
SHOULDName the media with label and link a visible description or caption with descriptionId.Not stated in the contract.
SHOULDPass caption tracks as <track kind="captions"> children whenever the video has speech; the captions toggle appears with them.Not stated in the contract.
SHOULDUse controlsPosition="below" when the artwork's bottom edge carries content, such as a band or a mark, that the overlay would cover.Not stated in the contract.
SHOULDOn a brand backdrop set --media-player-backdrop, and check that the ink keeps 4.5:1 for text and 3:1 for glyphs against it.Not stated in the contract.
SHOULD NOTDo not autoplay it; playback starts from the play control.Not stated in the contract.
SHOULD NOTDo not lighten --media-player-muted-ink on a mid-tone backdrop; the time remaining is text and needs 4.5:1.Not stated in the contract.

Install and import

  • Install: npm install @digitaltableteur/react (version 0.9.1, restricted access on npm).
  • Import: import { MediaPlayer } from "@digitaltableteur/react";
  • Entry point: @digitaltableteur/react/content exports it too.
  • Styles: import @digitaltableteur/react/style.css once at the app boundary.