Skip to content

Early previewhamur is not on npm yet. The components are being built in the open, follow along on GitHub.

DisplayReact

Media Player

Controls for an app's own <video> or <audio> element.

Rendered by React 19.3.1

Loading React…
import { MediaPlayer } from '@hamur/react/media-player'
import captions from '../../assets/media-player-captions.vtt?no-inline'
import video from '../../assets/media-player-test-pattern.webm'

export default function MediaPlayerExample() {
  return (
    <MediaPlayer.Root className="media-player">
      <MediaPlayer.Media
        className="media-player-media"
        src={video}
        playsInline
        preload="metadata"
      >
        <track id="en" kind="captions" srcLang="en" label="English" src={captions} />
      </MediaPlayer.Media>
      <MediaPlayer.Controls className="media-player-controls">
        <MediaPlayer.Seek className="media-player-seek">
          <MediaPlayer.SeekControl className="media-player-control">
            <MediaPlayer.SeekTrack className="media-player-track">
              <MediaPlayer.SeekBuffered
                className="media-player-buffered"
              />
              <MediaPlayer.SeekIndicator
                className="media-player-indicator"
              />
              <MediaPlayer.SeekThumb className="media-player-thumb" />
            </MediaPlayer.SeekTrack>
          </MediaPlayer.SeekControl>
        </MediaPlayer.Seek>
        <MediaPlayer.PlayButton className="media-player-button">
          <svg className="media-player-icon-play" viewBox="0 0 24 24" aria-hidden="true">
            <path d="M6 4v16l14-8z" />
          </svg>
          <svg className="media-player-icon-pause" viewBox="0 0 24 24" aria-hidden="true">
            <path d="M7 4v16M17 4v16" />
          </svg>
        </MediaPlayer.PlayButton>
        <MediaPlayer.SeekButton
          className="media-player-button"
          amount={-10}
        >
          <svg viewBox="0 0 24 24" aria-hidden="true">
            <path d="M3 12a9 9 0 1 0 3-6.7L3 8M3 3v5h5" />
          </svg>
        </MediaPlayer.SeekButton>
        <MediaPlayer.SeekButton className="media-player-button" amount={10}>
          <svg viewBox="0 0 24 24" aria-hidden="true">
            <path d="M21 12a9 9 0 1 1-3-6.7L21 8M21 3v5h-5" />
          </svg>
        </MediaPlayer.SeekButton>
        <MediaPlayer.MuteButton className="media-player-button">
          <svg className="media-player-icon-volume" viewBox="0 0 24 24" aria-hidden="true">
            <path d="M11 5 6 9H3v6h3l5 4zM16 9a5 5 0 0 1 0 6" />
          </svg>
          <svg className="media-player-icon-muted" viewBox="0 0 24 24" aria-hidden="true">
            <path d="M11 5 6 9H3v6h3l5 4zM22 9l-6 6M16 9l6 6" />
          </svg>
        </MediaPlayer.MuteButton>
        <MediaPlayer.Volume className="media-player-volume">
          <MediaPlayer.VolumeControl className="media-player-control">
            <MediaPlayer.VolumeTrack className="media-player-track">
              <MediaPlayer.VolumeIndicator
                className="media-player-indicator"
              />
              <MediaPlayer.VolumeThumb className="media-player-thumb" />
            </MediaPlayer.VolumeTrack>
          </MediaPlayer.VolumeControl>
        </MediaPlayer.Volume>
        <MediaPlayer.Time className="media-player-time" />
        <MediaPlayer.Time className="media-player-time" type="duration" />
        <MediaPlayer.CaptionsButton className="media-player-button">
          <svg viewBox="0 0 24 24" aria-hidden="true">
            <path d="M3 5h18v14H3zM7 15h4M15 15h2M7 11h2M13 11h4" />
          </svg>
        </MediaPlayer.CaptionsButton>
        <MediaPlayer.PictureInPictureButton
          className="media-player-button"
        >
          <svg viewBox="0 0 24 24" aria-hidden="true">
            <path d="M21 10V4H3v14h7M13 13h8v7h-8z" />
          </svg>
        </MediaPlayer.PictureInPictureButton>
        <MediaPlayer.FullscreenButton className="media-player-button">
          <svg className="media-player-icon-enter" viewBox="0 0 24 24" aria-hidden="true">
            <path d="M8 3H3v5M16 3h5v5M3 16v5h5M21 16v5h-5" />
          </svg>
          <svg className="media-player-icon-exit" viewBox="0 0 24 24" aria-hidden="true">
            <path d="M8 3v5H3M16 3v5h5M3 16h5v5M21 16h-5v5" />
          </svg>
        </MediaPlayer.FullscreenButton>
      </MediaPlayer.Controls>
      <MediaPlayer.Error className="media-player-error" />
    </MediaPlayer.Root>
  )
}
Not measured yetTests passing in React
Not measured yetSize
Not measured yetMemory
Not measured yetSpeed
[N] commits

