npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@playerkit/ui

v0.0.3

Published

React UI components, icons, and themes for video players — progress bar, volume control, settings panel, and customizable theming.

Downloads

221

Readme

@playerkit/ui

Ready-made React UI components for video players — progress bar, volume control, settings panel, and a theme system.

This package gives you the visual controls for a video player. It's designed to work with @playerkit/core (the video engine) and is automatically included when you install @playerkit/react.

# npm
npm install @playerkit/ui react react-dom

# yarn
yarn add @playerkit/ui react react-dom

# pnpm
pnpm add @playerkit/ui react react-dom

# bun
bun add @playerkit/ui react react-dom

Quick Start

Note: This package only provides UI components. If you want a complete working player, use @playerkit/react instead. Use this package only if you're building custom player controls.

import { PlayerControls, formatPlayerTime } from "@playerkit/ui";
import "@playerkit/ui/styles/common.css"; // ← Don't forget the core CSS!

function MyControls({ state, player }) {
  return (
    <PlayerControls
      state={state}
      player={player}
      progress={50}
      buffered={70}
      seekRelative={(percent) => player.seek(percent * state.duration)}
      formatTime={formatPlayerTime}
    />
  );
}

What's Included

| Component | What It Does | | --------------------- | --------------------------------------------------------------- | | 🎛️ PlayerControls | Complete control bar (play, seek, volume, settings, fullscreen) | | 📊 ProgressBar | Shows buffered/filled progress with a draggable slider | | ⏱️ TimeDisplay | Shows current time / duration (e.g. 1:23 / 5:00) | | 🔊 VolumeControl | Volume slider — horizontal or vertical popup | | ⚙️ SettingsPanel | Speed and quality picker with sliding sub-menus | | 🔘 ControlButton | Styled icon button for custom actions | | 📱 MobileTopBar | Top bar with settings, fullscreen, and video fit for mobile |


Installation

# npm
npm install @playerkit/ui react react-dom

# yarn
yarn add @playerkit/ui react react-dom

# pnpm
pnpm add @playerkit/ui react react-dom

# bun
bun add @playerkit/ui react react-dom

@playerkit/core is a direct dependency and will be installed automatically.

You also need React 18+:

npm install react react-dom

Import the CSS

The player UI will not render correctly without the stylesheets. Starting with v0.0.3, the CSS has been split into three focused files so you only load what you need.

Import the stylesheets once in your app depending on the target player format:

// 1. Core styles (always required for player-ui controls)
//    Covers: CSS variables, control bar, progress bar, volume,
//    settings panel, buffering spinner, error overlay, live badge,
//    and center overlay.
import "@playerkit/ui/styles/common.css";

// 2. HLS-specific styles (required for HLS / native <video> element)
//    Covers: native <video> element sizing, object-fit, and
//    background fill within .pk-player.
import "@playerkit/ui/styles/hls.css";

// 3. YouTube-specific styles (required for YouTube iframe player)
//    Covers: .pk-youtube-clip absolute-fill scaling wrapper and
//    .pk-youtube-poster custom poster overlay.
import "@playerkit/ui/styles/youtube.css";

// 4. MP4-specific styles (required for progressive MP4 player)
//    Covers: native <video> element sizing, object-fit, and
//    background fill overrides.
import "@playerkit/ui/styles/mp4.css";

Alternatively, you can import the full, backwards-compatible monolithic bundle (includes all files above):

import "@playerkit/ui/styles";

All CSS classes use the pk- prefix (e.g., pk-controls, pk-progress, pk-volume) so they won't conflict with your existing styles.


Components

PlayerControls

The main control bar. It includes play/pause, seek buttons, progress bar, time display, volume, settings, and fullscreen.

import { PlayerControls, formatPlayerTime } from "@playerkit/ui";

<PlayerControls
  state={playerState} // The player state object
  player={playerInstance} // The player instance (for play/pause/etc.)
  progress={bufferedPercent} // 0–100, how much is buffered
  buffered={bufferedPercent} // 0–100, currently buffered
  seekRelative={(percent) => {}} // Called when user drags the progress bar
  formatTime={(seconds) => string} // Formats seconds into "1:23" or "1:23:45"
  customization={{}} // Show/hide specific controls (optional)
  themeOverrides={{}} // Override CSS colors (optional)
/>;

ProgressBar

A draggable progress bar showing buffered and played sections:

import { ProgressBar } from "@playerkit/ui";

<ProgressBar
  progress={currentTime} // Current time in seconds
  duration={totalDuration} // Total video length in seconds
  buffered={bufferedEnd} // How much is buffered (seconds)
  onSeek={(seconds) => player.seek(seconds)}
  className="" // Optional extra CSS class
/>;

TimeDisplay

Shows current time and duration in a formatted way:

import { TimeDisplay, formatPlayerTime } from "@playerkit/ui";

<TimeDisplay
  currentTime={120} // 2 minutes → "2:00"
  duration={300} // 5 minutes → "5:00"
  formatTime={formatPlayerTime}
  className=""
