Timelinx

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:SS or SMPTE), transport controls (Skip to start, Play/Pause, Skip to end), and zoom buttons (-, +, Fit).
    • Ruler (TimelineRulerV3): Standard 0:00, 0:01, 0:02 second 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.
  • v2 (Classic NLE): Traditional multi-track layout with TimelineToolbarV2 and tick-based TimelineRulerV2.

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

PropTypeDefaultDescription
variant'v3' | 'v2''v3'Timeline layout design variant
classNamestring—Additional CSS class for the root element
showToolbarbooleantrueShow the top toolbar
showRulerbooleantrueShow the timeline ruler and playhead
showStatusBarbooleantrueShow the bottom status bar
pagesPageDefinition[]—Pages/compositions for the V3 page selector
activePagestring—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
emptyStateLabelstring'Upload Media'Text label inside the empty state
isPlayingboolean—Optional external override for playback state
onPlayPause() => void—Optional external play/pause handler

Keyboard Shortcuts

KeyAction
SpacePlay / Pause playback
CCut / Split clip under playhead
Delete / BackspaceRemove 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)

On this page