Installation

npm i @hamur/react

Not on npm yet. The package goes out under the chosen name.

Anatomy

Import the component and assemble its parts:

<MediaPlayer.Root>
  <MediaPlayer.Media />
  <MediaPlayer.Controls>
    <MediaPlayer.Seek>
      <MediaPlayer.SeekControl>
        <MediaPlayer.SeekTrack>
          <MediaPlayer.SeekBuffered />
          <MediaPlayer.SeekIndicator />
          <MediaPlayer.SeekThumb />
        </MediaPlayer.SeekTrack>
      </MediaPlayer.SeekControl>
    </MediaPlayer.Seek>
    <MediaPlayer.PlayButton />
    <MediaPlayer.SeekButton />
    <MediaPlayer.MuteButton />
    <MediaPlayer.Volume>
      <MediaPlayer.VolumeControl>
        <MediaPlayer.VolumeTrack>
          <MediaPlayer.VolumeIndicator />
          <MediaPlayer.VolumeThumb />
        </MediaPlayer.VolumeTrack>
      </MediaPlayer.VolumeControl>
    </MediaPlayer.Volume>
    <MediaPlayer.Time />
    <MediaPlayer.CaptionsButton />
    <MediaPlayer.PictureInPictureButton />
    <MediaPlayer.FullscreenButton />
  </MediaPlayer.Controls>
  <MediaPlayer.Error />
</MediaPlayer.Root>

Examples

Audio

render puts an <audio> element in place of the video: the seek bar, Play, the times, Mute and Volume, with no picture.

MediaPlayerAudio.tsx
import { MediaPlayer } from '@hamur/react/media-player'
import tone from '../../assets/media-player-tone.webm'

export default function MediaPlayerAudioExample() {
  return (
    <MediaPlayer.Root
      className="media-player media-player-audio"
      aria-label="Test tone"
    >
      <MediaPlayer.Media render={<audio />} src={tone} preload="metadata" />
      <MediaPlayer.Controls className="media-player-controls">
        <MediaPlayer.Seek className="media-player-seek">
          <MediaPlayer.SeekControl className="media-player-control">
            <MediaPlayer.SeekTrack className="media-player-track">
              <MediaPlayer.SeekBuffered
                className="media-player-buffered"
              />
              <MediaPlayer.SeekIndicator
                className="media-player-indicator"
              />
              <MediaPlayer.SeekThumb className="media-player-thumb" />
            </MediaPlayer.SeekTrack>
          </MediaPlayer.SeekControl>
        </MediaPlayer.Seek>
        <MediaPlayer.PlayButton className="media-player-button">
          <svg className="media-player-icon-play" viewBox="0 0 24 24" aria-hidden="true">
            <path d="M6 4v16l14-8z" />
          </svg>
          <svg className="media-player-icon-pause" viewBox="0 0 24 24" aria-hidden="true">
            <path d="M7 4v16M17 4v16" />
          </svg>
        </MediaPlayer.PlayButton>
        <MediaPlayer.Time className="media-player-time" />
        <MediaPlayer.Time className="media-player-time" type="duration" />
        <MediaPlayer.MuteButton className="media-player-button">
          <svg className="media-player-icon-volume" viewBox="0 0 24 24" aria-hidden="true">
            <path d="M11 5 6 9H3v6h3l5 4zM16 9a5 5 0 0 1 0 6" />
          </svg>
          <svg className="media-player-icon-muted" viewBox="0 0 24 24" aria-hidden="true">
            <path d="M11 5 6 9H3v6h3l5 4zM22 9l-6 6M16 9l6 6" />
          </svg>
        </MediaPlayer.MuteButton>
        <MediaPlayer.Volume className="media-player-volume">
          <MediaPlayer.VolumeControl className="media-player-control">
            <MediaPlayer.VolumeTrack className="media-player-track">
              <MediaPlayer.VolumeIndicator
                className="media-player-indicator"
              />
              <MediaPlayer.VolumeThumb className="media-player-thumb" />
            </MediaPlayer.VolumeTrack>
          </MediaPlayer.VolumeControl>
        </MediaPlayer.Volume>
      </MediaPlayer.Controls>
      <MediaPlayer.Error className="media-player-error" />
    </MediaPlayer.Root>
  )
}

