Build an Editor

Turn an Editframe composition into a small editor with preview, playback, scrubbing, hierarchy, canvas, and timeline controls.

This guide starts with the generated project and adds the pieces an editor needs: a composition, a preview, playback controls, a scrubber, a time readout, and a path to the full hierarchy, canvas, and timeline workbench.

Prerequisites

  • Node.js 22 or later
  • A scaffolded Editframe project. If you need one, follow Getting Started.

The HTML template uses web components. The React template exposes the same elements as React components. The examples below use HTML because the element wiring is visible, then show the React equivalent where the template file differs.

1. Start with a composition

Keep a stable id on the root timegroup. Controls use that id as their target, and the workbench uses it to find the composition.

html
<ef-timegroup id="editor-demo" mode="fixed" duration="5s" class="w-[1920px] h-[1080px] bg-black flex items-center justify-center">
  <ef-text class="text-white text-9xl font-bold">Build an editor</ef-text>
</ef-timegroup>

The generated HTML project already imports @editframe/elements and its stylesheet in src/index.js. In the generated React project, src/Video.tsx imports Timegroup and Text, while src/main.tsx imports the stylesheet and mounts the component with TimelineRoot.

The generated src/main.tsx mounts <TimelineRoot id="root" component={Video} />. Accept its id prop so the root stays addressable by controls and by the React render clone:

tsx
import React from "react";
import { Text, Timegroup } from "@editframe/react";

export function Video({ id }: { id: string }) {
  return (
    <Timegroup id={id} mode="fixed" duration="5s" className="w-[1920px] h-[1080px] bg-black flex items-center justify-center">
      <Text className="text-white text-9xl font-bold">Build an editor</Text>
    </Timegroup>
  );
}

2. Add play, scrub, and time controls

ef-controls provides a shared target to its child controls. The target value is the root timegroup's id. The play and pause buttons are supplied through the play and pause slots on ef-toggle-play.

Interactive example

This bare example supplies its own chrome so the target relationship is explicit. ef-scrubber seeks the target timegroup; ef-time-display reads its current time and duration.

In React, the matching controls are Controls, TogglePlay, Scrubber, and TimeDisplay from @editframe/react. This is a complete Video.tsx replacement for the generated React template; the existing src/main.tsx can keep mounting it through TimelineRoot:

tsx
import React from "react";
import { Controls, Scrubber, Text, TimeDisplay, Timegroup, TogglePlay } from "@editframe/react";

export function Video({ id }: { id: string }) {
  return (
    <>
      <Timegroup id={id} mode="fixed" duration="5s" className="w-[1920px] h-[1080px] bg-black flex items-center justify-center">
        <Text className="text-white text-9xl font-bold">Build an editor</Text>
      </Timegroup>
      <Controls target={id}>
        <TogglePlay>
          <button slot="play">Play</button>
          <button slot="pause">Pause</button>
        </TogglePlay>
        <Scrubber />
        <TimeDisplay />
      </Controls>
    </>
  );
}

Controls forwards its target to the descendant controls. The generated React preview already mounts the composition through TimelineRoot.

3. Preview it

From the project root:

bash
npm start

The start script runs editframe preview. Open the local preview, press Play, drag the scrubber, and confirm the time display changes. Keep the root's width and height classes while you are wiring the editor; the preview needs a sized composition to display a useful canvas.

4. Add the editor workbench

For a full editor shell, put the root timegroup in ef-workbench's default slot. The workbench creates its hierarchy, fitted canvas, timeline, transport, and zoom controls, then points the internal hierarchy and timeline at the root id. Add your own toolbar content through toolbar-start or toolbar-end:

html
<ef-workbench style="width: 100%; height: 100vh; display: block;">
  <span slot="toolbar-start">My editor</span>
  <button slot="toolbar-end" type="button">Save</button>
  <ef-timegroup id="root" mode="fixed" duration="10s" class="w-[1920px] h-[1080px] bg-slate-900">
    <!-- composition content -->
  </ef-timegroup>
</ef-workbench>

If you use the generated composition as the root, adding the workbench attribute to that root timegroup auto-wraps it in a workbench:

html
<ef-timegroup workbench mode="fixed" duration="5s" class="w-[1920px] h-[1080px] bg-black">
  <!-- composition content -->
</ef-timegroup>

Use the default slot when you need a full editor shell. Use the workbench attribute when the generated root should become the editor's composition. The detailed ef-workbench, ef-timeline, and ef-canvas references cover the available panels and attributes.

Troubleshooting

  • If the controls do nothing, check that target="editor-demo" matches the root timegroup's id exactly. In a workbench, use the id of the timegroup inside the canvas.
  • If the timeline has no tracks, give the root timegroup an id and keep the composition elements inside that root. The workbench wires its internal timeline to that id.
  • If the canvas is empty or collapsed, give the workbench a height and give the composition explicit dimensions such as w-[1920px] h-[1080px]; the workbench fits the default-slot composition for you.

Next steps

  • Controls — add volume, mute, fullscreen, loop, and resolution controls.
  • The time model — sequence scenes, contain nested groups, and set durations and FPS.
  • Rendering — render a composition in the browser.
  • Automate rendering — send a project to the Editframe cloud.