Segmented Timeline Strip
Multi-clip timeline overview built by composing one thumbnail-strip per segment with DOM chrome (active border, dim mask, label, playhead, total duration badge) and click-to-seek.
A horizontal timeline overview that concatenates multiple video segments
end-to-end. Each segment is rendered by a
thumbnail-strip; the wrapper layers DOM chrome on
top — active-segment border, dim mask, segment label, playhead, total
duration badge — and translates click-to-seek into per-segment
coordinates.
Segment widths are proportional to duration. The whole strip fills its
container; no horizontal scrolling. Multiple segments may share one
VideoThumbnailCache (different startOffsets into the same video) or
each carry its own cache (multi-clip projects).
Installation
Pulls thumbnail-strip and video-thumbnail-cache (and transitively
mediabunny) automatically.
One-time setup: add the @ikui registry to your components.json.
{
"registries": {
"@ikui": "https://ik-ui.pages.dev/r/{name}.json"
}
}Then install the component:
pnpm dlx shadcn@latest add @ikui/segmented-timeline-stripUsage
import {
SegmentedTimelineStrip,
type TimelineSegment,
} from "@/components/segmented-timeline-strip";
import { VideoThumbnailCache } from "@/lib/video-thumbnail-cache";const cache = await VideoThumbnailCache.fromUrl(videoUrl)
const { duration } = cache.getMetadata()!
const segDur = duration / 5
const segments: TimelineSegment[] = Array.from({ length: 5 }, (_, i) => ({
id: i,
cache,
duration: segDur,
startOffset: i * segDur,
label: String(i + 1),
}))
<SegmentedTimelineStrip
segments={segments}
currentIndex={currentIndex}
currentTime={video.currentTime - currentIndex * segDur}
onSeek={({ segmentIndex, timeWithinSegment }) => {
video.currentTime = segmentIndex * segDur + timeWithinSegment
}}
/>To wire a video element's timeupdate to the playhead, lift currentTime
into React state and feed the strip the segment-local time (subtract the
current segment's startOffset).
Examples
Wired to a video player
Each segment can instead carry its own VideoThumbnailCache (a multi-clip
project). Lift currentTime from the <video>, feed the strip the
segment-local time, and on onSeek swap the video src when crossing a clip
boundary — here two real clips that auto-advance on ended.
Props
| Prop | Type | Default |
|---|---|---|
segments | TimelineSegment[] | - |
currentIndex | number | - |
currentTime | number | 0 |
onSeek | ({ segmentIndex, timeWithinSegment }) => void | - |
height | number | 64 |
tileWidth | number | 36 |
showTotalDurationBadge | boolean | true |
autoFallback | boolean | true |
placeholderColor | string | "#111827" |
className | string | - |
style | React.CSSProperties | - |