Write reusable components
A reusable Odori component is a React component. Keep its presentation configurable through props, read the shared brand, and add a preview fixture so it can be reviewed independently in Studio.
Create a component
Create videos/components/headline/headline.tsx. This component adapts its typography and spacing to the design scale:
import {Fill, useBrand, useDesignScale} from "odori";
export function Headline({title}: {title: string}) {
const brand = useBrand();
const scale = useDesignScale();
return (
<Fill style={{
justifyContent: "center",
padding: 96 * scale,
background: brand.colors.background,
color: brand.colors.foreground,
fontFamily: brand.typography.sans,
}}>
<h1 style={{fontSize: 88 * scale, margin: 0}}>{title}</h1>
</Fill>
);
}Use props for content that changes between videos. Use the brand for shared visual decisions. See layouts and brands to define those defaults.
Add a preview fixture
Create videos/components/headline/headline.preview.tsx beside the implementation:
import {defineComponentPreview} from "odori/preview";
import {Headline} from "./headline";
export default defineComponentPreview({
title: "Headline",
category: "Typography",
component: Headline,
canvas: {width: 1920, height: 1080, duration: "4s"},
controls: {
title: {type: "text", defaultValue: "Meet the new editor."},
},
examples: [
{name: "Short", props: {title: "Ship it."}},
{name: "Long", props: {title: "A better place to build together."}},
],
});Start Studio with pnpm odori dev and open Components. Test both examples, then check portrait and square formats. Scaling preserves proportions; it does not guarantee that a long headline fits every aspect ratio.
Use it in a video
Import the implementation into a scene. Do not import the preview fixture into the production video:
import {Scene} from "odori";
import {Headline} from "../components/headline/headline";
export function Opening() {
return (
<Scene id="opening" duration="4s">
<Headline title="Meet the new editor." />
</Scene>
);
}Preview fixtures describe development controls and sample props. They are discovered separately from exportable video entries.
Organize shared and local code
Put code shared by several videos under videos/components/. Keep a video-specific component beside that video's entry, optionally in a local components/ directory. A directory alone does not create a video; discovery looks for entry filenames.
For installed registry components, keep odori.lock.json in version control. Review upstream changes with pnpm odori diff before updating edited source. See installing components.