Element reference
September 14, 2026 · View on GitHub
camelCase composition elements map 1:1 onto entities. Lowercase DOM vocabulary is valid only inside <html> content.
Structure
| Element | What it is |
|---|---|
<stage> | The infinite canvas, and the only valid root. Holds <scene> children, and loose nodes parked beside them. |
<scene> | A clipped, playable frame; owns the timeline its children sit on. Only under <stage>, never nested. |
<group> | Container with a transform; auto-fits its box and its span from its children. No size and no fill of its own. |
<sequence> | Track-like container for back-to-back clips, and where transitions are declared. No transform of its own. |
Nodes
| Element | What it is |
|---|---|
<rect> | A rectangle. Takes paints, strokes, shadows and effects. With mask it clips its parent instead of drawing. |
<text> | Text; its children are the glyphs. Sizes itself to them unless given a box. |
<textRange> | A style override over a run of the parent <text>'s glyphs, by character index. |
<video> | A video clip: a rect whose intrinsic paint is the media src names. |
<image> | A picture: a rect whose intrinsic paint is the media src names. |
<audio> | A clip with a sound and no picture; on the canvas, a waveform box. |
<captions> | A styled, timed transcript of the enclosing scene (or of a transcript file). |
<adjustmentLayer> | Draws nothing; its transform composes onto the clip directly below it, for as long as its own clip lasts. |
<html> | A rect whose paint is real, reactive HTML drawn into the box by the browser. |
<surface> | A rect whose paint is a canvas your ref draws into, sampled every frame. |
Paints
Children of a node, stacked in document order over its intrinsic fill. See paints.md.
| Element | What it is |
|---|---|
<solidPaint> | A solid color; what the fill prop is shorthand for. |
<linearGradientPaint> / <radialGradientPaint> | A gradient; takes <colorStop> children. |
<colorStop> | One gradient stop. Valid only inside a gradient paint. |
<imagePaint> / <videoPaint> | Media painted into another element's box — a rect or a text filled with a picture. |
<htmlPaint> | The paint form of <html>. |
<surfacePaint> | The paint form of <surface>. |
<shaderPaint> | A WGSL fragment shader over the media paint below it, or procedural where there is none. |
Styles and motion
Sub-entity children of the node (or paint) that holds them. See styles.md, animations.md, keyframes.md.
| Element | What it is |
|---|---|
<stroke> | An outline of the parent's box or glyphs. Several stack. |
<shadow> | A drop shadow beneath the parent's silhouette. Several stack. |
<effect> | A CSS-style filter over the parent's rendered pixels. Several stack. |
<animation> | One preset in/out animation of the node holding it. |
<keyframeTrack> | The keyframes of one prop of the element holding it. |
<keyframe> | One keyframe of the track holding it. |
User-defined components are ordinary Solid components; they compose the elements above and carry no runtime cost. Only the elements above produce entities.
Coordinates and sizing
- Coordinates are pixels relative to the parent's box, origin top-left. No percentages, no layout keywords; explicit numbers until the layout engine lands.
xandydefault to0. Size defaults are per element, not inherited from the parent:
| Element | Default box |
|---|---|
<video>, <image>, <adjustmentLayer> | 1920 × 1080 |
<scene> | required — the frame's own size |
<rect>, <html>, <surface> | 100 × 100 |
<audio> | 500 × 150 (the waveform box on the canvas) |
<rect mask> | 500 × 500 |
<text> | fits its glyphs |
<captions> | the preset's — it lays out the caption block against the scene's frame |
<group>, <sequence> | fits its children |
- A
<text>given neitherwidthnorheightsizes itself to what it says; giving it either fixes the box and wraps into it. <group>and<sequence>never take a size: theirs is the union of their children's.- How media pixels map into the box is controlled by
objectFit(default"cover"), never by the box itself. A generated asset's placeholder therefore always has a definite size, even before the asset exists.
Common props
Every node accepts:
| Prop | Type | Default | Meaning |
|---|---|---|---|
id | string | stamped | How the element is addressed — by the editor writing back to it, by capture, by syncTo. Written into your source if you leave it out (see module.md). |
ref | SceneNode variable or (node: SceneNode) => void | none | SolidJS-style ref; receives the element's node when it is created. For <surface>/<surfacePaint> the node's element is the backing canvas (see surface-paint.md). |
name | string | none | Human-readable node name; what labels the node in the editor. |
x, y | number | 0 | Position relative to the parent, px. |
offsetX, offsetY | number | 0 | Render-time translation on top of x/y, px; moves the drawn content without changing the layout box (the channel the slide animations drive). Subpixel values are kept. |
width, height | number | per element | Box size, px — see the table above. |
keepAspectRatio | boolean | absent | Locks the box to its authored proportions: resizing one bound (an editor handle, a layout row) drives the other so the ratio width:height has is kept — or, with neither authored, the ratio the box currently has. |
constrainX | "left" | "right" | "center" | "stretch" | "scale" | "left" | How the element follows its scene's frame when that frame is resized, horizontally — see below. |
constrainY | "top" | "bottom" | "center" | "stretch" | "scale" | "top" | The same vertically. |
rotation | number | 0 | Rotation in degrees. |
scale | number | 1 | Uniform scale about the box origin. Overrides scaleX/scaleY while set. |
scaleX, scaleY | number | 1 | Per-axis scale. |
opacity | number | 1 | 0–1; out-of-range values clamp, like CSS. |
cornerRadius | number | 0 | Uniform corner radius, px. |
cornerRadiusTopLeft, cornerRadiusTopRight, cornerRadiusBottomRight, cornerRadiusBottomLeft | number | cornerRadius | Per-corner radius, px; a corner without one takes cornerRadius, so cornerRadius={20} cornerRadiusTopLeft={0} rounds three corners. |
blendMode | BlendMode | "sourceOver" | How the element composites over what is below it: the canvas blend modes, camelCase — multiply, screen, overlay, darken, lighten, colorDodge, colorBurn, hardLight, softLight, difference, exclusion, hue, saturation, color, luminosity. |
hidden | boolean | absent | Excludes the element from rendering (and its audio from the mix) without removing it: it keeps its place in the timeline and its children. |
start, end, sourceIn, sourceOut | Time | see timing.md | Temporal placement. |
playbackRate | number | 1 | Speed multiplier for the node's local time (see timing.md). |
transition | TransitionSpec | null | none | Transition into the next clip; direct children of <sequence> only (see transitions.md). |
Props are animated by <keyframeTrack> children naming them; preset in/out effects are <animation> children. No prop takes keyframes inline.
Constraints
constrainX and constrainY say what an element does when the frame it sits in is resized — a scene taken from 1920×1080 to 1080×1920, say. Nothing else reads them: a constraint moves nothing at the moment it is written, only the next time the frame changes size.
| Value | constrainX | constrainY |
|---|---|---|
"left" / "top" | Keeps its distance from the left edge — where an element with no constraint stays. | The same from the top edge. |
"right" / "bottom" | Keeps its distance from the right edge, so it travels with it. | The same from the bottom edge. |
"center" | Keeps its position relative to the middle of the frame. | The same vertically. |
"stretch" | Holds both margins, so the element is resized by the frame's width delta. | Holds the top and bottom margins, resizing its height. |
"scale" | Position and width take the frame's horizontal ratio, so the element keeps its share of the frame. | The same vertically. |
Editor state
Three more props are written by the editor and read back on the next mount. They are not part of the composition — nothing rendered or exported depends on them — but the source is the document, so a row resized in the timeline has nowhere else to be remembered:
| Prop | Type | Meaning |
|---|---|---|
selected | boolean | Whether the editor has the element selected. Absent means not. |
clipHeight | number | Height of the element's row in the timeline, px. Absent means the common row height. |
expanded | boolean | Whether the timeline shows the element's keyframe rows below its clip. Absent means collapsed. |
Write them or delete them freely; the editor rewrites its own.