Building Custom Editors
Build video editor interfaces by composing GUI elements. Start with a minimal editor and progressively add features.
Minimal Editor (Preview + Controls)
The simplest functional editor needs only preview and controls:
<div class="h-screen flex flex-col bg-gray-900"><!-- Preview Area --><div class="flex-1 flex items-center justify-center p-8"><ef-preview class="w-full max-w-[1280px] aspect-video bg-black rounded-lg shadow-2xl"><ef-timegroup id="minimal-comp" mode="sequence" class="w-[1920px] h-[1080px]"><ef-timegroup mode="fixed" duration="3s" class="flex items-center justify-center bg-gradient-to-br from-blue-600 to-purple-600"><ef-text duration="3s" class="text-white text-6xl font-bold">Scene 1</ef-text></ef-timegroup><ef-timegroup mode="fixed" duration="3s" class="flex items-center justify-center bg-gradient-to-br from-green-600 to-teal-600"><ef-text duration="3s" class="text-white text-6xl font-bold">Scene 2</ef-text></ef-timegroup></ef-timegroup></ef-preview></div><!-- Controls Bar --><div class="bg-gray-800 border-t border-gray-700 p-4"><ef-controls target="minimal-comp" class="flex items-center gap-4 max-w-4xl mx-auto"><ef-toggle-play><button slot="play" class="w-10 h-10 flex items-center justify-center text-white hover:text-blue-400 transition">▶</button><button slot="pause" class="w-10 h-10 flex items-center justify-center text-white hover:text-blue-400 transition">⏸</button></ef-toggle-play><ef-time-display class="text-white text-sm font-mono min-w-[120px]"></ef-time-display><ef-scrubber class="flex-1"></ef-scrubber><ef-toggle-loop><button slot="off" class="w-10 h-10 flex items-center justify-center text-gray-400 hover:text-white transition">↻</button><button slot="on" class="w-10 h-10 flex items-center justify-center text-green-400 hover:text-white transition">↻</button></ef-toggle-loop></ef-controls></div></div>
Adding Timeline (Preview + Controls + Filmstrip)
Add visual timeline feedback with ef-filmstrip:
<div class="h-screen flex flex-col bg-gray-900"><!-- Preview Area --><div class="flex-1 flex items-center justify-center p-4"><ef-preview class="w-full max-w-[1280px] aspect-video bg-black rounded-lg shadow-2xl"><ef-timegroup id="timeline-comp" mode="sequence" class="w-[1920px] h-[1080px]"><ef-timegroup mode="fixed" duration="2s" class="flex items-center justify-center bg-blue-600"><ef-text duration="2s" class="text-white text-5xl font-bold">Intro</ef-text></ef-timegroup><ef-timegroup mode="fixed" duration="4s" class="relative"><ef-video src="https://assets.editframe.com/bars-n-tone.mp4" sourcein="0s" sourceout="4s" class="absolute inset-0 size-full object-cover"></ef-video><ef-text duration="4s" class="absolute bottom-8 left-8 text-white text-4xl font-bold bg-black/50 px-4 py-2 rounded">Main Content</ef-text></ef-timegroup><ef-timegroup mode="fixed" duration="2s" class="flex items-center justify-center bg-purple-600"><ef-text duration="2s" class="text-white text-5xl font-bold">Outro</ef-text></ef-timegroup></ef-timegroup></ef-preview></div><!-- Controls Bar --><div class="bg-gray-800 border-t border-gray-700 px-4 py-2"><ef-controls target="timeline-comp" class="flex items-center gap-3 max-w-4xl mx-auto"><ef-toggle-play><button slot="play" class="w-8 h-8 text-white">▶</button><button slot="pause" class="w-8 h-8 text-white">⏸</button></ef-toggle-play><ef-time-display class="text-white text-sm font-mono"></ef-time-display><ef-scrubber class="flex-1 h-2"></ef-scrubber><ef-toggle-loop><button slot="off" class="text-gray-400">↻</button><button slot="on" class="text-green-400">↻</button></ef-toggle-loop></ef-controls></div><!-- Timeline Panel --><div class="h-64 bg-gray-900 border-t border-gray-800"><ef-filmstrip target="timeline-comp" pixels-per-ms="0.1"></ef-filmstrip></div></div>
Adding Layers (Preview + Controls + Filmstrip + Hierarchy)
Add layer management with ef-hierarchy:
<div class="h-screen flex bg-gray-900"><!-- Left Sidebar: Layers --><div class="w-64 bg-gray-800 border-r border-gray-700 flex flex-col"><div class="px-4 py-3 border-b border-gray-700"><h3 class="text-white font-semibold">Layers</h3></div><div class="flex-1 overflow-auto"><ef-hierarchy target="layers-comp" class="w-full"></ef-hierarchy></div></div><!-- Main Content --><div class="flex-1 flex flex-col"><!-- Preview Area --><div class="flex-1 flex items-center justify-center p-4"><ef-preview class="w-full max-w-[1280px] aspect-video bg-black rounded-lg"><ef-timegroup id="layers-comp" mode="contain" class="w-[1920px] h-[1080px] bg-black"><ef-video src="https://assets.editframe.com/bars-n-tone.mp4" class="absolute inset-0 size-full object-cover"></ef-video><ef-text duration="8s" class="absolute top-8 left-8 text-white text-5xl font-bold">Title Text</ef-text><ef-text duration="8s" class="absolute bottom-8 right-8 text-white text-sm">© 2024</ef-text></ef-timegroup></ef-preview></div><!-- Controls --><div class="bg-gray-800 border-t border-gray-700 px-4 py-2"><ef-controls target="layers-comp" class="flex items-center gap-3 max-w-4xl mx-auto"><ef-toggle-play><button slot="play" class="w-8 h-8 text-white">▶</button><button slot="pause" class="w-8 h-8 text-white">⏸</button></ef-toggle-play><ef-time-display class="text-white text-sm font-mono"></ef-time-display><ef-scrubber class="flex-1 h-2"></ef-scrubber></ef-controls></div><!-- Timeline --><div class="h-48 bg-gray-900 border-t border-gray-800"><ef-filmstrip target="layers-comp"></ef-filmstrip></div></div></div>
Full-Featured Editor (Using Workbench)
For a complete editor with all features, use ef-workbench:
<ef-workbench class="w-full h-screen"><ef-pan-zoom slot="canvas"><ef-fit-scale><ef-timegroup mode="sequence" class="w-[1920px] h-[1080px]"><ef-timegroup mode="fixed" duration="3s" class="relative"><ef-video src="https://assets.editframe.com/bars-n-tone.mp4" sourcein="0s" sourceout="3s" class="absolute inset-0 size-full object-cover"></ef-video><div class="absolute inset-0 flex items-center justify-center"><ef-text duration="3s" class="text-white text-6xl font-bold bg-black/50 px-8 py-4 rounded-xl">Opening</ef-text></div></ef-timegroup><ef-timegroup mode="fixed" duration="4s" class="relative"><ef-video src="https://assets.editframe.com/bars-n-tone.mp4" sourcein="5s" sourceout="9s" class="absolute inset-0 size-full object-cover"></ef-video><ef-text duration="4s" class="absolute top-12 left-12 text-white text-4xl font-bold">Main Content</ef-text><ef-text duration="4s" class="absolute bottom-12 left-12 text-white text-xl">Subtitle text here</ef-text></ef-timegroup><ef-timegroup mode="fixed" duration="2s" class="flex items-center justify-center bg-gradient-to-br from-purple-900 to-blue-900"><ef-text duration="2s" class="text-white text-6xl font-bold">Thanks!</ef-text></ef-timegroup></ef-timegroup></ef-fit-scale></ef-pan-zoom><ef-hierarchy slot="hierarchy"></ef-hierarchy><div slot="timeline" class="h-full flex flex-col"><ef-controls class="flex items-center gap-2 p-2 border-b border-gray-700 bg-gray-800"><ef-toggle-play><button slot="play" class="px-4 py-2 bg-blue-600 text-white rounded hover:bg-blue-700 transition">Play</button><button slot="pause" class="px-4 py-2 bg-gray-600 text-white rounded hover:bg-gray-700 transition">Pause</button></ef-toggle-play><ef-time-display class="text-sm text-gray-300 font-mono"></ef-time-display><ef-scrubber class="flex-1 mx-4"></ef-scrubber><ef-toggle-loop><button slot="off" class="px-3 py-2 text-gray-400 hover:text-white transition">Loop Off</button><button slot="on" class="px-3 py-2 text-green-400 hover:text-white transition">Loop On</button></ef-toggle-loop></ef-controls><ef-filmstrip class="flex-1" pixels-per-ms="0.08"></ef-filmstrip></div></ef-workbench>
Custom Styling with CSS Parts
Style internal elements using ::part() selectors:
<style>.custom-scrubber::part(scrubber) {background: rgba(255, 255, 255, 0.1);height: 6px;border-radius: 3px;}.custom-scrubber::part(progress) {background: linear-gradient(90deg, #3b82f6, #8b5cf6);border-radius: 3px;}.custom-scrubber::part(handle) {width: 16px;height: 16px;background: white;border: 2px solid #3b82f6;border-radius: 50%;box-shadow: 0 2px 8px rgba(0, 0, 0, 0.3);}.custom-time::part(time) {font-family: 'Monaco', monospace;font-size: 14px;color: #60a5fa;letter-spacing: 0.5px;}</style><div class="bg-gray-900 p-8 rounded-lg"><ef-preview class="w-full max-w-[960px] aspect-video bg-black rounded-lg mx-auto mb-4"><ef-timegroup id="styled-comp" mode="contain" class="w-[1920px] h-[1080px] bg-gradient-to-br from-indigo-600 to-purple-700"><ef-text duration="5s" class="flex items-center justify-center size-full text-white text-7xl font-bold">Custom Styled</ef-text></ef-timegroup></ef-preview><ef-controls target="styled-comp" class="flex items-center gap-4 max-w-2xl mx-auto bg-gray-800 p-4 rounded-lg"><ef-toggle-play><button slot="play" class="w-12 h-12 bg-blue-600 rounded-full text-white text-xl hover:bg-blue-700 transition">▶</button><button slot="pause" class="w-12 h-12 bg-gray-600 rounded-full text-white text-xl hover:bg-gray-700 transition">⏸</button></ef-toggle-play><ef-time-display class="custom-time"></ef-time-display><ef-scrubber class="custom-scrubber flex-1"></ef-scrubber></ef-controls></div>
Split-Panel Layout
Separate preview from composition with side-by-side layout:
<div class="h-screen flex flex-col bg-gray-900"><div class="flex-1 grid grid-cols-2 gap-4 p-4"><!-- Left: Preview --><div class="flex flex-col"><h2 class="text-white text-xl mb-2 font-semibold">Preview</h2><ef-preview class="flex-1 bg-black rounded-lg"><ef-timegroup id="split-target" mode="sequence" class="w-[1920px] h-[1080px]"><ef-timegroup mode="fixed" duration="3s" class="flex items-center justify-center bg-blue-600"><ef-text duration="3s" class="text-white text-5xl font-bold">First</ef-text></ef-timegroup><ef-timegroup mode="fixed" duration="3s" class="flex items-center justify-center bg-green-600"><ef-text duration="3s" class="text-white text-5xl font-bold">Second</ef-text></ef-timegroup></ef-timegroup></ef-preview></div><!-- Right: Composition --><div class="flex flex-col"><h2 class="text-white text-xl mb-2 font-semibold">Composition Structure</h2><div class="flex-1 bg-gray-800 rounded-lg overflow-auto"><ef-hierarchy target="split-target"></ef-hierarchy></div></div></div><!-- Bottom: Controls + Timeline --><div class="border-t border-gray-800"><div class="bg-gray-800 px-4 py-2"><ef-controls target="split-target" class="flex items-center gap-3 max-w-4xl mx-auto"><ef-toggle-play><button slot="play" class="w-8 h-8 text-white">▶</button><button slot="pause" class="w-8 h-8 text-white">⏸</button></ef-toggle-play><ef-time-display class="text-white text-sm font-mono"></ef-time-display><ef-scrubber class="flex-1 h-2"></ef-scrubber></ef-controls></div><div class="h-48 bg-gray-900"><ef-filmstrip target="split-target"></ef-filmstrip></div></div></div>
Design Patterns
Context Bridging
Controls work through DOM ancestry by default. Use ef-controls to bridge contexts when targets are not ancestors:
<!-- Composition --><ef-timegroup id="my-video" mode="contain"><!-- content --></ef-timegroup><!-- Non-adjacent controls --><ef-controls target="my-video"><ef-toggle-play></ef-toggle-play><ef-scrubber></ef-scrubber></ef-controls>
Progressive Enhancement
Build editors incrementally:
- Start with Preview + Controls for basic playback
- Add Filmstrip for visual timeline
- Add Hierarchy for layer management
- Add Workbench for complete editor UI
Responsive Layouts
Use CSS Grid and Flexbox for responsive editor layouts:
<div class="h-screen grid grid-rows-[1fr_auto_200px]"><ef-preview><!-- preview --></ef-preview><ef-controls><!-- controls --></ef-controls><ef-filmstrip><!-- timeline --></ef-filmstrip></div>
Theming
Use CSS custom properties for consistent theming:
:root {--ef-color-bg: #111827;--ef-color-border: #374151;--ef-color-text: #f9fafb;--ef-color-primary: #3b82f6;}
Summary
- Minimal: Preview + Controls for basic playback
- Timeline: Add Filmstrip for visual timeline
- Layers: Add Hierarchy for layer management
- Complete: Use Workbench for full-featured editor
- Custom: Compose elements for custom layouts
- Styling: Use CSS parts for deep customization