Render these inside Player.Root, next to a Media.Video or Media.Audio.
Seekbar.Buffer and Seekbar.Progress set their own width from --buffer-percent and --progress-percent, and the thumb positions itself, so your CSS only handles how they look. The track still needs a size.
Parts accept the attributes of the element they render, plus a ref, except where noted. Every part that renders an element also sets the media state attributes. Passing aria-label replaces a default label.
Seekbar.Root
renders <div role="slider">
The interactive timeline. Click or drag to seek. If the media was playing, it pauses during a drag and resumes on release.
It can take keyboard focus and keeps aria-valuenow, aria-valuemax and aria-valuetext up to date. Its default aria-label is "Video player slider". It is always position: relative; touch-action: none.
Prop
Type
Default
Description
skipInterval
number
5
Seconds to skip per arrow key press. At least 1. Fractions are rounded down, and anything else throws a ReactMediaKitError.
Data attribute
Description
data-dragging
A pointer is pressed on the seekbar, for a click or a drag. Removed on release.
CSS variable
Description
--progress-percent
How much has played, as a plain number from 0 to 100, such as 42.50. Use calc(var(--progress-percent) * 1%) to turn it into a percentage length. The parts inside use it.
--buffer-percent
How much has buffered, in the same format. It stays unset until the first buffering or seek update after the seekbar mounts, so read it with a fallback: var(--buffer-percent, 0). When nothing is buffered, it matches the current position.
Your onKeyDown, onPointerDown, onPointerMove and onLostPointerCapture handlers run before the built-in ones; call event.preventDefault() in one to skip its built-in behavior.
Seekbar.Track
renders <div>
The rail. It holds Seekbar.Buffer, Seekbar.Progress and Seekbar.Thumb. It is position: relative and isolation: isolate, so the thumb’s high z-index doesn’t cover other content on the page. Give it a size, but don’t change its position.
Seekbar.Buffer
renders <div>
The buffered range, inside Seekbar.Track. Its width follows --buffer-percent, and it sits below Seekbar.Progress. It is position: absolute; height: 100% with an inline width, so don’t set those in CSS.
Seekbar.Progress
renders <div>
The played range, inside Seekbar.Track. Its width follows --progress-percent, and it sits above Seekbar.Buffer. It is position: absolute; height: 100% with an inline width, so don’t set those in CSS.
Seekbar.Thumb
renders <div>
The handle at the current position. It sits inside a full-size wrapper that moves it along the track with --progress-percent. className, ref and other <div> attributes are applied to the thumb itself.
The thumb is centered with an inline transform, so a transform in your CSS has no effect. Use scale, translate or rotate instead. The wrapper ignores pointer events, and the thumb inherits that.
CSS variable
Description
--seekbar-thumb-z-index
Sets the z-index of the wrapper around the thumb. Defaults to 9999.
Keyboard interactions
Active while the seekbar has focus.
Key
Action
←Left arrow↓Down arrow
Skip back by skipInterval seconds.
→Right arrow↑Up arrow
Skip forward by skipInterval seconds.
Home
Seek to the start.
End
Seek to the end.
Media state attributes
Five of these describe loading, and exactly one of them is set at a time. The other three mark features the browser lacks. Use them to hide controls that can’t work, or to style the player while it loads.
Data attribute
Description
data-media-pending
Loading hasn’t started. This is the initial state.
data-media-loading
The media has started loading.
data-media-metadata-loaded
The duration and dimensions are known, but there isn’t enough data to play yet.
data-media-playable
The media can play. It stays set if playback later stalls to buffer.
data-media-error
The media element reported an error, such as a network or decoding failure. A blocked play() call doesn’t set it; use onError for that.
data-fullscreen-unsupported
The browser can’t go fullscreen, or support hasn’t been detected yet.
data-pip-unsupported
Picture-in-picture isn’t available, such as for audio, or support hasn’t been detected yet.
data-volume-change-unsupported
The browser doesn’t let scripts set the volume, such as on iOS, or support hasn’t been detected yet.