RVE LogoReact Video EditorDOCS
RVE Pro/Components/Timeline

Timeline

A powerful, modular timeline component for React video editing applications

The RVE Timeline is our take on a React timeline for video editing apps. We wanted something that feels powerful but doesn’t lock you into a specific stack. That’s why the timeline is built to be modular and “drop-in.” You can literally copy the component into your project, hook up a few props, and it’ll run.

Under the hood we use mediabunny, for generating video thumbnails. Beyond that, we’ve tried to keep things lean so you’re not pulling in a ton of libraries just to get a timeline running. The idea is that the component gives you a good foundation (tracks, items, scrubbing, resizing, etc.), but you stay in control of the data and how it plugs into the rest of your editor.

Note

The timeline is the hub of most video editors. It’s a complex system of state and logic that drives nearly everything, which is why we’ve put so much emphasis on it. Right now, the Timeline is actively being worked on with ongoing improvements. A lot of the focus is on performance. Making sure it can handle larger projects smoothly without slowing down.

That said, there are still some limitations. Performance can depend on the browser you’re using, the size of your files, and other factors that aren’t always in our control. This is only going to get better. We’re committed to continually refining the Timeline and rolling out improvements that make it faster, smoother, and easier to work with.

Key Features

  • Multi-track Timeline: Support for unlimited tracks with different media types
  • Drag & Drop: Intuitive item manipulation with magnetic snapping
  • Multiselect & Marquee Selection: Select multiple items with click+drag marquee
  • Zoom Controls: Smooth zooming with mouse wheel and keyboard shortcuts
  • Playback Controls: Play/pause with customizable playback rates
  • Keyboard Shortcuts: Comprehensive hotkey support for efficient editing
  • Undo/Redo: Built-in history management with external integration support
  • Context Menus: Right-click actions for timeline operations
  • Mobile Support: Responsive design with mobile-optimized interactions
  • Theming: CSS custom properties for light/dark/custom themes
  • Splitting: Advanced item splitting with visual feedback
  • Guidelines: Visual alignment helpers during drag operations

Usage Example

import React from 'react';
import Timeline from '@/components/editor/components/advanced-timeline/timeline';
import { TimelineTrack } from '@/components/editor/components/advanced-timeline/types';

const VideoEditor = () => {
  const [tracks, setTracks] = React.useState<TimelineTrack[]>([
    {
      id: 'track-1',
      name: 'Video Track',
      items: [
        {
          id: 'item-1',
          trackId: 'track-1',
          start: 0,
          end: 10,
          type: 'video',
          label: 'Video Clip 1',
          color: '#3b82f6'
        }
      ]
    }
  ]);
  
  const [currentFrame, setCurrentFrame] = React.useState(0);
  const [isPlaying, setIsPlaying] = React.useState(false);
  const [selectedItems, setSelectedItems] = React.useState<string[]>([]);

  return (
    <Timeline
      tracks={tracks}
      totalDuration={30} // 30 seconds
      currentFrame={currentFrame}
      fps={30}
      onFrameChange={setCurrentFrame}
      onTracksChange={setTracks}
      selectedItemIds={selectedItems}
      onSelectedItemsChange={setSelectedItems}
      
      // Playback controls
      isPlaying={isPlaying}
      onPlay={() => setIsPlaying(true)}
      onPause={() => setIsPlaying(false)}
      showPlaybackControls={true}
      
      // UI features
      showZoomControls={true}
      showTimelineGuidelines={true}
      enableTrackDrag={true}
      enableMagneticTrack={true}
      
      // Event handlers
      onItemMove={(itemId, newStart, newEnd, newTrackId) => {
        console.log('Item moved:', { itemId, newStart, newEnd, newTrackId });
      }}
      onItemResize={(itemId, newStart, newEnd) => {
        console.log('Item resized:', { itemId, newStart, newEnd });
      }}
      onDeleteItems={(itemIds) => {
        console.log('Delete items:', itemIds);
      }}
    />
  );
};

