ef-workbench is a CSS grid shell with three named slots: hierarchy (left panel), canvas (center), and timeline (bottom). It adds a toolbar row with mode switching (DOM vs canvas render), theme toggle, zoom controls, and export. Pan/zoom state and theme preference are persisted to localStorage.
<ef-workbench style="width: 100%; height: 100vh; display: block;">
<ef-hierarchy slot="hierarchy" target="root" show-header header="Layers"></ef-hierarchy>
<ef-fit-scale slot="canvas">
<ef-timegroup id="root" mode="fixed" duration="10s" class="w-[1920px] h-[1080px] bg-slate-900">
<!-- composition content -->
</ef-timegroup>
</ef-fit-scale>
<ef-timeline slot="timeline" target="root" show-ruler show-playback-controls></ef-timeline>
</ef-workbench>
Alternatively, set the workbench attribute directly on a root ef-timegroup to auto-wrap:
<ef-timegroup workbench mode="fixed" duration="10s" class="w-[1920px] h-[1080px]">
<!-- workbench is created automatically -->
</ef-timegroup>
Render modes:
| Mode | Description |
|---|
dom | Live DOM rendering. ef-fit-scale is paused; the timegroup updates in place. |
canvas | RAF render loop via renderTimegroupToCanvas. Adaptive resolution during motion. |
Attributes
| Attribute | React prop | Type | Default | Description |
|---|
rendering | rendering | boolean | false | True while a native render host (`EF_FRAMEGEN`) owns frame capture — collapses the workbench to just the bare `.stage` (no toolbar/sidebar/ transport/timeline chrome). |
resolution | resolution | string | "1920x1080" | Composition's true rendered resolution, as `"WIDTHxHEIGHT"` (e.g. `"1920x1080"`, `"1080x1920"`). |
Slots
| Slot | Description |
|---|
| (default) | This slot holds the composition. The composition is a light-DOM `<ef-configuration>`, `<ef-canvas>`, or `<ef-timegroup>` element, and the workbench auto-wraps it as needed. |
toolbar-end | Extension point at the right end of the header toolbar, after the built-in theme/export controls. Assign elements with `slot="toolbar-end"`. |
toolbar-start | Extension point at the left end of the header toolbar. Assign elements with `slot="toolbar-start"`. They stay light-DOM children of `<ef-workbench>` (so page CSS and the theme's `--ef-color-*` custom properties still reach them), and hide with the rest of the editor chrome in render mode. |
CSS Custom Properties
| Property | Default | Description |
|---|
--ef-color-danger | #dc2626 | Color for destructive actions and error states. |
--ef-color-hover | #333 | Hover background color for toolbar and zoom buttons. |
--ef-color-success | #059669 | Color for success states in the export popover. |
--ef-color-text-subtle | var(--ef-color-text-muted) | Secondary text color for export popover labels. |
--ef-color-warning | #d97706 | Color for warning and cancelled states. |
--ef-workbench-sidebar-width | 260px | Width of the left hierarchy panel. |
--ef-workbench-timeline-height | 260px | Height of the bottom timeline panel. |
Events
| Event | Detail | Description |
|---|
export-complete | {
/** Omitted when a custom `target` was supplied. */
buffer?: ArrayBuffer;
mimeType: string;
} | This event fires once, when an export finishes successfully, with a `RenderTimegroupToVideoResult` detail value. |
export-error | — | This event fires if an export throws an error. Its detail value holds the thrown error. |
export-progress | {
frame: number;
totalFrames: number;
/** Composition time (seconds) just rendered. */
time: number;
/** Total exported duration (seconds), i.e. `to - from`. */
duration: number;
/** Wall-clock milliseconds since the render started. */
elapsedMs: number;
/**
* Estimated wall-clock milliseconds remaining, from the mean per-frame
* cost so far. `0` before the first frame lands.
*/
estimatedRemainingMs: number;
/**
* Composition seconds rendered per wall-clock second. Above `1` means
* the export is running faster than realtime. `0` before the first
* frame lands.
*/
speedMultiplier: number;
/**
* Live thumbnail of the last captured frame, redrawn in place every
* {@link RenderTimegroupToVideoOptions.progressPreviewInterval} frames.
* The same canvas instance is passed on every progress callback — embed
* it directly (e.g. append it to a status popover) rather than copying.
* Omitted when `progressPreviewInterval` is `0`.
*/
framePreviewCanvas?: HTMLCanvasElement;
} | This event fires repeatedly during an export, with a `RenderProgress` detail value that holds the frame count and the total frame count. |
export-start | — | This event fires once, when {@link EFWorkbenchElement#exportVideo} begins. |
Methods
| Method | Description |
|---|
exportVideo(options?: RenderTimegroupToVideoOptions): Promise<RenderTimegroupToVideoResult> | Renders the composition to an MP4, through an offscreen
{@link createRenderClone} and `renderTimegroupToVideo` call. By
default it renders at this workbench's `resolution`. The live,
interactive preview stays untouched. It dispatches bubbling
`export-start`, `export-progress`, `export-complete`, and
`export-error` events, so surrounding UI can show progress with no
polling.
This method returns the encoded buffer. The toolbar Export button
also downloads the buffer as an `.mp4` file. See
{@link #runToolbarExport} for that download logic. |