Docs
Custom element quickstart
Write a Node subclass with @vidova/2d, implement animateIn and animate, then place it with component create and timeline_edit addClip.
This path assumes Vidova is running, Local MCP is on, and a project is open in the editor. Install steps are on the MCP overview.
1. Write the class
The exported class name must match componentName. animate() is the timeline entry point. animateIn() is the intro.
import { Node, NodeProps, Txt, signal, initial, colorSignal } from '@vidova/2d';
import {
SignalValue,
SimpleSignal,
ColorSignal,
PossibleColor,
easeOutCubic,
type ThreadGenerator,
} from '@vidova/core';
export interface HelloTitleProps extends NodeProps {
label?: SignalValue<string>;
textColor?: SignalValue<PossibleColor>;
textSize?: SignalValue<number>;
}
export class HelloTitle extends Node {
@initial('Hello')
@signal()
public declare readonly label: SimpleSignal<string, this>;
@initial('#ffffff')
@colorSignal()
public declare readonly textColor: ColorSignal<this>;
@initial(48)
@signal()
public declare readonly textSize: SimpleSignal<number, this>;
public constructor(props?: HelloTitleProps) {
super({ ...props });
this.add(
<Txt
text={() => this.label()}
fill={() => this.textColor()}
fontSize={() => this.textSize()}
fontFamily="Inter Variable"
fontWeight={600}
/>,
);
}
public *animateIn(duration: number = 0.4): ThreadGenerator {
this.opacity(0);
yield* this.opacity(1, duration, easeOutCubic);
}
public *animate(duration?: number): ThreadGenerator {
yield* this.animateIn(duration ?? 0.4);
}
}Use the exact fontFamily string. Inter Variable is the default UI font. Code text uses Fira Code Variable.
2. Create the asset
Call component with action create:
{
"action": "create",
"name": "Hello title",
"componentName": "HelloTitle",
"code": "<the TSX above>"
}The result includes assetId. If the tool reports FAILED TO RENDER, fix the class before you place it.
3. Place it on the timeline
Call timeline_edit with action addClip, type component, and that assetId. Never type=text.
4. Capture a preview
Call preview with action captureFrame at a timecode where the clip is visible. Confirm the text is on screen and fully inside the frame.
A catalog template is faster when one already covers the design. Use createFromTemplate instead of create. Full props and methods: Authoring.