Component Structure

Timeline/
├── components/
│   ├── timeline-header/          # Header with controls
│   ├── timeline-content.tsx      # Main timeline area
│   ├── timeline-track.tsx        # Individual track component
│   ├── timeline-item/            # Timeline item components
│   ├── timeline-markers.tsx      # Time markers
│   ├── timeline-guidelines.tsx   # Drag guidelines
│   └── timeline-track-handles.tsx # Track control handles
├── hooks/
│   ├── use-timeline-zoom.ts      # Zoom functionality
│   ├── use-timeline-tracks.ts    # Track management
│   ├── use-timeline-shortcuts.ts # Keyboard shortcuts
│   ├── use-timeline-history.ts   # Undo/redo
│   └── use-timeline-*.ts         # Other specialized hooks
├── stores/
│   ├── use-timeline-store.ts     # Main timeline state
│   └── use-zoom-store.ts         # Zoom state persistence
├── utils/
│   └── gap-utils.ts              # Gap calculation utilities
├── types.ts                      # TypeScript definitions
└── constants.ts                  # Configuration constants

Props

The Timeline component accepts the following props:

PropTypeDefaultDescription
Data
tracksTimelineTrack[]-Required. Array of timeline tracks containing items
totalDurationnumber-Required. Total timeline duration in seconds
currentFramenumber0Current playhead position frame
fpsnumber30Frames per second for timeline calculations
Event Handlers
onFrameChange(frame: number) => void-Called when playhead position changes
onItemMove(itemId: string, newStart: number, newEnd: number, newTrackId: string) => void-Called when an item is moved
onItemResize(itemId: string, newStart: number, newEnd: number) => void-Called when an item is resized
onItemSelect(itemId: string) => void-Called when an item is selected
onDeleteItems(itemIds: string[]) => void-Called when items are deleted
onDuplicateItems(itemIds: string[]) => void-Called when items are duplicated
onSplitItems(itemId: string, splitTime: number) => void-Called when an item is split
onTracksChange(tracks: TimelineTrack[]) => void-Called when tracks are modified
onAddNewItem(item: Partial<TimelineItem> & { trackId: string; start: number; end: number }) => void-Called when a new item is added
Selection
selectedItemIdsstring[][]Array of currently selected item IDs
onSelectedItemsChange(itemIds: string[]) => void-Called when selection changes
UI Controls
showZoomControlsbooleanfalseShow zoom in/out controls
showPlaybackControlsbooleanfalseShow play/pause controls
showTimelineGuidelinesbooleantrueShow alignment guidelines during drag
showUndoRedoControlsbooleanfalseShow undo/redo buttons
showAspectRatioControlsbooleanfalseShow aspect ratio selector
Playback
isPlayingbooleanfalseCurrent playback state
onPlay() => void-Called when play is triggered
onPause() => void-Called when pause is triggered
playbackRatenumber1Current playback speed multiplier
setPlaybackRate(rate: number) => void-Called when playback rate changes
Track Management
autoRemoveEmptyTracksbooleantrueAutomatically remove tracks when they become empty
onAutoRemoveEmptyTracksChange(enabled: boolean) => void-Called when auto-remove setting changes
enableTrackDragbooleantrueAllow dragging items between tracks
enableMagneticTrackbooleantrueEnable magnetic snapping to other items
enableTrackDeletebooleantrueAllow deleting tracks
Behavior
hideItemsOnDragbooleantrue (desktop), false (mobile)Hide other items during drag operations
Undo/Redo (External)
canUndobooleanfalseWhether undo action is available
canRedobooleanfalseWhether redo action is available
onUndo() => void-Called when undo is triggered
onRedo() => void-Called when redo is triggered
Aspect Ratio
aspectRatioAspectRatio-Current aspect ratio setting
onAspectRatioChange(ratio: AspectRatio) => void-Called when aspect ratio changes

Next Steps