Controls

The <ef-controls> element is a context bridge that allows you to control an <ef-preview> or <ef-workbench> element from anywhere in your application, even when they're not direct ancestors. It proxies playback state, timing information, and other contexts from a target element to its children.

Basic Usage

<ef-preview id="my-preview">
  <ef-timegroup slot="canvas" mode="contain" className="w-[1920px] h-[1080px]">
    <ef-video src="/assets/video.mp4"></ef-video>
  </ef-timegroup>
</ef-preview>

<!-- Controls can be placed anywhere, not inside the preview -->
<ef-controls target="my-preview">
  <ef-toggle-play>
    <button slot="play">Play</button>
    <button slot="pause">Pause</button>
  </ef-toggle-play>
  <ef-scrubber></ef-scrubber>
  <ef-time-display></ef-time-display>
</ef-controls>

How Context Bridging Works

Normally, control elements like <ef-scrubber> and <ef-toggle-play> need to be descendants of an <ef-preview> or <ef-workbench> to access playback context. The <ef-controls> element solves this by:

  1. Finding the target element by its ID
  2. Subscribing to all relevant contexts from that target
  3. Re-providing those contexts to its own children
  4. Keeping all contexts synchronized in real-time

This enables flexible UI layouts where controls can be positioned independently of the video preview.

Learn More: For a detailed explanation of how the target system works and what temporal elements are, see Understanding Temporal Elements.

Attributes

target

DOM: read / write
Type: string

The ID of the element to control, typically an <ef-preview> or <ef-workbench>.

The controls element will look for an element with this ID in the document and bridge its context to child elements.

Example:

<ef-preview id="main-preview">...</ef-preview>
<ef-controls target="main-preview">...</ef-controls>

Proxied Contexts

The <ef-controls> element automatically bridges the following contexts from the target element:

| Context | Type | Description | |---------|------|-------------| | playing | boolean | Whether the video is currently playing | | loop | boolean | Whether the video should loop on completion | | currentTimeMs | number | Current playback time in milliseconds | | durationMs | number | Total duration in milliseconds | | targetTimegroup | EFTimegroup | Reference to the root timegroup | | focusedElement | HTMLElement | Currently focused element for editing | | focusContext | FocusContext | Focus management context |

Child elements of <ef-controls> can read and write to these contexts as if they were direct children of the target element.

Examples

Remote Control Panel

Create a separate control panel that can be positioned anywhere:

<div className="layout">
  <div className="preview-area">
    <ef-preview id="editor-preview">
      <ef-timegroup slot="canvas" mode="contain" className="w-[1920px] h-[1080px]">
        <ef-video src="/video.mp4"></ef-video>
      </ef-timegroup>
    </ef-preview>
  </div>
  
  <div className="control-panel">
    <ef-controls target="editor-preview">
      <div className="flex flex-col gap-4 p-4 bg-gray-800 rounded">
        <h3 className="text-white">Playback Controls</h3>
        
        <div className="flex gap-2">
          <ef-toggle-play>
            <button className="btn" slot="play">▶ Play</button>
            <button className="btn" slot="pause">⏸ Pause</button>
          </ef-toggle-play>
          
          <ef-toggle-loop>
            <button className="btn">🔁 Loop</button>
          </ef-toggle-loop>
        </div>
        
        <ef-scrubber></ef-scrubber>
        <ef-time-display></ef-time-display>
      </div>
    </ef-controls>
  </div>
</div>

Multiple Control Sets

Control the same preview from multiple locations:

<ef-preview id="video-editor">
  <!-- Video content -->
</ef-preview>

<!-- Main controls -->
<ef-controls target="video-editor">
  <ef-scrubber></ef-scrubber>
  <ef-toggle-play>...</ef-toggle-play>
</ef-controls>

<!-- Secondary controls in a different part of the UI -->
<ef-controls target="video-editor">
  <ef-time-display></ef-time-display>
  <ef-toggle-loop>...</ef-toggle-loop>
</ef-controls>

Use controls in a modal or overlay that's outside the normal DOM hierarchy:

<!-- Main video editor -->
<ef-preview id="main-editor">
  <ef-timegroup slot="canvas" mode="contain" className="w-[1920px] h-[1080px]">
    <ef-video src="/video.mp4"></ef-video>
  </ef-timegroup>
</ef-preview>

<!-- Modal rendered at document root -->
<dialog open>
  <h2>Playback Settings</h2>
  <ef-controls target="main-editor">
    <ef-toggle-loop>
      <label>
        <input type="checkbox" /> Loop playback
      </label>
    </ef-toggle-loop>
    <ef-time-display></ef-time-display>
  </ef-controls>
</dialog>

Use Cases

Separated UI Layout

Build layouts where the video preview and controls are in completely different parts of your application:

  • Video player in the main content area
  • Controls in a sticky footer
  • Timeline in a collapsible sidebar
  • Settings in a modal dialog

Portal-Based Rendering

When using React portals, Vue teleports, or similar patterns that render content outside the normal component tree, <ef-controls> maintains the connection to the target element.

Multi-Monitor Editing

Build applications where the video preview is on one screen and the control interface is on another, all controlled through a single set of contexts.

Technical Notes

  • Uses Lit's @lit/context for efficient context updates
  • Automatically subscribes to context changes for real-time synchronization
  • Renders with display: block by default (can be styled with CSS)
  • Uses createRenderRoot() override to render in light DOM
  • Updates are batched for performance

Limitations

  • The target element must have an id attribute
  • The target element must be present in the DOM when controls are initialized
  • Context updates flow both ways: children can modify target state
  • EFPreview - Preview container that can be controlled
  • EFTogglePlay - Playback control for use within ef-controls
  • EFToggleLoop - Loop control for use within ef-controls
  • EFScrubber - Scrubbing control for use within ef-controls
  • EFTimeDisplay - Time display for use within ef-controls