Timeline Control
Slider control to control the media timeline. Composed with timeline state control
Installation
npx shadcn add @limeplay/timeline-controlAdd Event & Action Bridge
Import the useTimelineStates hook in your existing PlayerHooks component.
import React from "react"
import { usePlaybackStates } from "@/hooks/limeplay/use-playback"
import { usePlayerStates } from "@/hooks/limeplay/use-player"
import { useTimelineStates } from "@/hooks/limeplay/use-timeline"
export const PlayerHooks = React.memo(() => {
usePlayerStates()
usePlaybackStates()
useTimelineStates()
return null
})Add the Store States
import { createPlaybackStore, PlaybackStore } from "@/hooks/limeplay/use-playback"
import { createPlayerStore, PlayerStore } from "@/hooks/limeplay/use-player"
import {
createTimelineStore,
TimelineStore,
} from "@/hooks/limeplay/use-timeline"
export type TypeMediaStore = PlaybackStore &
PlayerStore &
TimelineStore &
{}
export function createMediaStore(initProps?: Partial<CreateMediaStoreProps>) {
const mediaStore = create<TypeMediaStore>()((...etc) => ({
...createPlaybackStore(...etc),
...createPlayerStore(...etc),
...createTimelineStore(...etc),
...initProps,
}))
return mediaStore
}Example Usage
- Compose the timeline slider and handle states
import * as TimelineSlider from "@/components/limeplay/timeline-control"
import { Duration, HoverTime } from "@/components/limeplay/timeline-labels"
export function TimelineSliderControl() {
return (
<div className="relative w-full grow">
<TimelineSlider.Root className="h-1 rounded-full focus-area -focus-area-x-2 -focus-area-y-14">
<TimelineSlider.Track className="overflow-hidden rounded-full">
<TimelineSlider.Progress />
<TimelineSlider.Buffered variant="combined" />
</TimelineSlider.Track>
{/* Seek Cursor */}
<TimelineSlider.Thumb
showWithHover
className="absolute h-8 w-px rounded-full bg-primary/60"
/>
{/* Hover Time Label */}
<TimelineSlider.Thumb
showWithHover
className="top-auto! bottom-[calc(100%+16px)] flex h-auto w-fit bg-transparent text-xs font-medium"
>
<HoverTime />
<Duration className="text-primary/60" />
</TimelineSlider.Thumb>
</TimelineSlider.Root>
</div>
)
}- Use the component in your player.
<TimelineSliderControl />Understanding
The Timeline Control implements a highly composable seek slider following the Event & Action Bridge pattern:
- Event Bridge:
useTimelineStates()updatescurrentTime,duration,progress, andbufferedranges via polling (default 500ms) - Action Bridge: Components use
useTimeline()to callseek()which updatesmedia.currentTime
Live Stream Support
Timeline automatically handles live streams:
- Uses Shaka Player's
seekRange()for proper DVR seeking - Displays live latency
- Adjusts progress calculation for sliding window
Accessibility
- ARIA Slider:
aria-label="Timeline Slider" - Keyboard Navigation: Focus and arrow key support
- Screen Reader: Announces time changes
- Visual Focus: Clear focus indicators
Components
Timeline is built with multiple composable parts.
Root
Main slider container with built-in click/drag seek handling. Provides structural layout and CSS variable-driven height via --lp-timeline-track-height. Visual styles (border-radius, transitions, animations) should be applied by consumers.
API Reference
Prop
Type
Thumb
Positioned indicator. Base provides only positioning via CSS variable --lp-timeline-thumb-position. All visual styles (size, shape, color) must be provided by consumers.
API Reference
Prop
Type
Buffered
Shows buffered ranges. Supports 3 variants: default, combined, from-zero.
API Reference
Prop
Type
Track
Visual track representing full duration. Base provides structural layout and bg-foreground/20 background. Visual styles like rounded-full should be applied by consumers. Extends SliderPrimitive.Track props.
Progress
Filled indicator showing playback progress.