API reference

79 props across 22 parts, in React syntax. className, style, render are listed once, under Shared props.

CaptionsButtonMediaPlayer.CaptionsButton

Shows and hides the captions or subtitles; named "Show captions" or "Hide captions". Renders a <button>.

CaptionsButton props
PropTypeDefault
nativeButtonWhether the component renders a native <button> element when replacing itbooleantrue
focusableWhenDisabledWhether the button stays focusable while disabled.booleantrue
CaptionsButton data attributes
Data attributeDescription
data-showingPresent while a captions or subtitles track is shown.
data-disabledPresent when the button is disabled.
data-unavailablePresent when the feature is not available for this media or browser.

ControlsMediaPlayer.Controls

Holds the controls; the pointer over it keeps the player from going idle. Not a toolbar: each control is a Tab stop. Renders a <div>.

Controls data attributes
Data attributeDescription
data-idlePresent while the player is playing without activity for idleTimeout.

ErrorMediaPlayer.Error

Says what stopped the media, as an alert, only while there is a media error; the children or the label of the error. Renders a <div>.

Error data attributes
Data attributeDescription
data-errorThe media error.

FullscreenButtonMediaPlayer.FullscreenButton

Enters and exits fullscreen on the Root; named "Enter fullscreen" or "Exit fullscreen". Renders a <button>.

FullscreenButton props
PropTypeDefault
nativeButtonWhether the component renders a native <button> element when replacing itbooleantrue
focusableWhenDisabledWhether the button stays focusable while disabled.booleantrue
FullscreenButton data attributes
Data attributeDescription
data-fullscreenPresent while the player is fullscreen.
data-disabledPresent when the button is disabled.
data-unavailablePresent when the feature is not available for this media or browser.

MediaMediaPlayer.Media

The app's own media element, which the player reads and controls. Every attribute and child passes through as written.; render={<audio />} for audio. Renders a <video>.

MuteButtonMediaPlayer.MuteButton

Mutes and unmutes the media; named "Mute" or "Unmute". Renders a <button>.

MuteButton props
PropTypeDefault
nativeButtonWhether the component renders a native <button> element when replacing itbooleantrue
focusableWhenDisabledWhether the button stays focusable while disabled.booleantrue
MuteButton data attributes
Data attributeDescription
data-mutedPresent while the media is muted.
data-disabledPresent when the button is disabled.
data-unavailablePresent when the feature is not available for this media or browser.

PictureInPictureButtonMediaPlayer.PictureInPictureButton

Enters and exits picture-in-picture; named "Enter picture-in-picture" or "Exit picture-in-picture". Renders a <button>.

PictureInPictureButton props
PropTypeDefault
nativeButtonWhether the component renders a native <button> element when replacing itbooleantrue
focusableWhenDisabledWhether the button stays focusable while disabled.booleantrue
PictureInPictureButton data attributes
Data attributeDescription
data-picture-in-picturePresent while the video is in picture-in-picture.
data-disabledPresent when the button is disabled.
data-unavailablePresent when the feature is not available for this media or browser.

PlayButtonMediaPlayer.PlayButton

Plays the media while it is paused and pauses it otherwise; named "Play" or "Pause". Renders a <button>.

PlayButton props
PropTypeDefault
nativeButtonWhether the component renders a native <button> element when replacing itbooleantrue
focusableWhenDisabledWhether the button stays focusable while disabled.booleantrue
PlayButton data attributes
Data attributeDescription
data-playingPresent while the media is playing.
data-pausedPresent while the media is paused.
data-endedPresent while the media has ended.
data-disabledPresent when the button is disabled.
data-unavailablePresent when the feature is not available for this media or browser.

