UI
Individual Components
Build your own custom player UI using atomic components.
UI Components
If you don't want to use the pre-built PlayerControls, @playerkit/ui exports all of its internal atomic components so you can build your own completely bespoke layout.
Available Components
Here is a list of the exported atomic components:
ProgressBar: The seek bar for navigating the video timeline.TimeDisplay: Displays the current time and duration (e.g.,1:23 / 4:56).ControlButton: A styled button base for play, pause, fullscreen, etc.VolumeControl: The volume slider and mute toggle.SettingsPanel: The settings menu for playback speed, quality, and closed captions.MobileTopBar: A specialized layout component for the top of the video on mobile devices.
Building a Custom Layout
The UI components in @playerkit/ui are pure, headless-compatible presentational components. They do not use React Context internally. You must pass them the player instance and the current playback state.
If you are using @playerkit/react, you can get these from the player hook (useHlsPlayer, useMp4Player, etc.):
import { useHlsPlayer } from "@playerkit/react";
import {
ProgressBar,
TimeDisplay,
VolumeControl,
ControlButton,
IconPlay,
IconPause
} from "@playerkit/ui";
export default function CustomPlayer() {
const { player, state, videoRef, rootRef } = useHlsPlayer({
src: "https://example.com/stream.m3u8"
});
return (
<div ref={rootRef} className="relative w-full aspect-video bg-black">
<video ref={videoRef} className="w-full h-full" />
{/* Custom UI Wrapper */}
<div className="absolute bottom-0 w-full p-4 bg-gradient-to-t from-black/80">
{/* Pass player and state as props */}
<ProgressBar
player={player}
state={state}
progress={state?.progress || 0}
buffered={state?.bufferedPercentage || 0}
duration={state?.duration || 0}
currentTime={state?.currentTime || 0}
/>
<div className="flex items-center gap-4 mt-2 text-white">
<ControlButton onClick={() => player?.togglePlay()}>
{state?.isPlaying ? <IconPause /> : <IconPlay />}
</ControlButton>
<VolumeControl player={player} state={state} />
<TimeDisplay currentTime={state?.currentTime || 0} duration={state?.duration || 0} />
</div>
</div>
</div>
);
}