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}
/>
</>
);
};