/>;

Output: 2:00 / 5:00

VolumeControl

import { VolumeControl } from "@playerkit/ui";

<VolumeControl
  volume={0.7} // 0.0 to 1.0
  previousVolume={1} // Volume before muting
  onChange={(value) => player.setVolume(value)}
  onMute={() => player.mute()}
  onUnmute={() => player.unmute()}
  variant="horizontal" // "horizontal" | "vertical"
/>;

SettingsPanel

A settings panel with speed and quality controls. Supports desktop dropdown and mobile bottom sheet:

import { SettingsPanel } from "@playerkit/ui";

<SettingsPanel
  playbackRate={1} // Current speed
  availableRates={[0.25, 0.5, 1, 1.5, 2]} // Available speeds
  onRateChange={(rate) => player.setPlaybackRate(rate)}
  selectedQuality="auto" // "auto" or quality ID
  qualities={
    [
      /* array of quality levels */
    ]
  }
  onQualityChange={(id) => player.setQuality(id)}
  onClose={() => {
    /* close the panel */
  }}
/>;

ControlButton

A styled button that wraps any icon:

import { ControlButton } from "@playerkit/ui";

<ControlButton
  label="Play" // Accessible label
  icon={<svg>...</svg>} // Your SVG icon
  onClick={() => {}} // Click handler
  variant="default" // "default" | "primary"
  active // Highlight state
/>;

MobileTopBar

A top bar for mobile layouts with settings, fullscreen, and fit controls:

import { MobileTopBar } from "@playerkit/ui";

<MobileTopBar
  /* Controls */
  onToggleFullscreen={() => {}}
  onToggleStretch={() => {}}
  /* Settings panel */
  playbackRate={1}
  availableRates={[0.25, 0.5, 1, 1.5, 2]}
  onRateChange={(rate) => {}}
  selectedQuality="auto"
  qualities={[]}
  onQualityChange={(id) => {}}
/>;

Customizing the Look

Theme Overrides

You can change colors and spacing by passing themeOverrides:

<PlayerControls
  state={state}
  player={player}
  progress={50}
  buffered={70}
  seekRelative={fn}
  formatTime={formatPlayerTime}
  themeOverrides={{
    "--pk-accent": "#ec4899", // Pink accent color
    "--pk-surface": "transparent", // Transparent control bar
    "--pk-radius": "12px", // Rounded corners
  }}
/>

Available CSS Variables

Scoping: All CSS variables use the --pk- prefix and are scoped to the .pk-player root element. This means they only affect the player and will not leak into the rest of your application's styles.

| Variable | Default | What It Changes | | ---------------------- | ------------------------- | --------------------------------- | | --pk-accent | #2e3192 | Primary color (buttons, progress) | | --pk-accent-contrast | #ffffff | Text color on accent | | --pk-surface | rgb(2 6 23 / 0.76) | Control bar background | | --pk-border | rgb(148 163 184 / 0.26) | Border color | | --pk-text | #f8fafc | Text color | | --pk-muted | #cbd5e1 | Muted/secondary text | | --pk-radius | 8px | Border radius | | --pk-control-radius | 8px | Control button radius | | --pk-video-bg | #020617 | Video area background |

Hiding Specific Controls

Use the customization prop to show/hide individual controls:

<PlayerControls
  state={state}
  player={player}
  progress={50}
  buffered={70}
  seekRelative={fn}
  formatTime={formatPlayerTime}
  customization={{
    showPlayButton: true, // Show play/pause
    showTimeDisplay: true, // Show time
    showSettings: true, // Show settings gear
    showFullscreen: true, // Show fullscreen toggle
    volumeControl: "vertical", // "horizontal" | "vertical" | "hidden"
  }}
/>

PlayerCustomization Type

The full type definition for the customization prop accepted by PlayerControls and other components:

type PlayerCustomization = {
  /** Show/hide the play/pause button. Default: `true` */
  showPlayButton?: boolean;

  /** Show/hide the current time and duration display. Default: `true` */
  showTimeDisplay?: boolean;

  /** Show/hide the settings gear button. Default: `true` */
  showSettings?: boolean;

  /** Show/hide the fullscreen toggle button. Default: `true` */
  showFullscreen?: boolean;

  /** Show/hide the center tap-to-play overlay. Default: `true` */
  showCenterOverlay?: boolean;

  /** Show/hide the stretch/fit (object-fit) toggle button. Default: `true` */
  showObjectFitButton?: boolean;

  /**
   * Volume slider style.
   * - `"vertical"` — floating vertical popup (default)
   * - `"horizontal"` — inline horizontal slider
   * - `"hidden"` — no volume control rendered
   */
  volumeControl?: "vertical" | "horizontal" | "hidden";

  /** Gap in pixels between buttons in the center overlay. Default: `80` */
  centerOverlayGap?: number;

  /**
   * How the video is fitted inside its container.
   * - `"contain"` — letterbox / pillarbox (default)
   * - `"cover"` — crop to fill
   * - `"fill"` — stretch to fill
   */
  objectFit?: "contain" | "cover" | "fill";

  /** Scale factor applied to the center play icon. Default: `1` */
  centerIconScale?: number;

  /** Mobile-specific overrides */
  mobile?: {
    /** Show center gestures overlay on mobile. Default: `false` */
    showCenterOverlay?: boolean;
  };
};