RootMediaPlayer.Root

Groups all parts of the media player: the app's own media element and the controls bound to it., with the status region as its last child. Renders a <div>.

Root props
PropTypeDefault
volumeThe volume, from 0 to 1.number—
defaultVolumeThe volume written to the element on mount; without it the element's own volume stands.number—
onVolumeChangeEvent handler called when the volume changes, before a part writes it; cancel() skips theChangeHandler<number>—
mutedWhether the media is muted.boolean—
defaultMutedWhether the media is muted on mount; without it the element's own muted stands.boolean—
onMutedChangeEvent handler called when muted changes.ChangeHandler<boolean>—
playbackRateThe playback rate, written to defaultPlaybackRate too so a new source keeps it.number—
defaultPlaybackRateThe playback rate on mount; without it the element's own rate stands.number—
onPlaybackRateChangeEvent handler called when the playback rate changes.ChangeHandler<number>—
textTrackThe id of the shown captions or subtitles track, or null for none.string | null—
defaultTextTrackThe track shown once it exists; without it the browser's automatic selection stands.string | null—
onTextTrackChangeEvent handler called when the shown captions or subtitles track changes.ChangeHandler<string | null>—
onTextTracksChangeEvent handler called with the captions and subtitles tracks, on mount and when one is addedChangeHandler<readonly MediaPlayerTextTrack[]>—
onPlayingChangeEvent handler called after the element started or stopped playing.ChangeHandler<boolean>—
onCurrentTimeChangeEvent handler called after the element's current time changed, in seconds.ChangeHandler<number>—
onFullscreenChangeEvent handler called after the player entered or left fullscreen.ChangeHandler<boolean>—
onPictureInPictureChangeEvent handler called after the video entered or left picture-in-picture.ChangeHandler<boolean>—
onDurationChangeEvent handler called after the element's duration changed, in seconds.ChangeHandler<number>—
onPlayErrorEvent handler called when play() is rejected for another reason than an interruption.((error: unknown, eventDetails: MediaPlayerRootChangeEventDetails) => void)—
onErrorEvent handler called when the element reports a media error.ChangeHandler<MediaPlayerError>—
defaultCurrentTimeThe start position in seconds, applied once at the first loadedmetadata.number0
seekStepThe seconds the arrow-key shortcuts seek by.number5
volumeStepThe volume the arrow-key shortcuts change by.number0.05
keyboardShortcutsWhether the keyboard shortcuts act while focus is inside the player.booleantrue
idleTimeoutThe milliseconds without activity before a playing player is idle; 0 never.number2000
disabledWhether the component should ignore user interaction.booleanfalse
localeThe locale of the times and the volume percent.Intl.LocalesArgument—
labelsThe names and texts of the parts, in English by default.Partial<MediaPlayerLabels>—
actionsRefA ref to imperative actions: play(), pause(), togglePlaying(), seek(time),React.RefObject<MediaPlayerActions | null>—
Root data attributes
Data attributeDescription
data-playingPresent while the media is playing.
data-pausedPresent while the media is paused.
data-endedPresent once the media has ended.
data-loadingPresent while a source is set and its metadata is not loaded.
data-waitingPresent while playback waits for data.
data-seekingPresent while the media is seeking.
data-errorPresent while there is a media error.
data-mutedPresent while the media is muted.
data-fullscreenPresent while the player is fullscreen.
data-picture-in-picturePresent while the video is in picture-in-picture.
data-captionsPresent while a captions or subtitles track is shown.
data-idlePresent while the player is playing without activity for idleTimeout.
data-livePresent while the media is a live stream.
data-disabledPresent when the player is disabled.

SeekMediaPlayer.Seek

The seek bar: Slider's Root with the current time as its value and the duration as its maximum. Disabled until the duration is known and while there is an error. Renders a <div>.

