DslRenderer Component
The <DslRenderer> component takes an ElucimDocument and renders it as a fully interactive Elucim scene or presentation — no JSX authoring required.
| Prop | Type | Default | Description |
|---|---|---|---|
dsl | ElucimDocument | required | The DSL document to render |
className | string | — | CSS class for the root wrapper |
style | React.CSSProperties | — | Inline styles for the root wrapper |
theme | ElucimTheme | — | Unified content theme. Inject CSS custom properties for theming. Values can be hex, named colors, or var() references. Same type used by ElucimEditor. |
colorScheme | 'light' | 'dark' | 'auto' | — | Semantic token resolution: injects light or dark CSS variables |
poster | 'first' | 'last' | number | — | Render a static frame instead of an interactive player |
controls | boolean | — | Override the document’s controls setting (Player root only) |
autoPlay | boolean | — | Override the document’s autoPlay setting (Player root only) |
loop | boolean | — | Override the document’s loop setting (Player root only) |
fitToContainer | boolean | false | When true, scene fills parent width and scales proportionally |
onPlayStateChange | (playing: boolean) => void | — | Called when playback starts or stops |
onRenderError | (error: Error) => void | — | Called when a React render error occurs inside the scene tree |
fallback | React.ReactNode | — | Custom UI shown when a render error occurs |
onError | (errors: Array<{path, message}>) => void | — | Callback fired when DSL validation fails |
ref | React.Ref<DslRendererRef> | — | Imperative handle for programmatic control |
import { DslRenderer } from '@elucim/dsl';import type { ElucimDocument } from '@elucim/dsl';
const doc: ElucimDocument = { version: '1.0', root: { type: 'player', width: 800, height: 600, fps: 30, durationInFrames: 90, background: '#0a0a1e', children: [ { type: 'fadeIn', duration: 30, children: [ { type: 'circle', cx: 400, cy: 300, r: 60, stroke: '#4fc3f7', strokeWidth: 3 }, ], }, ], },};
export default function MyAnimation() { return <DslRenderer dsl={doc} style={{ maxWidth: 800 }} />;}Imperative API (DslRendererRef)
Section titled “Imperative API (DslRendererRef)”Attach a ref to DslRenderer for programmatic playback control:
import { useRef } from 'react';import { DslRenderer } from '@elucim/dsl';import type { DslRendererRef } from '@elucim/dsl';
function MyPlayer({ dsl }) { const ref = useRef<DslRendererRef>(null);
return ( <> <DslRenderer ref={ref} dsl={dsl} /> <button onClick={() => ref.current?.play()}>Play</button> <button onClick={() => ref.current?.pause()}>Pause</button> <button onClick={() => ref.current?.seekToFrame(0)}>Reset</button> </> );}DslRendererRef Methods
Section titled “DslRendererRef Methods”| Method | Return | Description |
|---|---|---|
getSvgElement() | SVGSVGElement | null | Access the underlying SVG element |
seekToFrame(frame) | void | Jump to a specific frame |
getTotalFrames() | number | Get the total frame count |
play() | void | Start playback |
pause() | void | Stop playback |
isPlaying() | boolean | Whether currently playing |
Poster Mode
Section titled “Poster Mode”The poster prop renders a single static frame without playback controls — useful for thumbnails, social previews, or print.
<DslRenderer dsl={doc} poster="first" /> {/* Frame 0 */}<DslRenderer dsl={doc} poster="last" /> {/* Final frame */}<DslRenderer dsl={doc} poster={45} /> {/* Frame 45 */}Scene Presets
Section titled “Scene Presets”Presets provide shorthand dimensions so you don’t have to remember exact pixel values:
| Preset | Width | Height | Use case |
|---|---|---|---|
'card' | 640 | 360 | Social cards, thumbnails |
'slide' | 1280 | 720 | Slide decks, presentations |
'square' | 600 | 600 | Social media, avatars |
{ "version": "1.0", "root": { "type": "player", "preset": "card", "durationInFrames": 60, "children": [...] }}Loading from a JSON File
Section titled “Loading from a JSON File”import { DslRenderer } from '@elucim/dsl';import doc from './my-animation.json';
export default function Page() { return <DslRenderer dsl={doc} />;}Automatic Validation
Section titled “Automatic Validation”DslRenderer validates the document before rendering. If the document is invalid, it displays an error message instead of crashing — making it safe to use with user-supplied or AI-generated JSON.
Errors are grouped by node with a collapsible raw JSON view for debugging.
// Invalid document — missing required "version" field<DslRenderer dsl={{ root: { type: 'player' } } as any} />// → Renders an error message describing what's wrongProgrammatic Error Handling
Section titled “Programmatic Error Handling”Use the onError callback to intercept validation failures:
<DslRenderer dsl={doc} onError={(errors) => { errors.forEach(e => console.warn(`${e.path}: ${e.message}`)); }}/>Render Error Handling
Section titled “Render Error Handling”Use onRenderError and fallback to catch React render crashes inside the scene tree:
<DslRenderer dsl={doc} onRenderError={(error) => console.error('Scene crashed:', error)} fallback={<div>Something went wrong rendering this animation.</div>}/>Responsive Rendering
Section titled “Responsive Rendering”Use fitToContainer to make the scene fill its parent container width and scale proportionally:
<div style={{ width: '100%', maxWidth: 960 }}> <DslRenderer dsl={doc} fitToContainer /></div>The SVG viewBox handles resolution-independent scaling — no CSS transforms needed.
Color Scheme
Section titled “Color Scheme”The colorScheme prop controls which default token values are injected (light or dark palette):
<DslRenderer dsl={doc} colorScheme="dark" /> {/* Dark palette defaults */}<DslRenderer dsl={doc} colorScheme="light" /> {/* Light palette defaults */}<DslRenderer dsl={doc} colorScheme="auto" /> {/* Detect from background luminance */}When set to "light" or "dark", the value is authoritative — it directly selects the palette without luminance detection. This is the recommended approach when theme values include CSS var() references, since var() strings can’t be parsed for luminance at render time.
When set to "auto" (or omitted), the renderer detects the background color’s luminance and selects the appropriate palette. This only works with resolved color values (hex, rgb), not var() references.
Theme Tokens
Section titled “Theme Tokens”The theme prop injects CSS custom properties onto the renderer wrapper. Each key becomes --elucim-{key}:
<DslRenderer dsl={doc} theme={{ foreground: '#ffeedd', background: '#2d1a0e', accent: '#ff6b35', }}/>Custom keys are supported — any key/value pair is converted to a CSS custom property. This is useful for embedding Elucim scenes in themed host pages.
Using $token syntax in DSL documents
Section titled “Using $token syntax in DSL documents”Any color field in a DSL document can reference theme tokens using $token syntax. This lets a single JSON document adapt to any host theme:
{ "type": "circle", "cx": 200, "cy": 200, "r": 80, "stroke": "$accent", "fill": "$surface"}At render time, "$accent" resolves to var(--elucim-accent, #4fc3f7) — using the host’s CSS value if set, or falling back to a default.
See Themes → Semantic Color Tokens for the full token reference.
Accessibility
Section titled “Accessibility”Reduced Motion
Section titled “Reduced Motion”Elucim respects the prefers-reduced-motion media query. When the user has requested reduced motion, the Player component skips animations and immediately shows the final frame.
This applies to both autoPlay scenes (which start at the final frame) and manual play triggers (which jump to the end instead of animating).
Use the useReducedMotion() hook in your own components to match this behavior:
import { useReducedMotion } from '@elucim/core';
function MyComponent() { const reducedMotion = useReducedMotion(); // true when prefers-reduced-motion: reduce is active // Updates reactively if the user changes their preference}Error Colors
Section titled “Error Colors”Error and validation UIs use semantic CSS custom properties (--elucim-error, --elucim-warning, --elucim-surface) with hardcoded fallbacks. This means error displays automatically adapt to your theme while remaining readable without one.
Presentations
Section titled “Presentations”If the root node is a presentation, the renderer outputs a full slide deck with navigation, transitions, and optional presenter notes — all driven by the JSON:
import { DslRenderer } from '@elucim/dsl';import presentation from './calculus-explained.json';
<DslRenderer dsl={presentation} className="my-deck" />