Logoreact-timeline-editor
Core Concepts

Basic Usage

Build your first functional timeline editor with multiple tracks and action blocks.

The <Timeline /> component is a controlled component — you manage the data state and the timeline renders it.

Live Preview

Standard Timeline Editor

import React, { useState } from "react";
import {
  Timeline,
  TimelineRow,
  TimelineEffect,
} from "@keplar-404/react-timeline-editor";
import "@keplar-404/react-timeline-editor/dist/react-timeline-editor.css";

const mockData: TimelineRow[] = [
  {
    id: "0",
    actions: [
      { id: "action00", start: 0, end: 2, effectId: "effect0" },
      { id: "action01", start: 3, end: 6, effectId: "effect1" },
    ],
  },
  {
    id: "1",
    actions: [{ id: "action10", start: 1, end: 4, effectId: "effect0" }],
  },
];

const mockEffect: Record<string, TimelineEffect> = {
  effect0: { id: "effect0", name: "Effect 0" },
  effect1: { id: "effect1", name: "Effect 1" },
};

export const EditorBasic = () => {
  const [data, setData] = useState(mockData);

  return (
    <div className="timeline-container">
      <Timeline
        editorData={data}
        effects={mockEffect}
        onChange={(newData) => setData(newData)}
        autoScroll={true}
        style={{ width: "100%", height: "100%" }}
      />
      <style>{`
        .timeline-container {
          border: 1px solid #333;
          border-radius: 6px;
          overflow: hidden;
          background: #1a1a1a;
          width: 100%;
          height: 400px;
        }
        @media (max-width: 768px) {
          .timeline-container {
            height: 300px;
          }
        }
      `}</style>
    </div>
  );
};

Controlled Component Pattern: The onChange callback fires after any drag or resize. Always update your state using the newData parameter to keep the timeline in sync.

Disable Editing

You can lock the entire timeline to prevent any user interaction:

<Timeline disableDrag={true} editorData={data} effects={mockEffect} />

Hide Cursor

Hide the playback cursor line when you don't need it:

<Timeline hideCursor={true} editorData={data} effects={mockEffect} />

Imperative Control via Ref

For programmatic control (play, pause, seek), attach a ref:

import React, { useRef } from "react";
import { Timeline, TimelineState } from "@keplar-404/react-timeline-editor";

export const ControlledTimeline = () => {
  const timelineRef = useRef<TimelineState>(null);

  const handlePlay = () => {
    timelineRef.current?.play({ autoEnd: true });
  };

  const handlePause = () => {
    timelineRef.current?.pause();
  };

  const handleSeek = (seconds: number) => {
    timelineRef.current?.setTime(seconds);
  };

  return (
    <>
      <button onClick={handlePlay}>▶ Play</button>
      <button onClick={handlePause}>⏸ Pause</button>
      <button onClick={() => handleSeek(5)}>Seek to 5s</button>
      <Timeline
        ref={timelineRef}
        editorData={data}
        effects={mockEffect}
        onChange={setData}
      />
    </>
  );
};

On this page