Controls & theming
The managed player (and the hosted embed, which runs it) ships a branded, fully skinnable control bar: center play overlay, seek bar, play/pause, volume, live badge + go-live, quality/audio/subtitle menus, Picture-in-Picture, fullscreen, buffering spinner, and branded status cards for the ended, error, pre-play, and waiting-for-live states. It auto-hides during playback and is fully keyboard- and screen-reader-accessible.
Every color, radius, and font is a CSS variable — skin it two interchangeable ways.
1. Pass a theme
Merged over the Oddin defaults; omitted keys keep the brand value:
await createPlayer({
video,
baseUrl,
matchUrn,
credential: { apiKey },
theme: {
accent: '#14b8a6', // play button, seek fill, live dot, focus ring
accentText: '#04201c', // text/icon sitting on the accent
surface: '#0f172a', // control-bar + menu background
logoUrl: 'https://cdn.example.com/logo.svg', // optional corner watermark
},
});2. Or override the CSS variables
Handy for many players at once, dark/light switching, or an existing design system:
.havik-player {
--havik-accent: #14b8a6;
--havik-accent-text: #04201c;
--havik-surface: #0f172a;
--havik-radius: 4px;
}The tokens
theme key | CSS variable | Default (Oddin) | Used for |
|---|---|---|---|
accent | --havik-accent | #E1B600 (gold) | Play button, seek fill, live dot, focus |
accentText | --havik-accent-text | #1B1C23 (navy) | Text/icon on the accent |
background | --havik-bg | #0e0f13 | Letterbox / behind-video background |
surface | --havik-surface | #1B1C23 | Control-bar + menu surface |
surfaceMuted | --havik-surface-muted | #2a2c36 | Hover / active surface |
text | --havik-text | #ffffff | Primary text / icons |
textMuted | --havik-text-muted | #9aa0ad | Secondary text (timestamps, inactive) |
border | --havik-border | rgba(255, 255, 255, 0.1) | Hairline borders |
radius | --havik-radius | 8px | Corner radius for buttons / menus |
fontFamily | --havik-font | system UI stack | Control-bar font |
logoUrl | --havik-logo | — (none) | Optional corner watermark (a URL) |
ODDIN_THEME and the applyTheme(root, theme?) helper are exported from the package root if you want the values directly or need to skin a container yourself.
Status cards & copy
The stopped/pre-play states render branded full-bleed cards — ended, fatal error (with Retry when retryable), pre-play (poster + play CTA), and armed-waiting ("Starting soon…") — so a finished stream never leaves a frozen frame behind a dead play button. They pick up the theme and theme.logoUrl. Customize the copy with endedMessage / errorMessage, or set statusOverlays: false and drive your own UI from the ended/error events.
Opting out
controls: 'native'; // the browser's <video controls> UI
controls: 'none'; // nothing — build your own on the Player APIKeyboard shortcuts with the custom bar: space/k play-pause, m mute, f fullscreen, c captions, l go-live, arrows seek/volume.