Seek props
PropTypeDefault
disabledWhether the slider should ignore user interaction.booleanfalse
localeThe locale used by Intl.NumberFormat when formatting the value.Intl.LocalesArgument—
orientationThe component orientation.Orientation'horizontal'
stepThe granularity with which the slider can step through values.number1
largeStepThe granularity with which the slider can step through values when using Page Up/Page Down or Shift + Arrow Up/Arrow Down.number10
thumbAlignmentHow the thumb(s) are aligned relative to Slider.Control when the value is at min or max:"center" | "edge" | "edge-client-only"'center'
onValueChangeCallback function that is fired when the slider's value changed.((value: number, eventDetails: SliderRootChangeEventDetails) => void)—
onValueCommittedCallback function that is fired when a value change is committed.((value: number, eventDetails: SliderRootCommitEventDetails) => void)—

SeekBufferedMediaPlayer.SeekBuffered

How far the media is buffered from the current time, as a width (or a height when vertical) and --media-buffered. Place it inside the SeekTrack. Renders a <div>.

SeekBuffered CSS variables
CSS variableDescription
--media-bufferedHow far the media is buffered from the current time, as a percent of the duration.

SeekButtonMediaPlayer.SeekButton

Seeks by amount seconds, clamped to the media; named "Forward {time}" or "Back {time}". Renders a <button>.

SeekButton props
PropTypeDefault
nativeButtonWhether the component renders a native <button> element when replacing itbooleantrue
amountThe seconds to seek by; a negative amount seeks back.number10
focusableWhenDisabledWhether the button stays focusable while disabled.booleantrue
SeekButton data attributes
Data attributeDescription
data-disabledPresent when the button is disabled.
data-unavailablePresent when the feature is not available for this media or browser.

SeekControlMediaPlayer.SeekControl

The clickable, interactive part of the slider. Renders a <div>.

SeekControl data attributes
Data attributeDescription
data-draggingPresent while the user is dragging.
data-orientationIndicates the orientation of the slider.
data-disabledPresent when the slider is disabled.
data-validPresent when the slider is in a valid state (when wrapped in Field.Root).
data-invalidPresent when the slider is in an invalid state (when wrapped in Field.Root).
data-touchedPresent when the slider has been touched (when wrapped in Field.Root).
data-dirtyPresent when the slider's value has changed (when wrapped in Field.Root).
data-focusedPresent when the slider is focused (when wrapped in Field.Root).

SeekIndicatorMediaPlayer.SeekIndicator

Visualizes the current value of the slider. Renders a <div>.

SeekIndicator data attributes
Data attributeDescription
data-draggingPresent while the user is dragging.
data-orientationIndicates the orientation of the slider.
data-disabledPresent when the slider is disabled.
data-validPresent when the slider is in a valid state (when wrapped in Field.Root).
data-invalidPresent when the slider is in an invalid state (when wrapped in Field.Root).
data-touchedPresent when the slider has been touched (when wrapped in Field.Root).
data-dirtyPresent when the slider's value has changed (when wrapped in Field.Root).
data-focusedPresent when the slider is focused (when wrapped in Field.Root).

SeekThumbMediaPlayer.SeekThumb

The seek bar's thumb, with a native <input type="range"> named "Seek" whose value text is "{current} of {duration}". Renders a <div>.

SeekThumb props
PropTypeDefault
disabledWhether the thumb should ignore user interaction.booleanfalse
aria-valuetextA string value forwarded to the [aria-valuetext](https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Reference/Attributes/aria-valuetext) attribute of the input.string—
getAriaLabelA function which returns a string value for the [aria-label](https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Reference/Attributes/aria-label) attribute of the input.((index: number) => string) | null—
getAriaValueTextA function which returns a string value for the [aria-valuetext](https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Reference/Attributes/aria-valuetext) attribute of the input.((formattedValue: string, value: number, index: number) => string) | null—
indexThe index of the thumb which corresponds to the index of its value in thenumber—
inputRefA ref to access the nested input element.React.Ref<HTMLInputElement>—
onBlurA blur handler forwarded to the input.React.FocusEventHandler<HTMLInputElement>—
onFocusA focus handler forwarded to the input.React.FocusEventHandler<HTMLInputElement>—
onKeyDownA keydown handler forwarded to the input.React.KeyboardEventHandler<HTMLInputElement>—
tabIndexOptional tab index attribute forwarded to the input.number—

SeekTrackMediaPlayer.SeekTrack

Contains the slider indicator and represents the entire range of the slider. Renders a <div>.