Custom Icons

You can replace all player icons using the icon provider:

import { PlayerIconProvider, type PlayerIconMap } from "@playerkit/ui";

const myIcons: PlayerIconMap = {
  Play: () => <span>▶</span>,
  Pause: () => <span>⏸</span>,
  Settings: () => <span>⚙️</span>,
  VolumeHigh: () => <span>🔊</span>,
  VolumeLow: () => <span>🔉</span>,
  VolumeOff: () => <span>🔇</span>,
  Maximize: () => <span>⛶</span>,
  Minimize: () => <span>⤡</span>,
};

function App() {
  return (
    <PlayerIconProvider icons={myIcons}>
      <YourPlayer />
    </PlayerIconProvider>
  );
}

CSS Class Reference

All classes follow BEM naming with the pk- prefix:

| Class | Element | | ------------------------- | --------------------------------------------------------------------------- | | pk-player | Root player container | | pk-controls | Control bar | | pk-controls--flush | Control bar without background | | pk-progress | Progress bar wrapper | | pk-progress__track | Progress track | | pk-progress__filled | Played portion | | pk-progress__buffered | Buffered portion | | pk-volume | Volume control | | pk-volume--vertical | Vertical popup volume | | pk-volume__popup | Volume popup container | | pk-icon-button | Icon button | | pk-center-overlay | Center play/pause overlay | | pk-center-btn | Center play/pause button | | pk-center-btn--play | Large play button | | pk-center-btn--seek | Small seek button | | pk-buffering | Buffering overlay | | pk-buffering__spinner | Spinning loader | | pk-live-badge | Live stream indicator | | pk-live-badge--active | Live badge active | | pk-live-badge--behind | Live badge behind edge | | pk-live-dot | Live indicator dot | | pk-live-top | Live badge top position | | pk-time | Time display | | pk-player__video | Video element | | pk-player__clip | Clip container | | pk-player__gradient | Bottom gradient overlay | | pk-tap-layer | Touch tap layer | | pk-seek-to-live | Seek to live button | | pk-seek-to-live--live | Active live state | | pk-seek-to-live--hidden | Hidden state | | pk-seek-feedback | Seek feedback overlay | | pk-seek-feedback--left | Left seek feedback | | pk-seek-feedback--right | Right seek feedback | | pk-center-action | Center action overlay | | pk-error-overlay | Error overlay | | pk-settings-* | All settings panel elements | | pk-settings-dropdown | Desktop dropdown | | pk-settings-sheet | Mobile bottom sheet | | pk-settings-slide | Sliding sub-view | | pk-security-overlay | DevTools security lock overlay | | pk-security-overlay__* | Security lock sub-elements (title, icon, message) | | pk-touch-diagnostic | Touch diagnostic grid overlay | | pk-touch-diagnostic__* | Left, right, and center touch zones | | pk-youtube-clip | Absolute-fill scaling wrapper for the YouTube iframe (youtube.css) | | pk-youtube-poster | Custom poster overlay shown before the YouTube iframe loads (youtube.css) |


TypeScript

import type {
  PlayerControlsProps,
  ProgressBarProps,
  TimeDisplayProps,
  VolumeControlProps,
  SettingsPanelProps,
  ControlButtonProps,
  MobileTopBarProps,
  PlayerIconProps,
  PlayerIconMap,
  IconComponent,
  ThemeVars,
  ThemeConfig,
  ControlsLayout,
  ControlsPreset,
  PlayerThemeName,
  PlayerCustomization,
} from "@playerkit/ui";

Public API

Components:     PlayerControls, ProgressBar, TimeDisplay, MobileTopBar,
                ControlButton, VolumeControl, SettingsPanel

Icons:          PlayerIconProvider, usePlayerIcons, IconPlay, IconPause,
                IconRewind, IconForward, IconVolume, IconVolumeLow,
                IconVolumeHigh, IconVolumeOff, IconMaximize, IconMinimize,
                IconSettings

Utilities:      formatPlayerTime(seconds) → "1:23" or "1:23:45"

Themes:         themes, getThemeConfig(name), getThemeNames()

CSS File → Component Mapping

| CSS file | What it styles | | ------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | common.css | PlayerControls, ProgressBar, TimeDisplay, VolumeControl, SettingsPanel, ControlButton, MobileTopBar (all core controls, variables, buffering spinner, error overlay, live badge, center overlay) | | youtube.css | pk-youtube-clip (YouTube iframe scaling container), pk-youtube-poster (custom poster overlay) | | hls.css | pk-player__video sizing overrides for the native <video> element (object-fit, background fill) | | mp4.css | pk-player__video sizing overrides for the progressive <video> element (identical layout and styles to hls.css) |


License

MIT