Timeline
Modern frame-accurate video timeline component with CapCut-style V3 layout, editing actions, transport, and thumbnails
Live Example
Loading...
Overview
TimelineLayout provides an end-to-end, fully functional timeline editor surface with two variants:
v3(Default / Modern): CapCut and Canva-inspired editing surface featuring:- Toolbar (
TimelineToolbarV3): Quick Cut (Scissors /C), Delete (Trash /Del), composition/page selector dropdown, current/total timecode (M:SSorSMPTE), transport controls (Skip to start, Play/Pause, Skip to end), and zoom buttons (-,+,Fit). - Ruler (
TimelineRulerV3): Standard0:00,0:01,0:02second marks with subtle half-second cadence dots and a white geometric flat-topped playhead (RulerPlayheadV3). - Clips (
Clip): Full-bleed video thumbnail strip background with a floating translucent pill label chip for readability. - Empty State (
TimelineEmptyState): Clean dashed upload dropzone displayed when no clips or tracks exist.
- Toolbar (
v2(Classic NLE): Traditional multi-track layout withTimelineToolbarV2and tick-basedTimelineRulerV2.
You can also import TimelineLayoutV3 directly as a typed shorthand.
Usage
import { TimelineLayout, TimelineProvider, MediaAssetsProvider } from '@timelinx/ui';
import { TimelineEngine } from '@timelinx/react';
import { createTimeline, createTimelineState, toFrame, frameRate } from '@timelinx/core';
function Editor() {
const engine = useMemo(
() =>
new TimelineEngine({
initialState: createTimelineState({
timeline: createTimeline({
id: 'tl-1',
name: 'My Timeline',
fps: frameRate(30),
duration: toFrame(9000),
}),
}),
}),
[],
);
return (
<MediaAssetsProvider value={{ getThumbnailUrl: (assetId) => `/thumbnails/${assetId}.jpg` }}>
<TimelineProvider engine={engine} initialPpf={10}>
<TimelineLayout
variant="v3"
pages={[
{ id: 'page-1', name: 'Page 1' },
{ id: 'page-2', name: 'Page 2' },
]}
activePage="page-1"
onUpload={() => alert('Upload clicked')}
/>
</TimelineProvider>
</MediaAssetsProvider>
);
}Props
| Prop | Type | Default | Description |
|---|---|---|---|
variant | 'v3' | 'v2' | 'v3' | Timeline layout design variant |
className | string | — | Additional CSS class for the root element |
showToolbar | boolean | true | Show the top toolbar |
showRuler | boolean | true | Show the timeline ruler and playhead |
showStatusBar | boolean | true | Show the bottom status bar |
pages | PageDefinition[] | — | Pages/compositions for the V3 page selector |
activePage | string | — | Active page ID |
onPageChange | (pageId: string) => void | — | Callback fired when switching pages |
timeFormat | 'mss' | 'timecode' | 'mss' | Timecode counter display format |
onUpload | () => void | — | Callback when clicking the empty state upload button |
emptyStateLabel | string | 'Upload Media' | Text label inside the empty state |
isPlaying | boolean | — | Optional external override for playback state |
onPlayPause | () => void | — | Optional external play/pause handler |
Keyboard Shortcuts
| Key | Action |
|---|---|
Space | Play / Pause playback |
C | Cut / Split clip under playhead |
Delete / Backspace | Remove selected clips |
+ / - | Zoom in / Zoom out |
← / → | Nudge playhead ±1 frame (±10 with Shift) |
↑ / ↓ | Nudge selected clip ±1 frame |
Architecture
TimelineLayout connects the engine, selection, transport loop, and provisional drag state through TimelineProvider:
TimelineLayout (variant="v3")
├── TimelineToolbarV3 (Cut, Delete, Page Selector, Transport, Zoom)
├── TimelineRulerV3 (Canvas 0:00 marks, half-sec dots, RulerPlayheadV3)
└── TimelineTrackAreaV2 (Scrollable tracks)
├── TrackRow × N
│ ├── TrackHeader (sticky left controls)
│ └── TrackBody (clips with thumbnail backgrounds + chips)
└── (or TimelineEmptyState when empty)