SeekTrack data attributes
Data attributeDescription
data-draggingPresent while the user is dragging.
data-orientationIndicates the orientation of the slider.
data-disabledPresent when the slider is disabled.
data-validPresent when the slider is in a valid state (when wrapped in Field.Root).
data-invalidPresent when the slider is in an invalid state (when wrapped in Field.Root).
data-touchedPresent when the slider has been touched (when wrapped in Field.Root).
data-dirtyPresent when the slider's value has changed (when wrapped in Field.Root).
data-focusedPresent when the slider is focused (when wrapped in Field.Root).

TimeMediaPlayer.Time

The current time, the duration or the time remaining: the digits, hidden from assistive technology, and a visually hidden long form. Renders a <time>.

Time props
PropTypeDefault
typeWhich time to show: the current time, the duration or the time remaining.MediaPlayerTimeType'current'
Time data attributes
Data attributeDescription
data-typeWhich time is shown.
data-unknownPresent while the duration is unknown.

VolumeMediaPlayer.Volume

The volume slider: Slider's Root from 0 to 1, at 0 while muted. Disabled with data-unavailable where the volume cannot be set. Renders a <div>.

Volume props
PropTypeDefault
stepThe granularity with which the volume changes with the arrow keys and a pointer.number0.05
largeStepThe volume change with Shift and an arrow key, or with Page Up and Page Down.number0.1
disabledWhether the slider should ignore user interaction.booleanfalse
localeThe locale used by Intl.NumberFormat when formatting the value.Intl.LocalesArgument—
orientationThe component orientation.Orientation'horizontal'
thumbAlignmentHow the thumb(s) are aligned relative to Slider.Control when the value is at min or max:"center" | "edge" | "edge-client-only"'center'
onValueChangeCallback function that is fired when the slider's value changed.((value: number, eventDetails: SliderRootChangeEventDetails) => void)—
onValueCommittedCallback function that is fired when a value change is committed.((value: number, eventDetails: SliderRootCommitEventDetails) => void)—

VolumeControlMediaPlayer.VolumeControl

The clickable, interactive part of the slider. Renders a <div>.

VolumeControl data attributes
Data attributeDescription
data-draggingPresent while the user is dragging.
data-orientationIndicates the orientation of the slider.
data-disabledPresent when the slider is disabled.
data-validPresent when the slider is in a valid state (when wrapped in Field.Root).
data-invalidPresent when the slider is in an invalid state (when wrapped in Field.Root).
data-touchedPresent when the slider has been touched (when wrapped in Field.Root).
data-dirtyPresent when the slider's value has changed (when wrapped in Field.Root).
data-focusedPresent when the slider is focused (when wrapped in Field.Root).

VolumeIndicatorMediaPlayer.VolumeIndicator

Visualizes the current value of the slider. Renders a <div>.

VolumeIndicator data attributes
Data attributeDescription
data-draggingPresent while the user is dragging.
data-orientationIndicates the orientation of the slider.
data-disabledPresent when the slider is disabled.
data-validPresent when the slider is in a valid state (when wrapped in Field.Root).
data-invalidPresent when the slider is in an invalid state (when wrapped in Field.Root).
data-touchedPresent when the slider has been touched (when wrapped in Field.Root).
data-dirtyPresent when the slider's value has changed (when wrapped in Field.Root).
data-focusedPresent when the slider is focused (when wrapped in Field.Root).

VolumeThumbMediaPlayer.VolumeThumb

The volume slider's thumb, with a native <input type="range"> named "Volume" whose value text is the locale's percent, or "Muted". Renders a <div>.

VolumeThumb props
PropTypeDefault
disabledWhether the thumb should ignore user interaction.booleanfalse
aria-valuetextA string value forwarded to the [aria-valuetext](https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Reference/Attributes/aria-valuetext) attribute of the input.string—
getAriaLabelA function which returns a string value for the [aria-label](https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Reference/Attributes/aria-label) attribute of the input.((index: number) => string) | null—
getAriaValueTextA function which returns a string value for the [aria-valuetext](https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Reference/Attributes/aria-valuetext) attribute of the input.((formattedValue: string, value: number, index: number) => string) | null—
indexThe index of the thumb which corresponds to the index of its value in thenumber—
inputRefA ref to access the nested input element.React.Ref<HTMLInputElement>—
onBlurA blur handler forwarded to the input.React.FocusEventHandler<HTMLInputElement>—
onFocusA focus handler forwarded to the input.React.FocusEventHandler<HTMLInputElement>—
onKeyDownA keydown handler forwarded to the input.React.KeyboardEventHandler<HTMLInputElement>—
tabIndexOptional tab index attribute forwarded to the input.number—

