Make a component interactivev4.0.479
Interactive components can be selected in the Remotion Studio timeline and can expose editable props.
If you only need an editable HTML or SVG element, use Interactive. For a custom component, wrap it with Interactive.withSchema().
Create a schema
An InteractivitySchema describes which props the Studio may edit.
Use Interactive.baseSchema for props inherited from <Sequence>, such as from, durationInFrames, freeze, hidden, name and showInTimeline.
Use Interactive.transformSchema if your component accepts a style prop and applies it to the rendered element.
Badge.tsximport typeReact from 'react'; import {Interactive , typeInteractiveBaseProps , typeInteractiveTransformProps , typeInteractivitySchema , } from 'remotion'; typeBadgeProps =InteractiveBaseProps &InteractiveTransformProps & { readonlychildren ?:React .ReactNode ; readonlycolor ?: string; readonlypadding ?: number; }; constbadgeSchema = { ...Interactive .baseSchema ,color : {type : 'color',default : '#0b84ff',description : 'Color', },padding : {type : 'number',min : 0,step : 1,default : 16,description : 'Padding',hiddenFromList : false, }, ...Interactive .transformSchema , } asconst satisfiesInteractivitySchema ;
Forward controls
The inner component receives a controls prop from Interactive.withSchema().
Forward it to the <Sequence> that represents your component in the timeline.
Badge.tsxconstBadgeInner =forwardRef <HTMLDivElement ,BadgeProps & { readonlycontrols :SequenceControls | undefined; } >( ( {children ,color = '#0b84ff',padding = 16,style ,name ,controls , ...sequenceProps },ref , ) => { constoutlineRef =useRef <HTMLDivElement >(null);useImperativeHandle (ref , () =>outlineRef .current asHTMLDivElement , []); return ( <Sequence layout ="none" {...sequenceProps }name ={name ?? '<Badge>'}controls ={controls }outlineRef ={outlineRef } > <div ref ={outlineRef }style ={{ ...style ,display : 'inline-flex',borderRadius : 999,backgroundColor :color ,color : 'white',fontWeight : 700,padding , }} > {children } </div > </Sequence > ); }, );
The exported component should not expose controls as a public prop.
Pass outlineRef when using <Sequence layout="none"> so the Studio can draw an outline around the rendered element.
Wrap the component
Use a stable componentIdentity so saved Studio edits can be associated with the component.
Badge.tsxexport constBadge =Interactive .withSchema ({Component :BadgeInner ,componentIdentity : 'com.example.Badge',schema :badgeSchema ,supportsEffects : false, });
Use the component
MyComp.tsximport {AbsoluteFill} from 'remotion'; import {Badge} from './Badge'; export const MyComp = () => { return ( <AbsoluteFill> <Badge from={30} durationInFrames={90} color="#ff5c7a" style={{translate: '120px 80px'}} > Sale </Badge> </AbsoluteFill> ); };
The component now has a timeline row, inherits the common <Sequence> props and exposes color, padding and transform controls in the Studio.
Choosing schema fragments
Interactive.baseSchema
Use it when the component renders a <Sequence> internally.
Interactive.transformSchema
Use it when the component accepts a style prop and applies it to the rendered element.
Interactive.premountSchema
Use it when the component forwards premountFor, postmountFor, styleWhilePremounted and styleWhilePostmounted to a <Sequence> with layout="absolute-fill".