VolumeTrackMediaPlayer.VolumeTrack

Contains the slider indicator and represents the entire range of the slider. Renders a <div>.

VolumeTrack data attributes
Data attributeDescription
data-draggingPresent while the user is dragging.
data-orientationIndicates the orientation of the slider.
data-disabledPresent when the slider is disabled.
data-validPresent when the slider is in a valid state (when wrapped in Field.Root).
data-invalidPresent when the slider is in an invalid state (when wrapped in Field.Root).
data-touchedPresent when the slider has been touched (when wrapped in Field.Root).
data-dirtyPresent when the slider's value has changed (when wrapped in Field.Root).
data-focusedPresent when the slider is focused (when wrapped in Field.Root).

Shared props

Every part that renders an element takes these.

Shared props
PropType
classNameCSS class applied to the element, or a function that returns a class based on the component's state.string | ((state: State) => string | undefined)
styleStyle applied to the element, or a function that returns a style object based on the component's state.React.CSSProperties | ((state: State) => React.CSSProperties | undefined)
renderAllows you to replace the component's HTML element with a different tag, or compose it with another component.React.ReactElement<unknown, string | React.JSXElementConstructor<any>> | ComponentRenderFn<HTMLProps, State>

Keyboard and accessibility

Keyboard

Keyboard
KeysDoesPart
SpacekPlays or pausesRoot
mMutes or unmutesRoot
cShows or hides the captionsRoot
fEnters or exits fullscreenRoot
ArrowLeftArrowRightSeeks back or forward by seekStep (5 seconds)Root
ArrowUpArrowDownTurns the volume up or down by volumeStep (0.05)Root
HomeEndSeeks to the start or the endRoot
09Seeks to that tenth of the durationRoot
With focus on a control, acts the sameRoot
SpaceEnterOn a button, presses only that buttonPlayButton
On the seek bar, 1 or 10 seconds; Home, End the endsSeekThumb
On the volume slider, 0.05 or 0.1VolumeThumb

Accessibility

What the parts set
PartSetsSo that
Rootrole="group" named "Media player" (labels.player or aria-label), tabindex="-1"the controls are announced as one player, and the player is no extra Tab stop
Roota polite status region as its last childa shortcut says what it did ("Muted", "Captions on"); a press or a slider key does not repeat its own announcement
PlayButtona button named "Play" or "Pause", disabled (still focusable) without a source or after an errorthe name says what a press will do
MuteButtona button named "Mute" or "Unmute"the same for the sound
CaptionsButtona button named "Show captions" or "Hide captions", data-unavailable without a captions trackthe same for the captions
PictureInPictureButtona button named "Enter picture-in-picture" or "Exit picture-in-picture"the same for the floating window
FullscreenButtona button named "Enter fullscreen" or "Exit fullscreen"the same for fullscreen
SeekButtonnamed "Back 10 seconds" or "Forward 10 seconds" from its amountthe direction and the step are read
SeekThumba native <input type="range"> named "Seek", its value text the long time ("1 minute, 5 seconds of 3 minutes")the position is read as a time, not as a number of seconds
VolumeThumba native <input type="range"> named "Volume", its value text a percentagethe level is read as a percentage
SeekBufferedaria-hidden="true"the loaded range is not read
Timea <time> with a visually hidden long form and aria-hidden digits"1:05" is read as "1 minute, 5 seconds"
Errorrole="alert", rendered only while there is an errorthe error is announced when it happens

Focus order

  1. The Root is not a Tab stop; each control is one, in DOM order. The Controls are not a toolbar, because the two sliders use the arrow keys themselves.
  2. A press on the video or on the Controls' background focuses the Root when focus is outside the player, so the keys work after a click.
  3. A control the media disables (PlayButton after an error) keeps focus.