# Introduction > Production-ready motion for Remotion. Install with the CLI, edit source in your repo. Source: https://remotionui.com/docs RemotionUI is a component registry for [Remotion](https://www.remotion.dev/docs). Use Remotion for framework fundamentals; use RemotionUI when you need ready-made captions, scenes, transitions, and composition templates. ## Building with an AI agent Paste this into your assistant and it will know the install workflow, the import paths, and the animation rules: Every page here has a **Copy page for AI** button and a Markdown version at `/llms.mdx/docs/`. For MCP-capable agents, see the [MCP Server](https://remotionui.com/docs/mcp.md); for Claude Code, `init --existing` installs a [project skill](https://remotionui.com/docs/installation.md). --- # Installation > Initialize a Remotion project with RemotionUI. Source: https://remotionui.com/docs/installation ## New project ```bash cd my-video && npm run dev ``` Open the Remotion Studio URL from your terminal, then add your first component: ```bash npx remotion-ui@latest add fade-in ``` ## Existing project Run `init --existing` from the root of an existing Remotion project. It writes `remotion-ui.json`, checks your path aliases, and installs the agent skill: ```bash npx remotion-ui@latest init --existing ``` That generates this config, which you can edit afterwards: ```json { "preset": "default", "aliases": { "primitives": "@/remotion/primitives", "scenes": "@/remotion/scenes", "compositions": "@/compositions", "lib": "@/remotion/lib", "hooks": "@/remotion/hooks" } } ``` Then add components: ```bash npx remotion-ui@latest add fade-in ``` ```bash npx remotion-ui@latest add lower-third ``` Run `npx remotion-ui@latest add` from your project root so the CLI can read `remotion-ui.json` and resolve aliases. Verify the setup at any time: ```bash npx remotion-ui@latest doctor ``` ## With the shadcn CLI Every RemotionUI component is also published to the shadcn registry under the `@remotionui` namespace, so you can install without the RemotionUI CLI: ```bash npx shadcn@latest add @remotionui/fade-in ``` The shadcn CLI resolves registry dependencies recursively and writes files using the aliases in your `components.json`. Where a component declares a `target` path, your own alias configuration takes priority. The shadcn path does not register compositions in `Root.tsx`. That is a `remotion-ui add` feature. Add the `` entry yourself when installing a full composition this way. ## What `add` does for you - Installs the component source plus every registry dependency it pulls in, recursively. - Installs npm dependencies with your detected package manager. - Registers compositions in `Root.tsx` automatically. Components that ship composition metadata get their `` entry and import added for you. Already-registered ids are left alone, so re-running `add` is safe. - Warns when a component declares a Remotion range your project does not satisfy. ## Agent skill `init --existing` installs a Claude Code skill at `.claude/skills/remotionui-agent/SKILL.md` by default, so agents working in the repo know the install-before-import workflow and the animation rules. ```bash npx remotion-ui@latest init --existing --no-agent-skill # skip it npx remotion-ui@latest init my-video --agent-skill # opt in for a new project ``` New projects do **not** install the skill unless you pass `--agent-skill`. ## Next steps - [CLI Reference](https://remotionui.com/docs/cli.md): flags, `--json` output, error codes, and version compatibility - [MCP Server](https://remotionui.com/docs/mcp.md): expose the registry as agent tools - [Authoring scenes](https://remotionui.com/docs/guides/authoring-scenes.md): layout patterns for multi-element scenes - [Components](https://remotionui.com/docs/components.md): browse all motion building blocks If RemotionUI saves you time, [star the repo on GitHub](https://github.com/riaz37/remotion-ui). It helps a lot. --- # CLI Reference > remotion-ui commands for init, add, doctor, and custom registries. Source: https://remotionui.com/docs/cli ## Commands | Command | Description | |---------|-------------| | `init [name]` | Scaffold a new Remotion project | | `init --existing` | Bootstrap `remotion-ui.json` in an existing Remotion project | | `add ` | Install components and dependencies | | `doctor` | Diagnose config, aliases, and Remotion version | | `list` | List registry components and installed status | | `update ` | Re-install from registry (overwrites files) | | `diff ` | Compare installed files vs registry | | `search -q ` | Search the registry | | `view ` | View registry item metadata | | `build [registry.json]` | Build a custom registry to `public/r/` | Every command accepts `--json`. Commands that read the registry also accept `-r, --registry-url ` and `--preset `. ## Flags by command | Command | Flags | |---------|-------| | `init [name]` | `-y, --yes`, `--existing`, `--agent-skill`, `--no-agent-skill`, `--json` | | `add ` | `-r, --registry-url`, `--preset`, `-y, --yes`, `--json` | | `doctor` | `--json` | | `list` | `-r, --registry-url`, `--json` | | `search` | `-q, --query`, `--lane`, `--tier`, `-r, --registry-url`, `--json` | | `view ` | `-r, --registry-url`, `--preset`, `--json` | | `update ` | `-r, --registry-url`, `--preset`, `-y, --yes`, `--json` | | `diff ` | `-r, --registry-url`, `--preset`, `--json` | | `build [registry.json]` | `-o, --output`, `--preset`, `--json` | ## Diagnose setup ```bash npx remotion-ui@latest doctor ``` Checks `remotion-ui.json`, `tsconfig` path aliases, install directories, and Remotion version alignment. ## Existing Remotion project ```bash cd your-remotion-app npx remotion-ui@latest init --existing npx remotion-ui@latest add social-clip ``` `init --existing` writes `remotion-ui.json` and installs the agent skill into `.claude/skills/remotionui-agent/`. Pass `--no-agent-skill` to skip it. ## New project ```bash npx remotion-ui@latest init my-video cd my-video && npm run dev npx remotion-ui@latest add social-clip ``` New projects skip the agent skill unless you pass `--agent-skill`. ## Composition registration When a registry item carries composition metadata, `add` patches `Root.tsx` for you: it inserts the import and a `` entry with the item's `id`, `durationInFrames`, `fps`, `width`, and `height`. If an id is already present, the file is left untouched, so re-running `add` or `update` never duplicates entries. ## Filter the registry ```bash npx remotion-ui@latest search -q caption npx remotion-ui@latest search --lane atoms npx remotion-ui@latest search --tier core --lane reels ``` Lanes: `atoms`, `signals`, `vectors`, `spatial`, `blocks`, `cuts`, `reels`. Tiers: `core`, `advanced`. ## Script output Pass `--json` to any command for machine-readable output. Useful for agents and CI. ```bash npx remotion-ui@latest doctor --json npx remotion-ui@latest search -q social --json npx remotion-ui@latest view social-clip --json npx remotion-ui@latest list --json npx remotion-ui@latest add social-clip --json npx remotion-ui@latest diff fade-in --json ``` ## Error codes With `--json`, failures print a structured envelope on stdout and exit non-zero: ```json { "ok": false, "error": { "code": "CONFIG_NOT_FOUND", "message": "No remotion-ui.json found in /path/to/project. Run \\"remotion-ui init\\" first." } } ``` | Code | Meaning | |------|---------| | `CONFIG_NOT_FOUND` | No `remotion-ui.json` (or no `package.json` during `init --existing`) in the working directory | | `CONFIG_INVALID` | `remotion-ui.json` failed schema validation | | `REGISTRY_ITEM_NOT_FOUND` | No registry item with that name | | `REGISTRY_FETCH_FAILED` | Network or HTTP failure reaching the registry | | `REGISTRY_ITEM_INVALID` | Fetched item failed schema validation | | `REGISTRY_INDEX_INVALID` | Fetched index failed schema validation | | `TEMPLATE_NOT_FOUND` | Project template missing from the CLI package | | `TARGET_EXISTS` | Target directory already exists | | `INVALID_ARGS` | Missing or malformed command arguments | | `DEPENDENCY_SPEC_INVALID` | A dependency string could not be parsed | | `UNKNOWN` | Anything not mapped to a specific code | ## Remotion version compatibility Registry items may declare a supported Remotion range: ```json { "name": "map-flight", "compat": { "remotion": "^4.0.0" } } ``` At install time, `add` reads the Remotion version from your `package.json` and warns when the range is not satisfied. The install still proceeds. The check is advisory, and it only runs at install time, not continuously. `doctor` reports your installed Remotion version alongside config and alias checks. ## Component props Prop metadata is published per component as JSON, for agents and tooling that need signatures without reading source: ```tsx https://remotionui.com/ai/components/lower-third.json ``` Each entry carries `name`, `type`, `required`, `default`, and `description`, plus usage snippets and related components. See [AI Usage](https://remotionui.com/docs/ai.md) for the full set of agent-readable endpoints. ## Workflow: staying up to date ```bash npx remotion-ui@latest diff fade-in ``` ```bash npx remotion-ui@latest update fade-in ``` ## Custom registry ```bash npx remotion-ui@latest build ./registry.json -o ./public/r ``` ## Config: remotion-ui.json ```json { "preset": "default", "aliases": { "primitives": "@/remotion/primitives", "scenes": "@/remotion/scenes", "compositions": "@/compositions", "lib": "@/remotion/lib", "hooks": "@/remotion/hooks" } } ``` --- # Motion Tokens > Shared durations, delays, stagger steps, and Bézier curves. Source: https://remotionui.com/docs/guides/motion-tokens ## Install ```bash npx remotion-ui@latest add motion-tokens ``` Motion tokens centralize timing so primitives and scenes stay consistent across compositions. ```tsx import { DURATION, DELAY, STAGGER, EASING } from "@/remotion/lib/motion-tokens"; import { enterProgress } from "@/remotion/lib/timing"; // DURATION.fast ~12 frames at 30fps // DURATION.normal ~24 frames // DURATION.slow ~36 frames // STAGGER.normal 8 frames between children // EASING.enter crisp ease-out for entrances const progress = enterProgress(frame, DELAY.short, DURATION.normal, EASING.enter); ``` Pair tokens with `springs.ts` for physics-based motion (`spring-in`, `marker-highlight`) and `timing.ts` for interpolate helpers. --- # Transitions > Scene-to-scene fades with TransitionSeries. Source: https://remotionui.com/docs/guides/transitions Install the fade helper and transitions package: ## Install ```bash npx remotion-ui@latest add transition-fade ``` ```bash npx remotion add @remotion/transitions ``` Use `transitionFade()` with `TransitionSeries`: ```tsx import { TransitionSeries } from "@remotion/transitions"; import { transitionFade, getTransitionFadeDuration, } from "@/remotion/primitives/transition-fade"; const fade = transitionFade({ durationInFrames: 15 }); const fadeSpring = transitionFade({ variant: "spring", durationInFrames: 20 }); ``` ### Duration math Transitions overlap adjacent scenes, so total duration is **shorter** than the sum of sequence durations: ```tsx const total = scene1 + scene2 - getTransitionFadeDuration({ durationInFrames: 15 }, 30); // 60 + 60 - 15 = 105 frames ``` For slide transitions, use `transition-slide`: ```tsx import { transitionSlide } from "@/remotion/primitives/transition-slide"; ``` See the [Showcase](https://remotionui.com/docs/components/showcase.md) composition for a full multi-scene example. --- # Authoring Scenes > Patterns for stagger, sequencing, and responsive layout. Source: https://remotionui.com/docs/guides/authoring-scenes ```bash npx remotion-ui@latest add stagger-children layout motion-tokens ``` ## Stagger Use `stagger-children` to offset delays automatically: ```tsx import { STAGGER } from "@/remotion/lib/motion-tokens"; {items.map((item) => ( {item} ))} ``` For per-item control in custom components, use the `use-stagger` hook: ```tsx import { useStagger } from "@/remotion/hooks/use-stagger"; const delayInFrames = useStagger({ index, staggerInFrames: 8 }); ``` ## Responsive layout Scenes use `layout.ts` helpers aligned with video-layout guidance. Never hardcode 1920×1080: ```tsx import { getSafeAreaPadding, scaleFont } from "@/remotion/lib/layout"; const safeArea = getSafeAreaPadding({ width, height }); // 80px sides / 100px vertical at 1080p reference const headline = scaleFont(84, width); // main message at 1080p baseline const supporting = scaleFont(44, width); ``` ## Sequencing scenes Chain scenes in a composition with `TransitionSeries`, or use `` with `premountFor` so content is ready before it appears: ```tsx import { Sequence, useVideoConfig } from "remotion"; const { fps } = useVideoConfig(); </Sequence> ``` Reveal crowded content **over time** instead of fitting everything in one frame. --- # Captions > Build captioned Remotion videos with CaptionScene, karaoke modes, and social clip templates. Source: https://remotionui.com/docs/guides/captions RemotionUI caption components work with Remotion's native [`Caption`](https://www.remotion.dev/docs/captions/caption) type, for TikTok-style word highlights, karaoke scale, or full caption scenes in vertical social clips. ## Install ```bash npx remotion-ui@latest add caption-scene caption-highlight ``` This installs `@remotion/captions` and `caption-utils`. For a complete 9:16 template: ## Pipeline 1. **Transcribe** audio to captions JSON (Whisper, SRT import, or `@remotion/openai-whisper`) 2. **Load** captions in your composition (fetch with `useDelayRender` if remote) 3. **Group** into pages with `groupCaptionsIntoPages()` from `caption-utils` 4. **Render** with `CaptionScene` or wire into `SocialClip` / `PodcastClip` ## Caption components | Component | Use when | |-----------|----------| | [CaptionScene](https://remotionui.com/docs/components/caption-scene.md) | Full-frame synced caption layout | | [CaptionHighlight](https://remotionui.com/docs/components/caption-highlight.md) | Word-level color emphasis | | [KaraokeCaptions](https://remotionui.com/docs/components/karaoke-captions.md) | Scale or underline active word | | [CaptionBumper](https://remotionui.com/docs/components/caption-bumper.md) | Short insight text between scenes | `CaptionScene` supports `mode`: `highlight`, `karaoke-scale`, or `karaoke-underline`. Flagship compositions default to `karaoke-scale` for social-ready motion. ## Example ```tsx import { CaptionScene } from "@/remotion/scenes/caption-scene"; import type { Caption } from "@remotion/captions"; <CaptionScene captions={captions} mode="karaoke-scale" pagesPerScene={1} />; ``` See [caption-scene](https://remotionui.com/docs/components/caption-scene.md) for the full API and [social-clip](https://remotionui.com/docs/components/social-clip.md) for a full template composition. --- # Maps > MapLibre determinism, render flags, and Turf patterns. Source: https://remotionui.com/docs/guides/maps RemotionUI spatial components use **MapLibre GL JS** and **Turf** for deterministic map animations. ## Install ```bash npx remotion-ui@latest add map-flight ``` ## Determinism rules - `interactive: false`, `fadeDuration: 0` - `delayRender()` until map `idle` on load and per-frame updates - Turf for geodesic routes. Do not hand-roll coordinate math - Separate **target route** (line animation) from **camera route** (camera position) ## Render flags WebGL maps require ANGLE and single concurrency: ```bash npx remotion render src/Root.tsx MapFlight out/map.mp4 --gl=angle --concurrency=1 ``` ## Components | Component | Role | |-----------|------| | `map-canvas` | Low-level MapLibre mount | | `map-route` | Animated line reveal | | `map-markers` | Circle + label layers | | `map-flight` | Full flyover scene | See [map-flight](https://remotionui.com/docs/components/map-flight.md) for the flagship example. --- # Audio Visualization > Audiogram setup with media-utils. Source: https://remotionui.com/docs/guides/audio-viz RemotionUI audiogram components use `@remotion/media-utils` for frame-accurate spectrum data. ## Install ```bash npx remotion-ui@latest add audiogram-scene ``` ## Usage ```tsx import { AudiogramScene } from "@/remotion/scenes/audiogram-scene"; import { staticFile } from "remotion"; <AudiogramScene src={staticFile("podcast.wav")} title="Episode 1" />; ``` ## Tips - Pass audio `src` as `staticFile()` or a remote URL - Use `useWindowedAudioData` via `audio-viz-utils` for custom visualizations - When nesting in `<Sequence>`, pass `frame` from parent. Do not call `useCurrentFrame()` in each bar child See [audiogram-bars](https://remotionui.com/docs/components/audiogram-bars.md) and [audiogram-scene](https://remotionui.com/docs/components/audiogram-scene.md). --- # All components > Browse and install Remotion compositions, scenes, and primitives. Source: https://remotionui.com/docs/components/browse RemotionUI groups components by **motion role** (lanes), with **tags** for use-case filters inside dense lanes. ## How categorization works **Lanes** describe how a component behaves on the timeline: | Lane | Install path | Examples | |------|----------------|----------| | Primitives | `@/remotion/primitives/…` | `fade-in`, `typewriter`, `mesh-gradient-bg` | | Data & media | `@/remotion/primitives/…` or scenes | `caption-highlight`, `animated-bar-chart` | | Paths & shapes | `@/remotion/primitives/…` | `path-draw`, `logo-reveal` | | Maps & device | scenes / primitives | `map-flight`, `device-mockup-zoom` | | 3D | `@/remotion/scenes/…` (render with `--gl=angle`) | `device-mockup-3d`, `product-turntable-3d`, `globe-points-3d` | | Shaders | `@/remotion/primitives/…` (render with `--gl=angle`) | `dither-field-bg`, `warp-bands-bg` | | Scenes | `@/remotion/scenes/…` | `lower-third`, `claude-chat`, `code-reveal` | | Transitions | `@/remotion/primitives/transition-*` | `transition-fade`, `blur-reveal` | | Compositions | `@/compositions/…` | `social-clip`, `hero-loop` | **Tags** narrow a lane by use case: AI composers, code & terminal, creator layouts, captions, charts, and more. Use tag chips on this page when a lane is selected, or follow tag sub-groups in the sidebar. **Helpers** (`layout`, `springs`, `timing`, `use-stagger`) install to `@/remotion/lib/` and `@/remotion/hooks/`. --- # Text effects > Animated type for titles, callouts, and captions. Each one is a single primitive you drop into a scene. Source: https://remotionui.com/docs/components/text-effects Text effects animate the letters themselves: typing, decoding, glitching, sweeping light, and morphing between words. They take a string and a few timing props, so they sit inside any scene or composition without extra layout work. ## Components - [Blur Focus In](https://remotionui.com/docs/components/blur-focus-in.md): Blur Focus In text animation for Remotion. - [Counter](https://remotionui.com/docs/components/counter.md): Animated number with grouping, decimals, an odometer roll and a reserved width. - [Handwriting Text](https://remotionui.com/docs/components/handwriting-text.md): Write a string on, character by character, with a nib riding the wet edge. Install with npx remotion-ui@latest add handwriting-text. - [Infinite Marquee](https://remotionui.com/docs/components/infinite-marquee.md): Infinite Marquee text animation for Remotion. - [Light Sweep Text](https://remotionui.com/docs/components/light-sweep-text.md): Light Sweep Text text animation for Remotion. - [Liquid Text Morph](https://remotionui.com/docs/components/liquid-text-morph.md): Melt one word into the next through a gooey threshold filter. Install with npx remotion-ui@latest add liquid-text-morph. - [Marker Highlight](https://remotionui.com/docs/components/marker-highlight.md): Highlighter stroke swept word by word, with marker, knockout, underline and box variants. - [Masked Slide Reveal](https://remotionui.com/docs/components/masked-slide-reveal.md): Masked Slide Reveal text animation for Remotion. - [Matrix Decode](https://remotionui.com/docs/components/matrix-decode.md): Matrix Decode text animation for Remotion. - [Neon Flicker Text](https://remotionui.com/docs/components/neon-flicker-text.md): Light a word tube by tube, with a mains hum that never quite settles. Install with npx remotion-ui@latest add neon-flicker-text. - [Perspective Marquee](https://remotionui.com/docs/components/perspective-marquee.md): Perspective Marquee text animation for Remotion. - [RGB Glitch Text](https://remotionui.com/docs/components/rgb-glitch-text.md): Signal-lock RGB glitch text primitive for Remotion. - [Scramble Text](https://remotionui.com/docs/components/scramble-text.md): Resolve each character out of random glyph noise, in any stagger order. Install with npx remotion-ui@latest add scramble-text. - [Slot Roll](https://remotionui.com/docs/components/slot-roll.md): Slot Roll text animation for Remotion. - [Split Text Chars](https://remotionui.com/docs/components/split-text-chars.md): Split a string into characters, words, or lines and stagger them in. Install with npx remotion-ui@latest add split-text-chars. - [Staggered Fade Up](https://remotionui.com/docs/components/staggered-fade-up.md): Staggered Fade Up text animation for Remotion. - [Strikethrough Replace](https://remotionui.com/docs/components/strikethrough-replace.md): Strikes out one phrase and puts another in its place, on a three-beat correction timeline. - [Stroke to Fill Text](https://remotionui.com/docs/components/stroke-to-fill-text.md): Draw type as an outline, then flood each letter solid. Install with npx remotion-ui@latest add stroke-to-fill-text. - [Text Mask Video](https://remotionui.com/docs/components/text-mask-video.md): Play video, a still, or a gradient inside letterforms, with a wipe reveal. Install with npx remotion-ui@latest add text-mask-video. - [Tracking In](https://remotionui.com/docs/components/tracking-in.md): Tracking In text animation for Remotion. - [Typewriter](https://remotionui.com/docs/components/typewriter.md): Typewriter reveal with rhythm, pauses, looping, and a caret that only blinks at rest. - [Variable Font Morph](https://remotionui.com/docs/components/variable-font-morph.md): Sweep a variable font's weight and width axes across a line, one character at a time. Install with npx remotion-ui@latest add variable-font-morph. - [Wave Text](https://remotionui.com/docs/components/wave-text.md): Run a sine along a line of type, one character at a time. Install with npx remotion-ui@latest add wave-text. --- # Blur Focus In > Blur Focus In text animation for Remotion. Source: https://remotionui.com/docs/components/blur-focus-in ## Installation ```bash npx remotion-ui@latest add blur-focus-in ``` Blur Focus In text animation primitive. ## Usage ```tsx import { BlurFocusIn } from "@/remotion/primitives/blur-focus-in"; <BlurFocusIn text="Sharp focus" maxBlur={18} /> ``` ## Props | Name | Type | Default | Description | | --- | --- | --- | --- | | `text` (required) | `string` | - | Text to reveal from blur. | | `durationInFrames` | `number` | `36` | Blur-to-sharp duration. | | `maxBlur` | `number` | `18` | Starting blur in pixels. | ## Related - [Blur In](https://remotionui.com/docs/components/blur-in.md) - [Tracking In](https://remotionui.com/docs/components/tracking-in.md) ## Machine-readable references - Props and usage as JSON: https://remotionui.com/ai/components/blur-focus-in.json - Component index: https://remotionui.com/ai/components.json --- # Counter > Animated number with grouping, decimals, an odometer roll and a reserved width. Source: https://remotionui.com/docs/components/counter ## Installation ```bash npx remotion-ui@latest add counter ``` Ramps from `from` to `to` on an ease-out, so the number decelerates into its landing instead of arriving at constant speed. The width is reserved from the longest value the ramp can produce, so a centred number never reflows the line around it. `roll` turns each digit like an odometer: the lowest column turns continuously and every column above it holds its face until the ones below are nearly wrapped, then flips through on the carry. With `decimals`, the freely turning column is the last decimal place, not the units. Every slot (a rolling digit, a group separator, the decimal point, a prefix or suffix) is a box exactly one digit tall with the glyph placed by half-leading, so all of them resolve to the same baseline at the same size, and each wheel is clipped to that one row. Nothing in the roll scales, fades or blurs, and turning `roll` on or off does not move the number or change the space it takes. ## Usage ```tsx import { Counter } from "@/remotion/primitives/counter"; <Counter from={0} to={124000} roll durationInFrames={64} /> ``` The width is reserved from the longest value the ramp can produce, so a centred number never reflows the line around it. Every rolling column shares one baseline and one size with the separators and is clipped to a single digit row, so nothing bleeds out of the number's line box. ## Props | Name | Type | Default | Description | | --- | --- | --- | --- | | `to` (required) | `number` | - | Value the count lands on. | | `from` | `number` | `0` | Value the count starts from. | | `durationInFrames` | `number` | `60` | Frames over which the value ramps. | | `delayInFrames` | `number` | `0` | Frames before the ramp starts. | | `decimals` | `number` | `0` | Fixed decimal places. Also fixes the width, so nothing shifts. | | `grouping` | `boolean` | `true` | Group thousands with the locale's separator. | | `locale` | `string` | - | Locale for grouping and decimal marks. | | `format` | `(value: number) => string` | - | Full override of the number formatting. | | `prefix` | `string` | - | Text before the number, e.g. a currency mark. | | `suffix` | `string` | - | Text after the number, e.g. %, K, M. | | `roll` | `boolean` | `false` | Roll each digit like an odometer. The lowest column turns continuously and every column above it turns over on the carry. With decimals, the free column is the last decimal place. | | `spring` | `MotionSpring` | - | Drive the ramp with a spring instead of the ease-out curve. | | `settle` | `boolean` | `true` | Small scale pop on the frame the number lands. | | `fontSize` | `number` | `scaled 96px` | Text size in pixels. | | `fontWeight` | `number` | `700` | Text weight. | | `color` | `string` | - | Text colour. | | `fontFamily` | `string` | - | Font family for the number. | | `style` | `CSSProperties` | - | Styles merged onto the number. | ## Related - [Stat Card](https://remotionui.com/docs/components/stat-card.md) - [Progress Bar](https://remotionui.com/docs/components/progress-bar.md) ## Machine-readable references - Props and usage as JSON: https://remotionui.com/ai/components/counter.json - Component index: https://remotionui.com/ai/components.json --- # Handwriting Text > Write a string on, character by character, with a nib riding the wet edge. Install with npx remotion-ui@latest add handwriting-text. Source: https://remotionui.com/docs/components/handwriting-text ## Installation ```bash npx remotion-ui@latest add handwriting-text ``` Reveals a line as if it were being written. ```tsx import { HandwritingText } from "@/remotion/primitives/handwriting-text"; <HandwritingText text="Signed by hand" staggerInFrames={9} penColor="#e8b86d" /> ``` ## This takes a string; `path-draw` takes a path That is the whole distinction, and it decides which one you want. A string has no stroke order (nothing in a font records that `S` starts at the top right), so the ink here is revealed by a left-to-right wipe per glyph with a nib riding the wet edge. For a signature or a logogram, where the stroke order *is* the effect, give `path-draw` the actual path. ## `order` is not a prop Writing runs left to right. Re-ranking the stagger would produce a word that assembles out of sequence, which reads as a glitch rather than as a hand. ## The hand `wobble` tilts each character and drifts it off the baseline by a hashed amount. It is fixed per character, not animated, so the word does not wriggle once it is written. Set it to `0` for machine-even type. `penSize` is in em; `0` hides the nib. ## Fonts The default family is a script stack ending in the generic `cursive`, which resolves to whatever the render machine happens to have. Pass a webfont through `fontFamily` for a result that is identical everywhere. ## Usage ```tsx import { HandwritingText } from "@/remotion/primitives/handwriting-text"; <HandwritingText text="Signed by hand" staggerInFrames={9} penColor="#e8b86d" /> ``` Takes a string, so there is no stroke order: the ink is wiped on per glyph. `path-draw` takes a path and strokes it properly. `order` and `mode` are deliberately not props. ## Props | Name | Type | Default | Description | | --- | --- | --- | --- | | `text` | `string` | - | The line that gets written. | | `penSize` | `number` | `0.14` | Diameter of the nib, in em. 0 hides it. | | `penColor` | `string` | - | Nib colour. Defaults to `color`. | | `inkSoftness` | `number` | `0.18` | Softness of the ink edge, as a share of one glyph. | | `wobble` | `number` | `1.6` | Per-character tilt and baseline drift, in degrees. Fixed, not animated. | | `staggerInFrames` | `number` | `3` | Frames between one character and the next. This is the writing speed. | | `durationInFrames` | `number` | `10` | Frames one character takes to be drawn. | | `delayInFrames` | `number` | `0` | Frames before the first stroke. | | `exitAtInFrames` | `number` | - | Frame the ink starts fading on. | | `fontFamily` | `string` | `script stack` | Ends in generic `cursive`; pass a webfont for identical renders everywhere. | ## Related - [Path Draw](https://remotionui.com/docs/components/path-draw.md) - [Split Text Chars](https://remotionui.com/docs/components/split-text-chars.md) - [Marker Highlight](https://remotionui.com/docs/components/marker-highlight.md) ## Machine-readable references - Props and usage as JSON: https://remotionui.com/ai/components/handwriting-text.json - Component index: https://remotionui.com/ai/components.json --- # Infinite Marquee > Infinite Marquee text animation for Remotion. Source: https://remotionui.com/docs/components/infinite-marquee ## Installation ```bash npx remotion-ui@latest add infinite-marquee ``` Text that scrolls forever, in either `direction`, at `speed` pixels per frame. The preview above runs three bands: two faded ones travelling opposite ways, and a third with `fade={0}` so the difference is visible in a single still. The whole job is the wrap. The track holds identical copies of the text, each carrying its own trailing `gap`, so every copy occupies exactly one tile; shifting the track by one tile lands each copy where its neighbour stood, which is the same picture. That shift is written as a percentage of the track rather than a measured pixel count, so a font that measures differently than it renders changes the speed slightly and can never make the wrap jump. `fade` softens both edges, as a fraction of the visible band (`0.08` by default), so at 960px wide the outer 77px on each side ramps to nothing and no letter ever terminates against the frame. Set it to `0` for a hard edge. ## Usage ```tsx import { InfiniteMarquee } from "@/remotion/primitives/infinite-marquee"; <InfiniteMarquee text="Scrolling band" speed={2} direction="left" fade={0.08} /> ``` The loop is one copy of the text wide and seamless by construction: the shift is a percentage of the track, so a mismeasured font changes the speed but can never make the wrap jump. ## Props | Name | Type | Default | Description | | --- | --- | --- | --- | | `text` (required) | `string` | - | Marquee copy. | | `speed` | `number` | `2` | Pixels travelled per frame. | | `direction` | `"left" \| "right"` | `"left"` | Which way the text travels. | | `fade` | `number` | `0.08` | Width of the fade at each edge as a fraction of the visible band. 0 gives a hard edge; capped at 0.45 so the two fades cannot meet. | | `fontSize` | `number` | - | Overrides the width-scaled default (56 at 1080p). | | `color` | `string` | `"#f4f4f5"` | Text colour. | | `fontWeight` | `number` | `600` | Text weight. | | `gap` | `number` | `48` | Space between one copy of the text and the next, in px. | ## Related - [Perspective Marquee](https://remotionui.com/docs/components/perspective-marquee.md) ## Machine-readable references - Props and usage as JSON: https://remotionui.com/ai/components/infinite-marquee.json - Component index: https://remotionui.com/ai/components.json --- # Light Sweep Text > Light Sweep Text text animation for Remotion. Source: https://remotionui.com/docs/components/light-sweep-text ## Installation ```bash npx remotion-ui@latest add light-sweep-text ``` A specular highlight travelling across the type, clipped to the glyphs. The gradient is 2.2× the width of the line, so `bandWidth` (the shine's half-width in percent of that gradient) controls how much of the line is lit at once: the default `8` is a hard streak, `14` lights up about three fifths of it. Widen the band for a long sweep, or the highlight spends the ends of its travel clear of the text. `easing` defaults to an ease-in-out, which is right for a short accent. A sweep long enough to read as light moving should pass `Easing.linear`: a specular reflection travels at constant speed. ## Usage ```tsx import { LightSweepText } from "@/remotion/primitives/light-sweep-text"; <LightSweepText text="Light pass" /> ``` ## Props | Name | Type | Default | Description | | --- | --- | --- | --- | | `text` (required) | `string` | - | Text with gradient sweep. | ## Related - [Marker Highlight](https://remotionui.com/docs/components/marker-highlight.md) ## Machine-readable references - Props and usage as JSON: https://remotionui.com/ai/components/light-sweep-text.json - Component index: https://remotionui.com/ai/components.json --- # Liquid Text Morph > Melt one word into the next through a gooey threshold filter. Install with npx remotion-ui@latest add liquid-text-morph. Source: https://remotionui.com/docs/components/liquid-text-morph ## Installation ```bash npx remotion-ui@latest add liquid-text-morph ``` Cycles a list of words, melting each one into the next. ```tsx import { LiquidTextMorph } from "@/remotion/primitives/liquid-text-morph"; <LiquidTextMorph words={["Melt", "Merge", "Reform"]} holdInFrames={12} morphInFrames={22} /> ``` ## Goo, not path interpolation Both words are drawn at once inside an SVG blur-plus-alpha-threshold, so letterforms that come near each other fuse into one blob and split apart again. Real glyph outline interpolation needs matched node counts between two arbitrary letters (`A` and `s` do not have them) and produces tearing where this produces surface tension. Use `shape-morph` when the two shapes are paths you control. `gooStrength` is the blur in em and `gooContrast` is the alpha threshold on top of it. Raising the blur past about `0.1` fuses the whole line into one mass. ## The overlap is a third of the morph, not all of it The outgoing word plays its own entrance backwards on a clock that runs 1.5× fast, and the incoming word does not start until the melt is 30% through. Running both across the whole morph leaves two complete words stacked at the midpoint and the threshold turns them into an unreadable puddle. ## Timing One cycle is `holdInFrames + morphInFrames`. `loop` is on by default and the last word morphs back into the first; turn it off and the final word is held. Both words run through `split-text-chars` with a frame override, so the stagger semantics are the same as everywhere else: it is fitted to the longest word so a wide stagger cannot leave the last letter half-formed when the hold begins. ## Usage ```tsx import { LiquidTextMorph } from "@/remotion/primitives/liquid-text-morph"; <LiquidTextMorph words={["Melt", "Merge", "Reform"]} morphInFrames={22} /> ``` A gooey threshold filter, not path interpolation: two arbitrary letters do not have matching node counts. Use `shape-morph` for paths you control. ## Props | Name | Type | Default | Description | | --- | --- | --- | --- | | `words` | `string[]` | - | Two or more words. The last melts back into the first when looping. | | `holdInFrames` | `number` | `12` | Frames a word is held before it starts melting. | | `morphInFrames` | `number` | `22` | Frames one word takes to become the next. | | `loop` | `boolean` | `true` | Keep cycling. When false the last word is held forever. | | `gooStrength` | `number` | `0.045` | Blur feeding the threshold, in em. This is what makes letters merge. | | `gooContrast` | `number` | `18` | Alpha contrast on the blurred layer. Lower is softer and wetter. | | `staggerInFrames` | `number` | `2` | Frames between neighbouring letters melting. Clamped to fit the morph. | | `fontSize` | `number` | - | Defaults to a scaled 96px at the composition width. | | `color` | `string` | `"#f4f4f5"` | Ink colour. | | `fontWeight` | `number \| string` | `700` | Heavier weights fuse more readily under the threshold. | ## Related - [Shape Morph](https://remotionui.com/docs/components/shape-morph.md) - [Split Text Chars](https://remotionui.com/docs/components/split-text-chars.md) - [Blob Morph](https://remotionui.com/docs/components/blob-morph.md) ## Machine-readable references - Props and usage as JSON: https://remotionui.com/ai/components/liquid-text-morph.json - Component index: https://remotionui.com/ai/components.json --- # Marker Highlight > Highlighter stroke swept word by word, with marker, knockout, underline and box variants. Source: https://remotionui.com/docs/components/marker-highlight ## Installation ```bash npx remotion-ui@latest add marker-highlight ``` Strikes emphasis across `phrase`, one word at a time. Word by word matters: one band appearing behind the whole phrase reads as a background, while a stroke crossing each word in turn reads as a hand moving. The stroke is built the way ink lands rather than as a filled rectangle: feathered top and bottom edges, fibre striations along the fill, and a soft leading edge held off vertical by `tilt`. The band itself is never rotated: rotating each word's box is what turns a joined phrase into a staircase of offset rectangles. Everything that varies is anchored to the band's own top edge, so the stroke runs through a word join without a seam and a wrapped phrase carries one band height on every line. The ink flips under the leading edge of the stroke rather than at a threshold, and it turns at the back of that edge, where the band is already at full strength. A half-tone letter on a half-laid band is the one place a covered word is hard to read. `variant` switches between a translucent marker, a solid knockout, an underline and a box. ## Usage ```tsx import { MarkerHighlight } from "@/remotion/primitives/marker-highlight"; <MarkerHighlight text="The best motion is code you can read and change." phrase="code you can read and change" markerColor="#f97316" /> ``` The stroke crosses each marked word in turn, so it reads as a hand moving rather than a background appearing. Band geometry is stated as top plus height in em against each word's own line box, so a phrase that wraps carries the same band on every line. ## Props | Name | Type | Default | Description | | --- | --- | --- | --- | | `text` (required) | `string` | - | Full sentence to render. | | `phrase` | `string` | - | Phrase to sweep. Matched case-insensitively and may span several words. | | `highlightWord` | `string` | - | Single-word form of phrase. | | `variant` | `"marker" \| "knockout" \| "underline" \| "box"` | `"marker"` | How the emphasis is drawn. | | `durationInFrames` | `number` | `12` | Length of the sweep across one word. | | `delayInFrames` | `number` | `0` | Frames before the first word is struck. | | `staggerInFrames` | `number` | `4` | Frames between one word being struck and the next. | | `tilt` | `number` | `-4` | Angle of the nib in degrees off vertical. Slopes the leading edge only; the band is never rotated, so a joined phrase does not step at every word. | | `inkSoftness` | `number` | `0.16` | Softness of the leading edge, as a share of the word. 0 is a hard cut. | | `markerColor` | `string` | `"#fbbf24"` | Colour of the stroke. | | `markerOpacity` | `number` | `per variant` | Alpha of the ink. Defaults to 0.62 for marker, 0.95 for underline, 1 for knockout and box. | | `invertOnHighlight` | `boolean` | `knockout only` | Flip the ink under the leading edge of the stroke as it passes. | | `inkColor` | `string` | `"#080810"` | Ink used over a covered word. | | `color` | `string` | `"#f8fafc"` | Base text colour. | | `textAlign` | `"left" \| "center" \| "right"` | `"left"` | Alignment of the wrapped words. | | `fontSize` | `number` | `scaled 84px` | Text size in pixels. | | `fontWeight` | `number` | `600` | Text weight. | | `fontFamily` | `string` | - | Font family for the text. | | `style` | `CSSProperties` | - | Styles merged onto the wrapper. | ## Related - [Quote Card](https://remotionui.com/docs/components/quote-card.md) - [Typewriter](https://remotionui.com/docs/components/typewriter.md) ## Machine-readable references - Props and usage as JSON: https://remotionui.com/ai/components/marker-highlight.json - Component index: https://remotionui.com/ai/components.json --- # Masked Slide Reveal > Masked Slide Reveal text animation for Remotion. Source: https://remotionui.com/docs/components/masked-slide-reveal ## Installation ```bash npx remotion-ui@latest add masked-slide-reveal ``` Each line slides up through a fixed-height mask with staggered timing. Pass `lines` for multi-line headlines, or `text` with newline-separated copy. ## Usage ```tsx import { MaskedSlideReveal } from "@/remotion/primitives/masked-slide-reveal"; <MaskedSlideReveal lines={[ "Three layers in your repo", "Drop scenes into", "TransitionSeries", ]} /> ``` ## Props | Name | Type | Default | Description | | --- | --- | --- | --- | | `text` | `string` | - | Copy to reveal. Splits on newlines for line mode, or words on a single line. Omit when using lines. | | `lines` | `string[]` | - | Explicit lines to reveal through the mask. Preferred for multi-line headlines. | | `staggerInFrames` | `number` | `6` | Frames between each line or word reveal. | | `durationInFrames` | `number` | `16` | Frames for each masked slide-in. | | `delayInFrames` | `number` | `0` | Delay before the first item animates. | | `textAlign` | `"left" \| "center" \| "right"` | `"center"` | Horizontal alignment of lines. | | `lineGap` | `number` | `0.18` | Gap between lines in em units (line mode only). | ## Related - [Staggered Fade Up](https://remotionui.com/docs/components/staggered-fade-up.md) ## Machine-readable references - Props and usage as JSON: https://remotionui.com/ai/components/masked-slide-reveal.json - Component index: https://remotionui.com/ai/components.json --- # Matrix Decode > Matrix Decode text animation for Remotion. Source: https://remotionui.com/docs/components/matrix-decode ## Installation ```bash npx remotion-ui@latest add matrix-decode ``` A resolve front sweeps the string left to right at a constant rate: everything behind it is the target text, everything ahead of it is a scrambled glyph, and the one character sitting on the front is tinted `hotColor`. A deterministic ±2 character jitter (hashed off the character index, never `Math.random`) keeps the front from landing as a perfectly straight edge. `glyphs` is the pool the unresolved characters are drawn from. It has to be monospace-width in whatever `fontFamily` you pass: the classic full-width katakana are twice a latin advance, so a line rendered in them is twice as wide while it is still scrambled as it is once it has resolved, and it runs off the frame. The window matches the preview at 120 frames so the docs `<Player>` shows the same sweep the tile does. ## Usage ```tsx import { MatrixDecode } from "@/remotion/primitives/matrix-decode"; <MatrixDecode text="DECODED" /> ``` The front sweeps at a constant rate with a deterministic ±2 character jitter, so glyphs lock in roughly, not exactly, left to right. No `Math.random`: the jitter is hashed off the character index. ## Props | Name | Type | Default | Description | | --- | --- | --- | --- | | `text` (required) | `string` | - | Target string. | | `delayInFrames` | `number` | `0` | Frame the resolve front starts sweeping. | | `durationInFrames` | `number` | `50` | Frames the front takes to cross the whole string. | | `color` | `string` | `"#2dd4bf"` | Resolved and scrambled glyph colour. | | `hotColor` | `string` | `"#5eead4"` | Colour of the single character sitting on the decode front. | | `glyphs` | `string` | - | Pool the unresolved characters are drawn from. Must be monospace-width in `fontFamily`: full-width katakana are twice a latin advance, so the line changes width as it resolves. | ## Related - [RGB Glitch Text](https://remotionui.com/docs/components/rgb-glitch-text.md) - [Scramble Text](https://remotionui.com/docs/components/scramble-text.md) ## Machine-readable references - Props and usage as JSON: https://remotionui.com/ai/components/matrix-decode.json - Component index: https://remotionui.com/ai/components.json --- # Neon Flicker Text > Light a word tube by tube, with a mains hum that never quite settles. Install with npx remotion-ui@latest add neon-flicker-text. Source: https://remotionui.com/docs/components/neon-flicker-text ## Installation ```bash npx remotion-ui@latest add neon-flicker-text ``` A neon sign starting the way neon actually starts. ```tsx import { NeonFlickerText } from "@/remotion/primitives/neon-flicker-text"; <NeonFlickerText text="Open all night" order="random" glowColor="#f472b6" staggerInFrames={5} /> ``` ## A gas-discharge model, not random opacity Three things separate this from `Math.random()` on `opacity`: - An unlit tube is still there as cold glass (`offColor`), not invisible. - The strike probability climbs across each character's own window, so the sign resolves instead of sputtering forever. - A lit tube keeps a mains hum and an occasional stutter. That last one matters more than it sounds. A settled state with no hum is what makes a neon effect look like a static PNG two seconds in. ## Tuning `hum` is the depth of the idle breathe and `buzz` is the chance per beat that a settled tube drops out. `glowSize` is the halo radius in px at full brightness; the glow is four stacked shadows, so it stays soft at large sizes instead of banding. `order="random"` is the natural fit (tubes in a real sign do not strike left to right), and the shuffle is seeded, so the same `seed` renders the same order everywhere. ## Going out `exit` stutters the tubes back off rather than fading them, because an exit is not an entrance played backwards. Set `flickerOnExit={false}` for a clean fade. ## Usage ```tsx import { NeonFlickerText } from "@/remotion/primitives/neon-flicker-text"; <NeonFlickerText text="Open all night" order="random" glowColor="#f472b6" /> ``` A gas-discharge model: unlit tubes are still cold glass, strike probability climbs so the sign resolves, and a lit tube keeps a hum. A settled state with no hum looks like a PNG. ## Props | Name | Type | Default | Description | | --- | --- | --- | --- | | `text` | `string` | - | The sign. | | `glowColor` | `string` | `"#f472b6"` | Colour of the halo around the tube. | | `glowSize` | `number` | `26` | Halo radius in px at full brightness. Four stacked shadows, so it stays soft. | | `offColor` | `string` | `faint pink` | The tube with no gas lit: cold glass, not invisible. | | `offLevel` | `number` | `0.14` | Brightness of an unlit tube, 0–1. | | `hum` | `number` | `0.12` | Depth of the mains hum once the sign has settled. | | `buzz` | `number` | `0.06` | Chance per beat that a settled tube stutters. 0 disables it. | | `flickerOnExit` | `boolean` | `true` | Stutter back off instead of fading cleanly. | | `order` | `"start" \| "end" \| "center" \| "edges" \| "random"` | `"start"` | Which tube strikes first. `random` is the natural fit. | | `staggerInFrames` | `number` | `2` | Frames between one tube striking and the next. | | `durationInFrames` | `number` | `20` | Length of one tube's ignition. Longer sputters more. | | `seed` | `number` | `1` | Seeds the flicker and `order="random"`. | | `exitAtInFrames` | `number` | - | Frame the sign starts cutting out on. | ## Related - [Split Text Chars](https://remotionui.com/docs/components/split-text-chars.md) - [Glow Pulse](https://remotionui.com/docs/components/glow-pulse.md) - [RGB Glitch Text](https://remotionui.com/docs/components/rgb-glitch-text.md) ## Machine-readable references - Props and usage as JSON: https://remotionui.com/ai/components/neon-flicker-text.json - Component index: https://remotionui.com/ai/components.json --- # Perspective Marquee > Perspective Marquee text animation for Remotion. Source: https://remotionui.com/docs/components/perspective-marquee ## Installation ```bash npx remotion-ui@latest add perspective-marquee ``` Horizontal marquee on a receding 3D floor plane: text scrolls toward the horizon with depth fade. Contrast with flat `InfiniteMarquee`. ## Usage ```tsx import { PerspectiveMarquee } from "@/remotion/primitives/perspective-marquee"; <PerspectiveMarquee text="Depth scroll" speed={10} floorTilt={70} perspective={640} /> ``` Unlike InfiniteMarquee, text scrolls on a receding 3D floor with horizon fade, not a flat band. ## Props | Name | Type | Default | Description | | --- | --- | --- | --- | | `text` (required) | `string` | - | Marquee copy. | | `speed` | `number` | `10` | Scroll speed in pixels per frame along the floor plane. | | `gap` | `number` | `72` | Gap between repeated items in px. | | `floorTilt` | `number` | `70` | Floor plane tilt in degrees. Higher values exaggerate depth receding toward the horizon. | | `perspective` | `number` | `640` | Perspective distance in px. Lower values exaggerate depth. | | `showFloorGrid` | `boolean` | `true` | Draw a perspective grid behind the marquee plane. | ## Related - [Infinite Marquee](https://remotionui.com/docs/components/infinite-marquee.md) ## Machine-readable references - Props and usage as JSON: https://remotionui.com/ai/components/perspective-marquee.json - Component index: https://remotionui.com/ai/components.json --- # RGB Glitch Text > Signal-lock RGB glitch text primitive for Remotion. Source: https://remotionui.com/docs/components/rgb-glitch-text ## Installation ```bash npx remotion-ui@latest add rgb-glitch-text ``` Signal-lock text primitive with RGB channel separation, deterministic horizontal slices, scanline accents, and a soft settle glow. ## Usage ```tsx import { RgbGlitchText } from "@/remotion/primitives/rgb-glitch-text"; <RgbGlitchText text="SIGNAL LOCK" glitchDurationInFrames={34} /> ``` ## Props | Name | Type | Default | Description | | --- | --- | --- | --- | | `text` (required) | `string` | - | Readable text rendered under the glitch layers. | | `glitchStartFrame` | `number` | - | Frame where the RGB/slice glitch begins. | | `glitchDurationInFrames` | `number` | - | Length of the signal-lock glitch window. | | `intensity` | `number` | - | Channel offset and slice displacement multiplier, clamped from 0 to 2. | | `sliceCount` | `number` | - | Number of deterministic horizontal glitch slices, clamped from 3 to 9. | | `redChannelColor` | `string` | - | Warm channel split color. | | `cyanChannelColor` | `string` | - | Cool channel split color. | | `accentColor` | `string` | - | Scanline and final slice accent. | ## Related - [Matrix Decode](https://remotionui.com/docs/components/matrix-decode.md) ## Machine-readable references - Props and usage as JSON: https://remotionui.com/ai/components/rgb-glitch-text.json - Component index: https://remotionui.com/ai/components.json --- # Scramble Text > Resolve each character out of random glyph noise, in any stagger order. Install with npx remotion-ui@latest add scramble-text. Source: https://remotionui.com/docs/components/scramble-text ## Installation ```bash npx remotion-ui@latest add scramble-text ``` Every character runs its own scramble on its own clock, then locks onto its target glyph. ```tsx import { ScrambleText } from "@/remotion/primitives/scramble-text"; <ScrambleText text="Resolve out of noise" order="center" charset="symbols" staggerInFrames={6} /> ``` ## Against `matrix-decode` `matrix-decode` resolves strictly left to right from one shared progress value. This one is built on `split-text-chars`, so the resolve follows any stagger order (`center`, `edges`, `random`), and a character's noise stops when *that character* arrives, not when the string is a given percentage decoded. ## Charsets `charset` takes `symbols` (the default), `latin`, `digits`, `blocks`, or any string to use as the pool. `tickInFrames` is how long one noise glyph is held: `1` is a blur, `4` is a slot machine. ## Monospace is the default on purpose A proportional face re-flows the line every time a noise glyph changes width, and the whole word jitters sideways. Override `fontFamily` only with a face whose glyphs share an advance, or accept the wobble. ## Determinism Glyphs are hashed from the character index, the tick and `seed`, never sampled. `Math.random()` would resample on every render pass, so the same frame would scramble differently in the preview and in the render. ## Usage ```tsx import { ScrambleText } from "@/remotion/primitives/scramble-text"; <ScrambleText text="Resolve out of noise" order="center" charset="symbols" /> ``` Per-character clocks, so any stagger order works. `matrix-decode` resolves strictly left to right from one shared progress value. ## Props | Name | Type | Default | Description | | --- | --- | --- | --- | | `text` | `string` | - | The string that resolves. `\n` breaks a line. | | `charset` | `"latin" \| "symbols" \| "digits" \| "blocks" \| string` | `"symbols"` | Glyph pool the noise is drawn from. Any string is used as-is. | | `tickInFrames` | `number` | `2` | Frames one noise glyph is held. 1 is a blur, 4 is a slot machine. | | `scrambleColor` | `string` | - | Colour of the unresolved glyphs. Defaults to `color`. | | `scrambleOpacity` | `number` | `0.72` | Opacity of the unresolved glyphs. | | `scrambleOnExit` | `boolean` | `true` | Scramble again on the way out. | | `order` | `"start" \| "end" \| "center" \| "edges" \| "random"` | `"start"` | Which character resolves first. Document order is never affected. | | `staggerInFrames` | `number` | `2` | Frames between one character resolving and the next. | | `durationInFrames` | `number` | `20` | Length of one character's resolve. | | `delayInFrames` | `number` | `0` | Frames before the first character starts. | | `seed` | `number` | `1` | Seeds the glyph noise and `order="random"`. | | `exitAtInFrames` | `number` | - | Frame the first character starts leaving on. | | `fontFamily` | `string` | `ui-monospace stack` | Monospace by default: a proportional face re-flows on every tick. | ## Related - [Split Text Chars](https://remotionui.com/docs/components/split-text-chars.md) - [Matrix Decode](https://remotionui.com/docs/components/matrix-decode.md) - [Slot Roll](https://remotionui.com/docs/components/slot-roll.md) ## Machine-readable references - Props and usage as JSON: https://remotionui.com/ai/components/scramble-text.json - Component index: https://remotionui.com/ai/components.json --- # Slot Roll > Slot Roll text animation for Remotion. Source: https://remotionui.com/docs/components/slot-roll ## Installation ```bash npx remotion-ui@latest add slot-roll ``` An odometer, not a scramble. Each column owns its own window inside `durationInFrames` (`staggerInFrames` frames apart), so the reel settles left to right, and each one walks the glyph pool forwards from its old character to its new one so it decelerates *into* the answer. The pool is digits when both `from` and `to` are numeric and alphanumeric otherwise: an odometer that rolls through letters is not an odometer. Columns are padded to a common width and rendered monospace so the line cannot shift while it rolls. ## Usage ```tsx import { SlotRoll } from "@/remotion/primitives/slot-roll"; <SlotRoll from="1200" to="9840" /> ``` ## Props | Name | Type | Default | Description | | --- | --- | --- | --- | | `from` (required) | `string` | - | Starting characters. | | `to` (required) | `string` | - | Target characters. | ## Related - [Counter](https://remotionui.com/docs/components/counter.md) ## Machine-readable references - Props and usage as JSON: https://remotionui.com/ai/components/slot-roll.json - Component index: https://remotionui.com/ai/components.json --- # Split Text Chars > Split a string into characters, words, or lines and stagger them in. Install with npx remotion-ui@latest add split-text-chars. Source: https://remotionui.com/docs/components/split-text-chars ## Installation ```bash npx remotion-ui@latest add split-text-chars ``` Splits a string into characters, words, or lines and staggers each unit in. The default look is deliberately plain. This is the foundation the other text effects are built on: it owns the split, the layout, and the stagger, and hands each unit's own 0–1 progress to `renderUnit` so an effect only has to describe one glyph. ## Modes `mode` decides what one animated unit is: `chars`, `words`, or `lines`. The layout is always three levels (line → word → unit) whichever mode is used, so a character split can never break a word across a line. `mode="words"` is a word-by-word reveal; there is no separate component for it. ## Ordering `order` re-ranks which unit animates first without touching document order: `start`, `end`, `center` (middle outward), `edges` (ends inward), or `random`. `random` is seeded, so the same `seed` renders the same shuffle on every machine and every frame. ## Building an effect on it Effects that draw something other than plain text should skip the component and call the hook, which gives identical splitting and stagger semantics: ```tsx import { useSplitText } from "@/remotion/lib/text-split"; const { lines, lastEnterFrame } = useSplitText({ text, mode: "chars", order: "center", }); ``` `lastEnterFrame` is the frame the final unit lands on: size a `<Sequence>` with it rather than guessing. ## Usage ```tsx import { SplitTextChars } from "@/remotion/primitives/split-text-chars"; <SplitTextChars text="Ship it on Friday" mode="chars" order="center" /> // Headless: build your own effect on the same split and stagger. import { useSplitText } from "@/remotion/lib/text-split"; const { lines } = useSplitText({ text, mode: "words" }); ``` The splitting foundation. Other text effects should call `useSplitText()` from `text-split` rather than re-implementing a split. ## Props | Name | Type | Default | Description | | --- | --- | --- | --- | | `text` (required) | `string` | - | Copy to split. `\n` starts a new line. | | `mode` | `"chars" \| "words" \| "lines"` | `"chars"` | What one animated unit is. `words` is a word-by-word reveal. | | `order` | `"start" \| "end" \| "center" \| "edges" \| "random"` | `"start"` | Which unit animates first. Document order is never changed. | | `effect` | `"fade-up" \| "fade" \| "scale" \| "blur" \| "none"` | `"fade-up"` | Built-in look. `none` positions the units and animates nothing. | | `renderUnit` | `(unit: SplitUnitState) => ReactNode` | - | Draws one unit from its own 0-1 progress. This is the composition point for custom text effects. | | `staggerInFrames` | `number` | `2 chars / 4 words / 7 lines` | Frames between consecutive units. | | `durationInFrames` | `number` | `20 chars / 24 words / 28 lines` | Length of one unit's entrance. | | `delayInFrames` | `number` | `0` | Frames before the first unit starts. | | `spring` | `boolean \| 'smooth' \| 'snappy' \| 'bouncy' \| Partial<SpringConfig>` | - | Drive the entrance with a spring instead of the ease-out curve. | | `exit` | `boolean` | `false` | Animate back out, landing inside the surrounding Sequence. | | `exitStaggerInFrames` | `number` | `= staggerInFrames` | Frames between consecutive units leaving. | | `travel` | `number` | `0.42` | `fade-up` travel distance in em. | | `fontSize` | `number` | `84 (scaled)` | Font size in pixels. | | `frame` | `number` | - | Frame override: pass the parent frame inside a Sequence. | ## Related - [Staggered Fade Up](https://remotionui.com/docs/components/staggered-fade-up.md) - [Tracking In](https://remotionui.com/docs/components/tracking-in.md) - [Typewriter](https://remotionui.com/docs/components/typewriter.md) ## Machine-readable references - Props and usage as JSON: https://remotionui.com/ai/components/split-text-chars.json - Component index: https://remotionui.com/ai/components.json --- # Staggered Fade Up > Staggered Fade Up text animation for Remotion. Source: https://remotionui.com/docs/components/staggered-fade-up ## Installation ```bash npx remotion-ui@latest add staggered-fade-up ``` Staggered Fade Up text animation primitive. ## Usage ```tsx import { StaggeredFadeUp } from "@/remotion/primitives/staggered-fade-up"; <StaggeredFadeUp text="Words rise in sequence" /> ``` ## Props | Name | Type | Default | Description | | --- | --- | --- | --- | | `text` (required) | `string` | - | Space-separated words to stagger. | | `staggerInFrames` | `number` | `4` | Delay between words. | ## Related - [Stagger Children](https://remotionui.com/docs/components/stagger-children.md) - [Masked Slide Reveal](https://remotionui.com/docs/components/masked-slide-reveal.md) ## Machine-readable references - Props and usage as JSON: https://remotionui.com/ai/components/staggered-fade-up.json - Component index: https://remotionui.com/ai/components.json --- # Strikethrough Replace > Strikes out one phrase and puts another in its place, on a three-beat correction timeline. Source: https://remotionui.com/docs/components/strikethrough-replace ## Installation ```bash npx remotion-ui@latest add strikethrough-replace ``` Cancels `from` and puts `to` in its place: the correction gesture. The whole component is the timing relationship between three beats, and they run in order rather than as one cross-fade. First the stroke travels the full width of `from` over `strikeDurationInFrames`, on an ease-in-out, because a hand accelerates off the first letter and decelerates onto the last. It is drawn once, at full length, so the old phrase is visibly cancelled before anything moves. Then, after `holdInFrames`, the old phrase lifts by `travel` and fades on an ease-in. The stroke leaves inside that layer rather than being switched off: a rule that vanishes on its own frame reads as a glitch, while one that travels out with the text it cancelled reads as a single object. Last, `replaceDelayInFrames` after the stroke lands, the new phrase rises into the same baseline over `replaceDurationInFrames`. The defaults open the arrival as the departure passes half: the narrow window where the line is neither empty nor doubled. Opacity leads the move in both directions, gone at 62% of the lift and complete at 55% of the rise, so by the time the new phrase is readable the old one has gone, and while both are faint they are travelling in opposite directions. That matters in both directions: shorten `replaceDelayInFrames` far enough and you get two half-tone phrases stacked on one line, which is the single state in which neither is readable; push it past `holdInFrames + departDurationInFrames` and the line goes briefly empty, which reads as a dropout rather than a beat. Both phrases sit in the same grid cell, so the box is as wide as the longer of the two for the whole shot and a centred line never reflows on the swap. The stroke is placed from the baseline, in the font's own x-height: `strikeHeight` is in `ex` units and defaults to `0.5`, which is centred through the lowercase mass. It is an inline box aligned by `vertical-align` rather than a rule positioned inside the line box, and that is the whole point: `top: 50%` or an em offset from the top of the em box is thrown off by half-leading the moment `lineHeight` changes, and is only ever right for the one face it was eyeballed on. Measured at 62px and 28px, and at line heights from 1.0 to 2.2, the stroke's centre lands within 4% of an x-height of the glyph mass centre, at 0.30–0.33em above the baseline. `strikeWeight` is the thickness in em, so it tracks the type size, and the stroke overshoots each end of the phrase slightly: a pen does not stop on the glyph. The layer turns about its centre so `tilt` costs the same deviation at both ends, and the sweep is scaled inside that rotation rather than outside it, since scaling a rotated box stretches it along the frame's axis instead of its own. ## Usage ```tsx import { StrikethroughReplace } from "@/remotion/primitives/strikethrough-replace"; <StrikethroughReplace from="Motion you rent" to="Motion you own" delayInFrames={10} /> ``` The stroke is aligned from the baseline in ex units, so it stays centred through the lowercase mass at any fontSize or lineHeight, and it departs inside the old phrase's layer rather than switching off. Both phrases share one grid cell, so the box holds the width of the longer one and a centred line never reflows on the swap. ## Props | Name | Type | Default | Description | | --- | --- | --- | --- | | `from` (required) | `string` | - | Phrase that gets struck out. | | `to` (required) | `string` | - | Phrase that takes its place. | | `delayInFrames` | `number` | `0` | Frames before the stroke starts travelling. | | `strikeDurationInFrames` | `number` | `16` | Frames the stroke takes to cross the full width of `from`. | | `holdInFrames` | `number` | `4` | Beat held on the struck-out phrase after the stroke lands, before it leaves. | | `departDurationInFrames` | `number` | `12` | Frames the old phrase takes to lift away. Its opacity is gone at 62% of it. | | `replaceDelayInFrames` | `number` | `10` | Frames after the stroke lands before the new phrase starts arriving. Past `holdInFrames + departDurationInFrames` the line goes briefly empty; well below it the two phrases cross-fade. | | `replaceDurationInFrames` | `number` | `20` | Frames the new phrase takes to rise into place. | | `travel` | `number` | `0.42` | Vertical handoff distance in em: the old lifts by it, the new rises from it. | | `strikeWeight` | `number` | `0.07` | Stroke thickness in em, so it tracks the type size. | | `strikeHeight` | `number` | `0.5` | Stroke height above the baseline in `ex`, units of the font's own x-height. 0.5 is centred through the lowercase mass. | | `tilt` | `number` | `-0.6` | Stroke angle in degrees off level: a hand does not rule it flat. | | `color` | `string` | `"#ececec"` | Text colour. | | `strikeColor` | `string` | `"#e8b86d"` | Stroke colour. | | `replaceColor` | `string` | - | Ink of the replacement. Defaults to `color`. | | `fontSize` | `number` | `scaled 72px` | Text size in pixels. | | `fontWeight` | `number` | `600` | Text weight. | | `fontFamily` | `string` | - | Font family for both phrases. | | `textAlign` | `"left" \| "center" \| "right"` | `"center"` | Alignment of both phrases inside the shared box. | | `style` | `CSSProperties` | - | Styles merged onto the wrapper span. | ## Related - [Marker Highlight](https://remotionui.com/docs/components/marker-highlight.md) - [Typewriter](https://remotionui.com/docs/components/typewriter.md) - [Slot Roll](https://remotionui.com/docs/components/slot-roll.md) ## Machine-readable references - Props and usage as JSON: https://remotionui.com/ai/components/strikethrough-replace.json - Component index: https://remotionui.com/ai/components.json --- # Stroke to Fill Text > Draw type as an outline, then flood each letter solid. Install with npx remotion-ui@latest add stroke-to-fill-text. Source: https://remotionui.com/docs/components/stroke-to-fill-text ## Installation ```bash npx remotion-ui@latest add stroke-to-fill-text ``` Outline first, then a flood that travels through the line. ```tsx import { StrokeToFillText } from "@/remotion/primitives/stroke-to-fill-text"; <StrokeToFillText text="Ship faster with source" strokeColor="#e8b86d" fillColor="#f4f4f5" staggerInFrames={5} direction="up" /> ``` ## The outline is not staggered; the fill is They ran on one clock in the first cut, and a slow stagger then left the un-flooded half of the line completely absent. The word looked truncated rather than outlined. The whole outline now draws once across `outlineInFrames`, and the stagger is spent entirely on the flood, which is the part the eye is meant to follow. ## Two layers of the same span The outline and the fill are the same `<span>` of real text stacked on itself, so they are guaranteed to be the same glyph at the same metrics. Tracing a fill with a second element positioned by hand drifts by a fraction of a pixel and the outline starts reading as a drop shadow. The flood is a gradient mask rather than a `background-clip` trick, because a mask can move, and the moving edge is the effect. `direction` takes `up`, `down`, `left` or `right`; `edgeSoftness` is how wet that edge is. ## Weights `strokeWidth` is the outline in px and `strokeRetain` is the share of it left once the letter is full: keeping a little makes the fill read as ink inside a drawn letter instead of as a swap between two typefaces. ## Usage ```tsx import { StrokeToFillText } from "@/remotion/primitives/stroke-to-fill-text"; <StrokeToFillText text="Ship faster with source" strokeColor="#e8b86d" staggerInFrames={5} /> ``` The outline is unstaggered and the fill is staggered. Running both on one clock leaves the un-flooded half of the line absent, which reads as truncated type. ## Props | Name | Type | Default | Description | | --- | --- | --- | --- | | `text` | `string` | - | The line that outlines and then fills. | | `strokeWidth` | `number` | `2` | Outline weight in px, before it thins into the fill. | | `strokeColor` | `string` | - | Outline colour. Defaults to `color`. | | `fillColor` | `string` | - | Colour the letter fills with. Defaults to `color`. | | `direction` | `"up" \| "down" \| "left" \| "right"` | `"up"` | Which way the fill floods the letter. | | `edgeSoftness` | `number` | `0.12` | Softness of the fill edge, as a share of the glyph. 0 is a hard line. | | `strokeRetain` | `number` | `0.35` | Share of the outline weight left once the letter is full. | | `outlineInFrames` | `number` | `16` | Frames the outline takes to draw. It arrives as a whole word, unstaggered. | | `staggerInFrames` | `number` | `2` | Frames between one letter flooding and the next. | | `durationInFrames` | `number` | `20` | Length of one letter's flood. | | `delayInFrames` | `number` | `0` | Frames before the outline starts. | | `order` | `"start" \| "end" \| "center" \| "edges" \| "random"` | `"start"` | Which letter floods first. | | `exitAtInFrames` | `number` | - | Frame the fill starts draining on. | ## Related - [Split Text Chars](https://remotionui.com/docs/components/split-text-chars.md) - [Text Mask Video](https://remotionui.com/docs/components/text-mask-video.md) - [Path Draw](https://remotionui.com/docs/components/path-draw.md) ## Machine-readable references - Props and usage as JSON: https://remotionui.com/ai/components/stroke-to-fill-text.json - Component index: https://remotionui.com/ai/components.json --- # Text Mask Video > Play video, a still, or a gradient inside letterforms, with a wipe reveal. Install with npx remotion-ui@latest add text-mask-video. Source: https://remotionui.com/docs/components/text-mask-video ## Installation ```bash npx remotion-ui@latest add text-mask-video ``` Media seen through a word. ```tsx import { staticFile } from "remotion"; import { TextMaskVideo } from "@/remotion/primitives/text-mask-video"; <TextMaskVideo text={"IN\nMOTION"} src={staticFile("clips/skyline.mp4")} fontSize={172} fontWeight={900} reveal="left" /> ``` ## Why a clip path, not `background-clip` `background-clip: text` only takes a paint, so it can carry a gradient and it can carry an image, but it can never carry a video. Clipping a real element with an SVG `clipPath` of `<text>` means one code path covers all three: the media underneath is a normal `<OffthreadVideo>` that seeks and trims like any other. Set `media` explicitly to force a mode. It defaults to `video` when `src` is set and `gradient` when it is not. ## The reveal is a second clip One element gets one `clip-path`, so the wipe lives on a child of the letter-clipped layer. `reveal` takes `left`, `right`, `up`, `down` or `none`, runs on the entrance and unwinds on the exit. ## Sizing `width` and `height` are the clip's coordinate space and the type is positioned inside it arithmetically. Nothing is measured: a measured layout renders one thing on frame 0 of a headless render and another on frame 1. Both default to multiples of `fontSize`; set them when the copy is long. ## Footage almost always needs lifting A clip that reads fine full-frame is usually too dark once it is only visible inside letterforms. `mediaFilter` takes any CSS filter: `brightness(2.2) saturate(1.5)` is a reasonable starting point for night footage. ## Usage ```tsx import { staticFile } from "remotion"; import { TextMaskVideo } from "@/remotion/primitives/text-mask-video"; <TextMaskVideo text={"IN\nMOTION"} src={staticFile("clips/skyline.mp4")} fontSize={172} fontWeight={900} /> ``` An SVG clipPath on a real element, not `background-clip: text`, which only takes a paint, so it can never carry a video. ## Props | Name | Type | Default | Description | | --- | --- | --- | --- | | `text` | `string` | - | The letterforms the media is seen through. `\n` breaks a line. | | `src` | `string` | - | Video or image source. Wrap local files in `staticFile()`. | | `media` | `"video" \| "image" \| "gradient"` | `video with a src, gradient without` | Which layer is drawn behind the letters. | | `gradient` | `string` | - | Any CSS background, used by `media="gradient"`. | | `mediaFilter` | `string` | - | CSS filter on the media. Footage is usually too dark inside letterforms. | | `reveal` | `"left" \| "right" \| "up" \| "down" \| "none"` | `"left"` | Which way the letters are uncovered. | | `width` | `number` | - | Clip coordinate space. Defaults to a multiple of `fontSize`. | | `height` | `number` | - | Clip coordinate space. Defaults from the line count. | | `drift` | `number` | `26` | Peak sideways travel of the media, in px. | | `zoom` | `number` | `0.12` | Extra scale the media breathes through. 0 holds it still. | | `startFrom` | `number` | - | Frame offset into the video. | | `durationInFrames` | `number` | `30` | Length of the reveal. | | `delayInFrames` | `number` | `0` | Frames before the reveal starts. | | `exitAtInFrames` | `number` | - | Frame the reveal starts unwinding on. | ## Related - [Light Sweep Text](https://remotionui.com/docs/components/light-sweep-text.md) - [SVG Mask Reveal](https://remotionui.com/docs/components/svg-mask-reveal.md) - [Stroke to Fill Text](https://remotionui.com/docs/components/stroke-to-fill-text.md) ## Machine-readable references - Props and usage as JSON: https://remotionui.com/ai/components/text-mask-video.json - Component index: https://remotionui.com/ai/components.json --- # Tracking In > Tracking In text animation for Remotion. Source: https://remotionui.com/docs/components/tracking-in ## Installation ```bash npx remotion-ui@latest add tracking-in ``` Tracking In text animation primitive. ## Usage ```tsx import { TrackingIn } from "@/remotion/primitives/tracking-in"; <TrackingIn text="Tracking snap" /> ``` ## Props | Name | Type | Default | Description | | --- | --- | --- | --- | | `text` (required) | `string` | - | Headline with tracking collapse. | ## Related - [Blur Focus In](https://remotionui.com/docs/components/blur-focus-in.md) - [Typewriter](https://remotionui.com/docs/components/typewriter.md) ## Machine-readable references - Props and usage as JSON: https://remotionui.com/ai/components/tracking-in.json - Component index: https://remotionui.com/ai/components.json --- # Typewriter > Typewriter reveal with rhythm, pauses, looping, and a caret that only blinks at rest. Source: https://remotionui.com/docs/components/typewriter ## Installation ```bash npx remotion-ui@latest add typewriter ``` Types a string out under a live caret. The caret holds solid while keys are landing and only blinks once it rests. A caret that blinks mid-word looks like a loading state, not typing. The full block is measured up front, so a wrapping line does not shunt everything under it down a row mid-sentence. Use `[pause:0.5]` inside `text` to hold at any point. `humanize` varies the key rhythm, `respectPunctuation` rests on sentence punctuation, and `loop` types, holds, deletes and repeats. ## Usage ```tsx import { Typewriter } from "@/remotion/primitives/typewriter"; <Typewriter text="Build videos with React.[pause:0.5] One frame at a time." charFrames={2} humanize respectPunctuation cursorStyle="block" /> ``` The caret holds solid while keys land and only blinks once it rests. Inline [pause:0.5] markers are stripped from the rendered text. ## Props | Name | Type | Default | Description | | --- | --- | --- | --- | | `text` (required) | `string` | - | Full string to reveal character by character. Use [pause:0.5] for inline pauses. | | `charFrames` | `number` | - | Frames per character (preferred over durationInFrames). Values below 1 type more than one character a frame. | | `durationInFrames` | `number` | `60` | Total duration when charFrames is omitted. | | `delayInFrames` | `number` | `0` | Frames before typing begins. | | `pauseAfter` | `string` | - | Pause after this substring is typed. | | `pauseSeconds` | `number` | `0.6` | Length of the pauseAfter pause in seconds. | | `showCursor` | `boolean` | `true` | Show the caret. | | `cursorBlinkFrames` | `number` | `30` | Caret blink cycle length in frames, used while it rests. | | `cursorColor` | `string` | - | Caret colour. Defaults to the text colour. | | `cursorWidth` | `number` | - | Caret width in pixels (bar/underscore only). | | `cursorStyle` | `"bar" \| "block" \| "underscore"` | `"bar"` | Caret shape. | | `humanize` | `boolean` | `false` | Uneven key rhythm: the difference between typing and a progress bar. | | `respectPunctuation` | `boolean` | `false` | Pause automatically after . ! ? ; : , | | `punctuationPauseSeconds` | `number` | `0.25` | Length of automatic punctuation pauses. | | `loop` | `boolean` | `false` | Type, pause, backspace, and repeat. | | `loopPauseSeconds` | `number` | `1` | Pause at full text before backspacing. | | `backspaceCharFrames` | `number` | `1` | Frames per character when backspacing. | | `reserveSpace` | `boolean` | `true` | Measure the full block up front so a wrapping line never reflows mid-sentence. | | `fontSize` | `number` | `scaled 84px` | Text size in pixels. | | `fontWeight` | `number` | `600` | Text weight. | | `color` | `string` | `"#ececec"` | Text colour. | | `fontFamily` | `string` | - | Font family for the typed text. | | `style` | `CSSProperties` | - | Styles merged onto the text span. | ## Related - [Marker Highlight](https://remotionui.com/docs/components/marker-highlight.md) - [Counter](https://remotionui.com/docs/components/counter.md) ## Machine-readable references - Props and usage as JSON: https://remotionui.com/ai/components/typewriter.json - Component index: https://remotionui.com/ai/components.json --- # Variable Font Morph > Sweep a variable font's weight and width axes across a line, one character at a time. Install with npx remotion-ui@latest add variable-font-morph. Source: https://remotionui.com/docs/components/variable-font-morph ## Installation ```bash npx remotion-ui@latest add variable-font-morph ``` A weight wave travelling through a headline. ```tsx import { VariableFontMorph } from "@/remotion/primitives/variable-font-morph"; <VariableFontMorph text="Weight in motion" weight={[200, 900]} width={[85, 115]} oscillate periodInFrames={46} /> ``` ## One position, every axis The axis position is a single 0–1 value per character, spent on every requested axis at once. A real variable face moves `wght` and `wdth` together; driving them from separate clocks makes the type look broken rather than variable. `weight`, `width` and `slant` are the registered axes. Anything else goes through `axes` by four-letter tag: ```tsx <VariableFontMorph text="Optical" axes={{ opsz: [14, 96] }} /> ``` ## Oscillate, or arrive By default the axes ramp from `from` to `to` with the entrance and stay there. `oscillate` keeps them travelling between the two ends forever, offset per character by `phaseStep` so the wave moves along the line. ## Reserved advance widths Weight and width both change a glyph's advance, so a centred line re-centres itself every frame and the whole string jitters horizontally as the wave passes through it. `reserveSpace`, on by default, lays each character out in an `inline-grid` cell sized by a hidden copy at the heaviest, widest setting, and centres the animated glyph inside that fixed cell. The line cannot move. Turn it off if you want the type to breathe. ## Load a real variable face `font-variation-settings` does nothing on a face without those axes, so the `wght` and `wdth` values are also written to `font-weight` and `font-stretch`. A family shipping discrete weights therefore steps between them instead of gliding (visibly coarser, but never frozen), and it is *not* what this component is for. Load a variable face at module scope and pass its family: ```tsx import { loadFont } from "@remotion/google-fonts/Inter"; const { fontFamily } = loadFont("normal", { weights: ["100", "200", "300", "400", "500", "600", "700", "800", "900"], subsets: ["latin"], }); <VariableFontMorph text="Weight in motion" fontFamily={fontFamily} /> ``` Google serves Inter as a single variable woff2 (every one of those nine weight URLs is the same file), so the `wght` axis has somewhere continuous to travel. ## Usage ```tsx import { VariableFontMorph } from "@/remotion/primitives/variable-font-morph"; <VariableFontMorph text="Weight in motion" weight={[200, 900]} oscillate /> ``` One 0–1 position drives every axis at once. On a static face the values fall back to `font-weight`/`font-stretch`, which steps rather than glides. ## Props | Name | Type | Default | Description | | --- | --- | --- | --- | | `text` | `string` | - | The line whose axes are swept. | | `weight` | `[number, number]` | `[200, 800]` | `wght` axis. Also mirrored onto `font-weight`. | | `width` | `[number, number]` | - | `wdth` axis in percent. Also mirrored onto `font-stretch`. | | `slant` | `[number, number]` | - | `slnt` axis in degrees. Negative leans right, per the spec. | | `axes` | `Record<string, [number, number]>` | - | Any further axes by four-letter tag, e.g. `{ opsz: [14, 96] }`. | | `oscillate` | `boolean` | `false` | Keep travelling between the two ends instead of landing on `to`. | | `periodInFrames` | `number` | `60` | Frames for one there-and-back when oscillating. | | `phaseStep` | `number` | `0.55` | Radians of offset per character along the wave. | | `staggerInFrames` | `number` | `2` | Frames between one character starting and the next. | | `durationInFrames` | `number` | `20` | Length of one character's ramp. | | `delayInFrames` | `number` | `0` | Frames before the first character starts. | | `fontFamily` | `string` | - | Pass a variable face here: the fallback only steps between static weights. | | `reserveSpace` | `boolean` | `true` | Lay each glyph out in a cell sized by a hidden copy at the heaviest, widest setting. Weight changes advance widths, so without it a centred line re-centres itself every frame. | ## Related - [Split Text Chars](https://remotionui.com/docs/components/split-text-chars.md) - [Wave Text](https://remotionui.com/docs/components/wave-text.md) - [Tracking In](https://remotionui.com/docs/components/tracking-in.md) ## Machine-readable references - Props and usage as JSON: https://remotionui.com/ai/components/variable-font-morph.json - Component index: https://remotionui.com/ai/components.json --- # Wave Text > Run a sine along a line of type, one character at a time. Install with npx remotion-ui@latest add wave-text. Source: https://remotionui.com/docs/components/wave-text ## Installation ```bash npx remotion-ui@latest add wave-text ``` An ambient loop, not an entrance. ```tsx import { WaveText } from "@/remotion/primitives/wave-text"; <WaveText text="Ride the sine" amplitude={0.2} wavelength={5} periodInFrames={44} /> ``` ## It never settles The wave is a function of the frame, so there is no end state to reach. The entrance is still there underneath (`split-text-chars` owns it, and every `delayInFrames` / `staggerInFrames` / `exit` prop works as usual), and the amplitude is scaled by each character's own arrival progress, so a character does not start bobbing before it has landed and the line lowers as one on the way out. ## Phase follows document order Phase is keyed off the character's index in the string, not off its stagger rank. A wave that travels in the stagger order of `order="random"` is not a wave. ## Shape `amplitude` is the peak lift in em, `wavelength` is how many characters one full wave spans, and `periodInFrames` is how long a cycle takes. `scale` and `shade` add depth by growing and brightening the crest: set both to `0` for a flat displacement. ## Usage ```tsx import { WaveText } from "@/remotion/primitives/wave-text"; <WaveText text="Ride the sine" amplitude={0.2} wavelength={5} /> ``` Ambient: the wave is a function of the frame and never settles. Phase follows document order, not the stagger rank. ## Props | Name | Type | Default | Description | | --- | --- | --- | --- | | `text` | `string` | - | The line the wave runs along. | | `amplitude` | `number` | `0.16` | Peak displacement, in em of the font size. | | `wavelength` | `number` | `6` | Characters per full wave. Higher spreads the crest wider. | | `periodInFrames` | `number` | `48` | Frames for one full cycle. | | `direction` | `"forward" \| "backward"` | `"forward"` | Travel direction along the line. | | `scale` | `number` | `0.06` | Extra scale on the crest, so it reads as depth rather than jitter. | | `shade` | `number` | `0.25` | How far the trough fades. 0 keeps every character at full opacity. | | `staggerInFrames` | `number` | `2` | Frames between one character arriving and the next. | | `durationInFrames` | `number` | `20` | Length of one character's entrance. | | `delayInFrames` | `number` | `0` | Frames before the first character arrives. | | `exitAtInFrames` | `number` | - | Frame the line starts leaving on. The wave lowers with it. | ## Related - [Split Text Chars](https://remotionui.com/docs/components/split-text-chars.md) - [Infinite Marquee](https://remotionui.com/docs/components/infinite-marquee.md) - [Variable Font Morph](https://remotionui.com/docs/components/variable-font-morph.md) ## Machine-readable references - Props and usage as JSON: https://remotionui.com/ai/components/wave-text.json - Component index: https://remotionui.com/ai/components.json --- # Backgrounds > Full-frame stage layers: gradients, grain, light, and particles that sit behind a scene. Source: https://remotionui.com/docs/components/backgrounds Backgrounds fill the frame and move slowly enough to stay behind your content. Put one first inside an `AbsoluteFill` and layer the scene on top. ## Components - [Animated Noise Grain](https://remotionui.com/docs/components/animated-noise-grain.md): Film grain that boils, without generating noise per frame. Install with npx remotion-ui@latest add animated-noise-grain. - [Aurora Background](https://remotionui.com/docs/components/aurora-bg.md): Drifting aurora curtains. Install with npx remotion-ui@latest add aurora-bg. - [Caustics Background](https://remotionui.com/docs/components/caustics-bg.md): Underwater light caustics, with no shader and no per-frame noise. Install with npx remotion-ui@latest add caustics-bg. - [Dynamic Grid](https://remotionui.com/docs/components/dynamic-grid.md): Subtle drifting dot and line grid background. - [Light Rays](https://remotionui.com/docs/components/light-rays.md): Volumetric shafts fanning out of a point and drifting. Install with npx remotion-ui@latest add light-rays. - [Mesh Gradient Background](https://remotionui.com/docs/components/mesh-gradient-bg.md): Living gradient blobs on a dark stage. - [Particle Field](https://remotionui.com/docs/components/particle-field.md): Ambient particles drifting with depth. Install with npx remotion-ui@latest add particle-field. - [Topographic Lines Background](https://remotionui.com/docs/components/topographic-lines-bg.md): Contour lines drifting outward, like elevation rising. Install with npx remotion-ui@latest add topographic-lines-bg. --- # Animated Noise Grain > Film grain that boils, without generating noise per frame. Install with npx remotion-ui@latest add animated-noise-grain. Source: https://remotionui.com/docs/components/animated-noise-grain ## Installation ```bash npx remotion-ui@latest add animated-noise-grain ``` An emulsion pass for anything that looks too clean. ```tsx import { AnimatedNoiseGrain } from "@/remotion/primitives/animated-noise-grain"; <AnimatedNoiseGrain opacity={0.18}> <YourScene /> </AnimatedNoiseGrain> ``` Pass `children` to grain a subtree, or drop it into a stack with no children to grain everything beneath it. ## How the noise is made once The noise itself is a single stitched `feTurbulence` tile baked into a data URI. The browser rasterises that URL the first time it decodes it and then caches it like any other image, and because the URL depends only on props, never on `frame`, a 300-frame render rasterises it once. What changes every step is where the tile is sampled from and which way it is flipped: a hashed sub-tile offset plus one of four mirrorings. The tile stitches, so the offset wraps invisibly, and the flip breaks the translation so the eye reads new grain rather than a sliding texture. ## What that saves Rendering this page's 120-frame preview at 960x540: | Variant | Wall clock | CPU | | --- | --- | --- | | No grain | 7.5s | 20s | | Grain, cached tile (shipped) | 15.7s | 78s | | Grain, `feTurbulence` re-seeded every frame | 27.8s | 144s | Two things to read out of that. Regenerating the noise per frame nearly doubles the render again, which is the whole reason for the cached tile. And grain is not free even when it is cached: it takes the encoder from a 206 kB file to a 15.1 MB one, because noise is incompressible. Most of the gap between the first two rows is H.264, not rendering. Budget for the bitrate, not just the frames. ## Blend mode matters more than opacity `overlay` is the default and the right choice over footage: it pivots around mid grey and leaves the extremes alone. Over a near-black plate it does nothing at all, because there is nothing to modulate. Use `screen` there: it lifts the blacks, which is both what makes the grain visible and what grain does in the shadows of a real print. This is worth knowing because the failure is silent. The first cut of this page's preview measured as a completely static frame while the component was working perfectly. ## Stock `holdInFrames` is the film-stock control. Grain that changes on every frame of a 30fps render looks like video noise; holding each pattern for two frames gives the coarser chatter of film shot at 15fps. `size` and `density` set the grain's coarseness. `vignette` adds a second, edge-masked pass, because real film grain is heaviest away from the centre. An even field of grain reads as a digital filter. For phosphor rather than emulsion, see `scanline-crt`. The two stack. ## Usage ```tsx import { AnimatedNoiseGrain } from "@/remotion/primitives/animated-noise-grain"; <AnimatedNoiseGrain opacity={0.18}> <YourScene /> </AnimatedNoiseGrain> ``` The noise is one stitched `feTurbulence` tile baked into a data URI, so the browser rasterises it once for the whole render. Per-frame variation comes from a hashed sub-tile offset plus one of four mirrorings, never from regenerating noise. Rendering the preview costs about 3% more per frame than the same frame without it. ## Props | Name | Type | Default | Description | | --- | --- | --- | --- | | `children` | `ReactNode` | - | Content the grain sits over. Omit to use it as a bare overlay. | | `opacity` | `number` | `0.18` | Grain strength. Film sits around 0.12-0.25; above 0.4 reads as damage. | | `size` | `number` | `220` | Tile size on screen, in px. Larger grain is coarser and cheaper. | | `density` | `number` | `0.85` | Noise frequency inside the tile. Higher is finer. | | `detail` | `number` | `3` | Octaves of noise. 1 is smooth, 4 is gritty. | | `holdInFrames` | `number` | `2` | Frames each pattern is held. 2 gives the 15fps chatter of film. | | `blendMode` | `CSS mix-blend-mode` | `"overlay"` | How the grain composites. Use `screen` over a near-black plate: overlay pivots on mid grey and does nothing to blacks. | | `colored` | `boolean` | `false` | Keep the noise coloured instead of desaturating it to silver. | | `vignette` | `number` | `0.35` | Extra grain in the corners, where film grain actually lives. | | `seed` | `number` | `1` | Changes the pattern without changing any other prop. | ## Related - [Scanline CRT](https://remotionui.com/docs/components/scanline-crt.md) - [Mesh Gradient Background](https://remotionui.com/docs/components/mesh-gradient-bg.md) - [Light Rays](https://remotionui.com/docs/components/light-rays.md) ## Machine-readable references - Props and usage as JSON: https://remotionui.com/ai/components/animated-noise-grain.json - Component index: https://remotionui.com/ai/components.json --- # Aurora Background > Drifting aurora curtains. Install with npx remotion-ui@latest add aurora-bg. Source: https://remotionui.com/docs/components/aurora-bg ## Installation ```bash npx remotion-ui@latest add aurora-bg ``` A full-frame stage layer of aurora curtains. ```tsx import { AuroraBg } from "@/remotion/primitives/aurora-bg"; <AbsoluteFill> <AuroraBg ribbonCount={4} /> <YourScene /> </AbsoluteFill> ``` ## Where it sits Ribbons, not blobs: `mesh-gradient-bg` owns blobs, and the difference is structural rather than stylistic. A blob is a radial gradient that moves; a ribbon is a tapered path whose *shape* is recomputed every frame. If what you want is colour that drifts, use the gradient. If you want something that folds, use this. Set `backgroundColor="transparent"` to lay the curtains over footage instead of over their own plate. ## Why it does not look like a smear Three things, and the layer falls apart without any of them. Each curtain tapers to nothing at both ends. A constant-height shape reads as a painted stripe no matter how it undulates. Each curtain is filled with a vertical gradient that is brightest along its lower edge, composited on `screen`, so overlapping curtains add light instead of stacking alpha and going muddy. And `striation` runs vertical rays through the whole band. Real aurora has ray structure; without it a curtain is a coloured blur. The mask is applied after the blur, so the rays stay crisp while the folds stay soft. ## Keep the blur down `blur` is the prop that decides whether this reads as curtains or as blobs. Much above 20 and the fold structure is gone. The first cut of this component ran at 34 and the preview was indistinguishable from a mesh gradient. ## Motion There is no entrance; the content on top of a background owns the entrance. Every fold runs on two clocks at once, 2.3s beaten against 1.1s. A single travelling wave repeats exactly once per period, which is enough for two frames a second and a half apart to hold the same shape. Beating two periods against each other means a curtain never returns to a shape it has already held. `speed` scales all of it, and `speed={0}` freezes the sky. ## Usage ```tsx import { AuroraBg } from "@/remotion/primitives/aurora-bg"; <AbsoluteFill> <AuroraBg ribbonCount={4} /> <YourScene /> </AbsoluteFill> ``` Tapered paths whose shape changes every frame, not gradients that move. That is the line between this and `mesh-gradient-bg`. Two incommensurate fold clocks (2.3s against 1.1s) mean a curtain never repeats a shape. Background layer, so it has no entrance. ## Props | Name | Type | Default | Description | | --- | --- | --- | --- | | `backgroundColor` | `string` | `"#050505"` | Plate behind the curtains. `transparent` layers them over footage. | | `colors` | `string[]` | `["#e4ac59", "#e07a5f", "#c2557a"]` | Curtain colours, cycled. | | `ribbonCount` | `number` | `4` | How many curtains. | | `amplitude` | `number` | `9` | Vertical travel of a fold, in percent of the frame. | | `thickness` | `number` | `15` | Curtain height at its thickest point, in percent. | | `centerY` | `number` | `46` | Where the band sits, in percent of the frame height. | | `spread` | `number` | `34` | How far the curtains spread around `centerY`. | | `speed` | `number` | `1` | Drift speed. 0 freezes the sky. | | `blur` | `number` | `14` | Softness in px. Much above 20 and the folds become blobs. | | `intensity` | `number` | `1.3` | Overall brightness. | | `horizonGlow` | `number` | `0.5` | Ground glow under the band. 0 removes it. | | `striation` | `number` | `0.55` | Vertical ray structure through the curtains, 0-1. | | `seed` | `number` | `1` | Changes the fold layout without changing any other prop. | ## Related - [Mesh Gradient Background](https://remotionui.com/docs/components/mesh-gradient-bg.md) - [Light Rays](https://remotionui.com/docs/components/light-rays.md) - [Particle Field](https://remotionui.com/docs/components/particle-field.md) ## Machine-readable references - Props and usage as JSON: https://remotionui.com/ai/components/aurora-bg.json - Component index: https://remotionui.com/ai/components.json --- # Caustics Background > Underwater light caustics, with no shader and no per-frame noise. Install with npx remotion-ui@latest add caustics-bg. Source: https://remotionui.com/docs/components/caustics-bg ## Installation ```bash npx remotion-ui@latest add caustics-bg ``` The bright web that light makes on the bottom of a pool. ```tsx import { CausticsBg } from "@/remotion/primitives/caustics-bg"; <AbsoluteFill> <CausticsBg scale={130} /> <YourScene /> </AbsoluteFill> ``` ## How it is made Five wave trains, tilted at angles that share no common divisor, added together with `plus-lighter` so they combine the way light does. A slow, large-scale swell multiplies the sum so it only reaches full brightness in patches. Then `contrast()` thresholds the result into the sharp-edged web. No shader, no canvas, no noise texture regenerated per frame: six `div`s and one filter chain. ## Why five layers Two crossed wave trains give a plaid. Three give a hexagonal lattice, and detuning their wavelengths does not help: the pattern is still periodic in two directions and the eye finds the tiling immediately. Five incommensurate directions make the sum *quasi*-periodic, so it never repeats. That is the difference between water and wallpaper, and both intermediate cuts of this component were rejected on exactly that point. ## Tuning `contrast` is the important one. Too low and the web dissolves back into the plaid it came from; too high and the bright regions saturate and the cells invert into dark blobs on a light field, which is the opposite of a caustic. Around 3-4 is the usable band. The filter order is blur, then contrast. Thresholding first and blurring after gives soft-edged blobs instead of a web. ## Motion Each train slides at its own rate and rocks by a few degrees on its own clock, so the cells stretch and pinch rather than sliding as a rigid pattern. Two trains on the same clock would swim in lockstep and give the whole thing away. `speed={0}` freezes the surface. There is no entrance; this is a stage layer. ## Usage ```tsx import { CausticsBg } from "@/remotion/primitives/caustics-bg"; <AbsoluteFill> <CausticsBg scale={130} /> <YourScene /> </AbsoluteFill> ``` Five wave trains at incommensurate angles, added with `plus-lighter`, dimmed in patches by a slow swell, then thresholded with `contrast()`. Three trains, at any wavelengths, make a lattice, and a lattice reads as wallpaper; five make the sum quasi-periodic. No shader and no per-frame noise. ## Props | Name | Type | Default | Description | | --- | --- | --- | --- | | `backgroundColor` | `string` | `deep water gradient` | Water behind the light. `transparent` layers the caustics over footage. | | `color` | `string` | `"#9fe8ff"` | Colour of the light itself. | | `scale` | `number` | `120` | Cell size, in px. | | `speed` | `number` | `1` | Swim speed. 0 freezes the surface. | | `contrast` | `number` | `3.4` | How hard the cells threshold. Too low and the web dissolves into plaid. | | `blur` | `number` | `8` | Softness of a cell edge, in px. | | `intensity` | `number` | `1` | Overall brightness. | | `falloff` | `number` | `0.55` | Depth shading down the frame. 0 lights it evenly. | ## Related - [Mesh Gradient Background](https://remotionui.com/docs/components/mesh-gradient-bg.md) - [Light Rays](https://remotionui.com/docs/components/light-rays.md) - [Aurora Background](https://remotionui.com/docs/components/aurora-bg.md) ## Machine-readable references - Props and usage as JSON: https://remotionui.com/ai/components/caustics-bg.json - Component index: https://remotionui.com/ai/components.json --- # Dynamic Grid > Subtle drifting dot and line grid background. Source: https://remotionui.com/docs/components/dynamic-grid ## Installation ```bash npx remotion-ui@latest add dynamic-grid ``` Layer a slow-moving dot grid and faint line grid for depth behind scene content. ## Usage ```tsx import { DynamicGrid } from "@/remotion/primitives/dynamic-grid"; <DynamicGrid spacing={64} /> ``` ## Props | Name | Type | Default | Description | | --- | --- | --- | --- | | `spacing` | `number` | `64` | Grid cell size in px. | | `lineColor` | `string` | `"rgba(255,255,255,0.1)"` | Grid line color. | | `sweepColor` | `string` | `"rgba(232,184,109,0.55)"` | Diagonal light-sweep color. | | `speed` | `number` | `0.4` | Grid drift speed in px per frame. | | `sweepDurationInFrames` | `number` | `150` | Frames for one full sweep loop. | ## Related - [Mesh Gradient Background](https://remotionui.com/docs/components/mesh-gradient-bg.md) ## Machine-readable references - Props and usage as JSON: https://remotionui.com/ai/components/dynamic-grid.json - Component index: https://remotionui.com/ai/components.json --- # Light Rays > Volumetric shafts fanning out of a point and drifting. Install with npx remotion-ui@latest add light-rays. Source: https://remotionui.com/docs/components/light-rays ## Installation ```bash npx remotion-ui@latest add light-rays ``` A full-frame stage layer of god rays. ```tsx import { LightRays } from "@/remotion/primitives/light-rays"; <AbsoluteFill> <LightRays originX={28} originY={-14} angle={20} spread={56} /> <YourScene /> </AbsoluteFill> ``` ## Where it sits Shafts, not blobs: `mesh-gradient-bg` owns blobs. And full-frame, unlike `light-sweep-text`, which is a specular pass clipped to letterforms. Set `backgroundColor="transparent"` to lay it over footage instead of over its own plate. ## Why it does not look printed Each shaft is a tapered wedge composited on `screen`, so overlapping shafts add the way light does instead of stacking alpha and going muddy. Width, brightness and sway period are all hashed per index: an evenly spaced, evenly bright fan reads as a printed sunburst rather than as light in air. An odd `rayCount` avoids a symmetric seam down the middle of the fan. ## Aiming it `originX` / `originY` are percentages of the frame and are usually outside it: the default puts the source above the top edge. `angle` points the fan, `spread` is its total width in degrees, and `bloom` is the halo at the source. ## Motion There is no entrance: every shaft sways on its own period and the fan drifts on a longer one. `speed` scales all of it, and `speed={0}` freezes the fan into a still image, which is occasionally what a poster frame wants. Keep `blur` moderate. A heavy blur swallows the sway. The first cut of this component moved one to two degrees under an 18px blur and measured as a still frame on the preview audit. ## Usage ```tsx import { LightRays } from "@/remotion/primitives/light-rays"; <AbsoluteFill> <LightRays originX={28} originY={-14} angle={20} spread={56} /> <YourScene /> </AbsoluteFill> ``` Tapered wedges on `screen`, with width, brightness and sway period hashed per index: an even fan reads as a printed sunburst. Background layer, so it has no entrance. ## Props | Name | Type | Default | Description | | --- | --- | --- | --- | | `backgroundColor` | `string` | `"#080810"` | Plate behind the rays. `transparent` layers them over footage. | | `color` | `string` | `"#e8b86d"` | Colour of the shafts. | | `rayCount` | `number` | `11` | How many shafts. Odd counts avoid a symmetric seam down the middle. | | `spread` | `number` | `52` | Total fan angle, in degrees. | | `angle` | `number` | `22` | Direction the fan points. 0 points straight down. | | `originX` | `number` | `26` | Source position in percent of the frame. Usually outside it. | | `originY` | `number` | `-12` | Source position in percent of the frame. | | `intensity` | `number` | `1` | Overall brightness. | | `speed` | `number` | `1` | Sway speed. 0 freezes the fan into a poster frame. | | `blur` | `number` | `13` | Softness of a shaft's edge, in px. A heavy blur swallows the sway. | | `bloom` | `number` | `42` | Bloom radius at the source, in percent. 0 removes it. | ## Related - [Mesh Gradient Background](https://remotionui.com/docs/components/mesh-gradient-bg.md) - [Light Sweep Text](https://remotionui.com/docs/components/light-sweep-text.md) - [Aurora Background](https://remotionui.com/docs/components/aurora-bg.md) ## Machine-readable references - Props and usage as JSON: https://remotionui.com/ai/components/light-rays.json - Component index: https://remotionui.com/ai/components.json --- # Mesh Gradient Background > Living gradient blobs on a dark stage. Source: https://remotionui.com/docs/components/mesh-gradient-bg ## Installation ```bash npx remotion-ui@latest add mesh-gradient-bg ``` Full-frame ambient background with drifting phosphor, ember, and rose blobs on `#050505`. ## Usage ```tsx import { MeshGradientBg } from "@/remotion/primitives/mesh-gradient-bg"; <MeshGradientBg /> ``` ## Props | Name | Type | Default | Description | | --- | --- | --- | --- | | `backgroundColor` | `string` | `"#050505"` | Stage color. | | `colors` | `[string, string, string]` | `["#e8b86d", "#e07a5f", "#c2557a"]` | Blob accent colors: solid hex, screen-blended over the stage. | | `intensity` | `number` | `1` | Drift amplitude multiplier. | ## Related - [Dynamic Grid](https://remotionui.com/docs/components/dynamic-grid.md) ## Machine-readable references - Props and usage as JSON: https://remotionui.com/ai/components/mesh-gradient-bg.json - Component index: https://remotionui.com/ai/components.json --- # Particle Field > Ambient particles drifting with depth. Install with npx remotion-ui@latest add particle-field. Source: https://remotionui.com/docs/components/particle-field ## Installation ```bash npx remotion-ui@latest add particle-field ``` A full-frame layer of drifting particles. ```tsx import { ParticleField } from "@/remotion/primitives/particle-field"; <AbsoluteFill> <ParticleField count={70} angle={8} /> <YourScene /> </AbsoluteFill> ``` ## Where it sits Continuous, unlike `confetti-burst`, which is a single impulse with physics behind it. This has no beginning and no end, so it can sit under a whole scene without ever resolving. Reach for the burst when something *happened*; reach for this when nothing has. ## Depth is one number Each particle gets a `depth` and everything else follows from it: near particles are larger, faster, brighter and in focus, far ones are small, slow and defocused. That single correlation is what makes a plane of `div`s read as volume. Break it (same size, different speeds) and the field flattens immediately. Depths are distributed towards the back on purpose. An even spread gives a field of same-sized dots, which reads as a texture rather than as air. ## Travel `angle` is the direction, in degrees, with 0 drifting straight up. Particles wrap on a track whose both ends sit outside the frame, so nothing ever pops into existence on screen. `drift` adds a per-particle sideways wander on its own clock, which keeps the field from moving as a rigid sheet. `speed={1}` puts a near particle across the frame in about eight seconds. ## Cost `count` divs per frame, each with a radial-gradient background and a small blur. Seventy is comfortable at 1080p. Several hundred is not: raise `size` and drop `count` instead, since a bigger particle carries the same read for less. ## Usage ```tsx import { ParticleField } from "@/remotion/primitives/particle-field"; <AbsoluteFill> <ParticleField count={70} angle={8} /> <YourScene /> </AbsoluteFill> ``` Continuous, unlike `confetti-burst`, which is a single impulse. One depth value per particle drives size, speed, brightness and focus together, and that correlation is what makes a plane of divs read as volume. Travel wraps on a track whose ends sit outside the frame. ## Props | Name | Type | Default | Description | | --- | --- | --- | --- | | `backgroundColor` | `string` | `"#05070f"` | Plate behind the field. `transparent` layers it over footage. | | `color` | `string` | `"#e8b86d"` | Particle colour. | | `count` | `number` | `70` | How many particles. | | `angle` | `number` | `8` | Direction of travel in degrees. 0 drifts straight up. | | `speed` | `number` | `1` | Traverse speed. 1 crosses the frame in about eight seconds. | | `size` | `number` | `14` | Diameter of the nearest particle, in px. | | `minSize` | `number` | `2` | Diameter of the furthest particle, in px. | | `depthBlur` | `number` | `3` | Defocus on the furthest particles. 0 flattens the field. | | `drift` | `number` | `4` | Sideways wander, in percent of the frame. | | `intensity` | `number` | `1` | Overall brightness. | | `glow` | `number` | `1.6` | Halo per particle, as a multiple of its size. 0 draws hard dots. | | `seed` | `number` | `1` | Changes the layout without changing any other prop. | ## Related - [Confetti Burst](https://remotionui.com/docs/components/confetti-burst.md) - [Aurora Background](https://remotionui.com/docs/components/aurora-bg.md) - [Mesh Gradient Background](https://remotionui.com/docs/components/mesh-gradient-bg.md) ## Machine-readable references - Props and usage as JSON: https://remotionui.com/ai/components/particle-field.json - Component index: https://remotionui.com/ai/components.json --- # Topographic Lines Background > Contour lines drifting outward, like elevation rising. Install with npx remotion-ui@latest add topographic-lines-bg. Source: https://remotionui.com/docs/components/topographic-lines-bg ## Installation ```bash npx remotion-ui@latest add topographic-lines-bg ``` A survey-map background. ```tsx import { TopographicLinesBg } from "@/remotion/primitives/topographic-lines-bg"; <AbsoluteFill> <TopographicLinesBg speed={1} /> <YourScene /> </AbsoluteFill> ``` ## How the contours are built Real contours come out of a height field by marching squares, which is far too expensive to run per frame. This inverts the problem. A landform is a stack of closed polar curves around a centre, each radius modulated by three harmonics, so the family is nested by construction and can never self-intersect, which is the one thing a contour map must never do. Two overlapping landforms give the crossing, merging look of a real survey sheet. One landform on its own reads as a target. ## Peaks ```tsx <TopographicLinesBg peaks={[ { x: 20, y: 34, size: 72, roughness: 1.05 }, { x: 84, y: 74, size: 54, roughness: 1.35 }, ]} /> ``` `x` and `y` are percentages of the frame, `size` is the outermost contour's radius as a percentage of the short edge, and `roughness` scales the harmonics. At `roughness={0}` you get concentric circles. ## Index contours Every `indexEvery`-th line is drawn heavier, which is the convention that makes a real map legible. A contour keeps its identity as it travels outward, so an index contour stays an index contour rather than flickering between weights when the stack wraps. ## Motion Contours travel outward, which reads as elevation rising under the camera. They fade in at the peak and out at the rim, so nothing appears or vanishes mid-frame. `speed={0}` freezes the map into a still. `lineWidth` is in pixels at any output size: the stroke is pinned with `vectorEffect="non-scaling-stroke"`, because the drawing space is a fixed 160x90 box and an unpinned stroke would triple in weight between a preview and a 4K render. ## Usage ```tsx import { TopographicLinesBg } from "@/remotion/primitives/topographic-lines-bg"; <AbsoluteFill> <TopographicLinesBg speed={1} /> <YourScene /> </AbsoluteFill> ``` Not marching squares: far too expensive per frame. Each landform is a stack of polar curves modulated by three harmonics, so the family is nested by construction. Contours travel outward and wrap, fading in at the peak and out at the rim. ## Props | Name | Type | Default | Description | | --- | --- | --- | --- | | `backgroundColor` | `string` | `"#050505"` | Plate behind the contours. `transparent` layers them over footage. | | `lineColor` | `string` | `"rgba(232,184,109,0.5)"` | Contour colour. | | `indexColor` | `string` | `"rgba(232,184,109,0.95)"` | Colour of the heavier index contour. | | `peaks` | `TopographicPeak[]` | `two peaks` | Landforms: `{ x, y, size, roughness }` in percent. One peak reads as a target; two read as terrain. | | `lineCount` | `number` | `12` | Contours per landform. | | `indexEvery` | `number` | `4` | Every n-th contour is drawn heavier. 0 makes them uniform. | | `lineWidth` | `number` | `1.4` | Contour weight in px, independent of output size. | | `speed` | `number` | `1` | How fast elevation rises. 0 freezes the map. | | `intensity` | `number` | `1` | Overall brightness. | | `seed` | `number` | `1` | Changes the terrain without changing any other prop. | ## Related - [Dynamic Grid](https://remotionui.com/docs/components/dynamic-grid.md) - [Map Canvas](https://remotionui.com/docs/components/map-canvas.md) - [Aurora Background](https://remotionui.com/docs/components/aurora-bg.md) ## Machine-readable references - Props and usage as JSON: https://remotionui.com/ai/components/topographic-lines-bg.json - Component index: https://remotionui.com/ai/components.json --- # Motion > Entrances, exits, and emphasis primitives that wrap any element and animate it on the timeline. Source: https://remotionui.com/docs/components/motion Motion primitives wrap an element and animate how it enters, leaves, or draws attention. They take frame-based delays and durations, so they compose inside sequences and staggers. ## Components - [Blur In](https://remotionui.com/docs/components/blur-in.md): Resolve out of a defocus, the blur clears before the move lands. - [Confetti Burst](https://remotionui.com/docs/components/confetti-burst.md): Frame-driven confetti burst overlay. - [Depth of Field Blur](https://remotionui.com/docs/components/depth-of-field-blur.md): A rack focus across depth planes. Install with npx remotion-ui@latest add depth-of-field-blur. - [Fade In](https://remotionui.com/docs/components/fade-in.md): Opacity-only entrance for Remotion, with an exit that times itself to the end of its sequence. - [Fade Out](https://remotionui.com/docs/components/fade-out.md): Held exit that accelerates away, timed to the last frame of its sequence. - [Glow Pulse](https://remotionui.com/docs/components/glow-pulse.md): A rhythmic glow for CTAs and live indicators. Install with npx remotion-ui@latest add glow-pulse. - [Motion Trail](https://remotionui.com/docs/components/motion-trail.md): Echo trails behind a moving element, rendered from earlier frames. Install with npx remotion-ui@latest add motion-trail. - [Orbit Motion](https://remotionui.com/docs/components/orbit-motion.md): Elements orbiting a centre point, with depth. Install with npx remotion-ui@latest add orbit-motion. - [Parallax Layers](https://remotionui.com/docs/components/parallax-layers.md): Depth-offset planes driven by one camera move. Install with npx remotion-ui@latest add parallax-layers. - [Progress Bar](https://remotionui.com/docs/components/progress-bar.md): Inline progress bar with determinate and indeterminate modes, segments and a value readout. - [Rotate In](https://remotionui.com/docs/components/rotate-in.md): Swing into place in plane, or hinged in depth on the x or y axis. - [Scale In](https://remotionui.com/docs/components/scale-in.md): Grow into place from just under full size, with an optional spring and exit. - [Scanline CRT](https://remotionui.com/docs/components/scanline-crt.md): CRT scanlines, aperture grille and tube curvature. Install with npx remotion-ui@latest add scanline-crt. - [Shake Emphasis](https://remotionui.com/docs/components/shake-emphasis.md): A short impact shake with a decaying envelope. Install with npx remotion-ui@latest add shake-emphasis. - [Skew In](https://remotionui.com/docs/components/skew-in.md): Lean in and straighten up, an editorial entrance built from shear plus travel. Install with npx remotion-ui@latest add skew-in. - [Slide Left](https://remotionui.com/docs/components/slide-left.md): Slide in from either side, with an optional mask reveal and an automatic exit. - [Slide Up](https://remotionui.com/docs/components/slide-up.md): Rise into place, with an optional mask reveal and an automatic exit. - [Spring In](https://remotionui.com/docs/components/spring-in.md): Spring-driven scale and rise, with snappy, smooth and bouncy presets. - [Squash Stretch](https://remotionui.com/docs/components/squash-stretch.md): The animation principle, as a primitive. Install with npx remotion-ui@latest add squash-stretch. - [Stagger Children](https://remotionui.com/docs/components/stagger-children.md): Offset children onto their own sequences, forward, reverse, centre or edge order, in and out. --- # Blur In > Resolve out of a defocus, the blur clears before the move lands. Source: https://remotionui.com/docs/components/blur-in ## Installation ```bash npx remotion-ui@latest add blur-in ``` Resolves out of a defocus, like a lens finding its subject. The blur is gone at 80% of the travel. Held to the last frame the whole entrance feels soft, and the eye reads the sharpening instead of the arrival. ## Usage ```tsx import { BlurIn } from "@/remotion/primitives/blur-in"; <BlurIn maxBlur={12}> <h1>Focus reveal</h1> </BlurIn> ``` The blur clears at 80% of the travel; held to the last frame the whole entrance feels soft. ## Props | Name | Type | Default | Description | | --- | --- | --- | --- | | `children` (required) | `ReactNode` | - | Content to animate. | | `durationInFrames` | `number` | `30` | Length of the enter animation in frames. | | `delayInFrames` | `number` | `0` | Frames to wait before the animation starts. | | `spring` | `"smooth" \| "snappy" \| "bouncy" \| Partial<SpringConfig> \| boolean` | - | Drive the entrance with a spring instead of the ease-out curve. | | `exit` | `boolean` | `false` | Animate back out, landing on the last frame of the surrounding Sequence. | | `exitInFrames` | `number` | `70% of durationInFrames` | Length of the exit. Exits are shorter than entrances. | | `exitAtInFrames` | `number` | - | Frame the exit starts on, overriding the end-of-window timing. | | `exitTravel` | `number` | `0.6` | Share of the enter distance the exit travels. | | `exitDirection` | `"reverse" \| "continue"` | `"reverse"` | reverse leaves the way it came in, continue carries on through. | | `block` | `boolean` | `false` | Fill the parent's width instead of shrink-wrapping the child. | | `style` | `CSSProperties` | - | Styles merged onto the wrapper. | | `maxBlur` | `number` | `10` | Blur radius in pixels at the start. | | `scaleFrom` | `number` | `0.98` | Scale at the start: the push that sells the pull into focus. | ## Related - [Fade In](https://remotionui.com/docs/components/fade-in.md) - [Scale In](https://remotionui.com/docs/components/scale-in.md) ## Machine-readable references - Props and usage as JSON: https://remotionui.com/ai/components/blur-in.json - Component index: https://remotionui.com/ai/components.json --- # Confetti Burst > Frame-driven confetti burst overlay. Source: https://remotionui.com/docs/components/confetti-burst ## Installation ```bash npx remotion-ui@latest add confetti-burst ``` Deterministic confetti particles with gravity. Seed the burst for repeatable renders. ## Usage ```tsx import { ConfettiBurst } from "@/remotion/primitives/confetti-burst"; <ConfettiBurst originX={50} originY={40} seed="launch" /> ``` ## Props | Name | Type | Default | Description | | --- | --- | --- | --- | | `count` | `number` | `48` | Particle count. | | `originX` | `number` | `50` | Burst origin X in percent. | | `originY` | `number` | `42` | Burst origin Y in percent. | | `seed` | `string` | `"confetti"` | Deterministic random seed. | | `gravity` | `number` | `680` | Downward acceleration in px/s². The default clears a 1080p frame in about two seconds; lower it to keep the confetti in shot for longer. | | `drag` | `number` | `1.6` | Air resistance on the outward throw, per second. Higher settles the spread sooner. | ## Related - [Spring In](https://remotionui.com/docs/components/spring-in.md) ## Machine-readable references - Props and usage as JSON: https://remotionui.com/ai/components/confetti-burst.json - Component index: https://remotionui.com/ai/components.json --- # Depth of Field Blur > A rack focus across depth planes. Install with npx remotion-ui@latest add depth-of-field-blur. Source: https://remotionui.com/docs/components/depth-of-field-blur ## Installation ```bash npx remotion-ui@latest add depth-of-field-blur ``` Pull the audience's attention from one plane to another. ```tsx import { DepthOfFieldBlur } from "@/remotion/primitives/depth-of-field-blur"; <DepthOfFieldBlur focusFrom={1} focusTo={0} layers={[ { content: <Background />, depth: 1 }, { content: <Card />, depth: 0.4 }, { content: <Foreground />, depth: 0 }, ]} /> ``` ## Where it sits Spatial, unlike `blur-focus-in`, which resolves a single piece of type as it arrives. Here every plane is blurred by its *distance from the focal plane*, so racking the focus pulls one layer in exactly as it pushes another out. That relationship is the shot; blurring one element on its own reads as an effect rather than as a camera. ## Two details that do the convincing Defocused planes dim slightly, because a lens spreads the same light over a larger circle of confusion. And they scale slightly, which is the focus breathing every real lens has. Both are small enough to be invisible on their own and obvious by their absence. `aperture` controls how fast focus falls off with distance. A high number is a wide aperture: a plane goes soft over a very small change in depth. ## Land the rack on a plane Time the rack so it is *on* a plane whenever anyone is looking. A rack that is halfway between two planes at the moment a viewer's eye settles, or at the moment a thumbnail is captured, has nothing sharp in it, and an all-soft frame reads as a broken render rather than as a camera move. The default runs across 78% of the surrounding window, starting at frame 6. Override `startAtInFrames` and `durationInFrames` to place it against a beat, or pass `progress` and drive it yourself. ## Usage ```tsx import { DepthOfFieldBlur } from "@/remotion/primitives/depth-of-field-blur"; <DepthOfFieldBlur focusFrom={1} focusTo={0} layers={[ { content: <Background />, depth: 1 }, { content: <Card />, depth: 0.4 }, { content: <Foreground />, depth: 0 }, ]} /> ``` Spatial, unlike `blur-focus-in`, which resolves one piece of type. Blur comes from each plane's distance to the focal plane, so racking pulls one layer in exactly as it pushes another out. Time the rack so it lands *on* planes: a rack that is between two planes at the moment anyone looks has nothing sharp in frame. ## Props | Name | Type | Default | Description | | --- | --- | --- | --- | | `layers` | `DepthOfFieldLayer[]` | - | Back to front. Each is `{ content, depth }`, depth 0 nearest to 1 furthest. | | `focusFrom` | `number` | `0` | Depth the lens starts focused on. | | `focusTo` | `number` | `1` | Depth the lens racks to. Equal to `focusFrom` holds focus. | | `startAtInFrames` | `number` | `6` | Frame the rack starts on. | | `durationInFrames` | `number` | `78% of the window` | Length of the rack. | | `maxBlur` | `number` | `16` | Blur at maximum defocus, in px. | | `aperture` | `number` | `2.2` | How fast focus falls off with distance. Higher is a wider aperture. | | `dim` | `number` | `0.35` | How much an out-of-focus plane darkens. | | `breathe` | `number` | `0.03` | Scale a defocused plane picks up (focus breathing). | | `progress` | `number` | - | Drive the rack yourself, 0-1. | | `backgroundColor` | `string` | `"#07080e"` | Plate behind every plane. | ## Related - [Blur Focus In](https://remotionui.com/docs/components/blur-focus-in.md) - [Parallax Layers](https://remotionui.com/docs/components/parallax-layers.md) - [Zoom Pan Frame](https://remotionui.com/docs/components/zoom-pan-frame.md) ## Machine-readable references - Props and usage as JSON: https://remotionui.com/ai/components/depth-of-field-blur.json - Component index: https://remotionui.com/ai/components.json --- # Fade In > Opacity-only entrance for Remotion, with an exit that times itself to the end of its sequence. Source: https://remotionui.com/docs/components/fade-in ## Installation ```bash npx remotion-ui@latest add fade-in ``` Animates opacity from `from` to `to`, no transform, so it composes with anything that already moves. Pass `exit` and the element leaves again on the last frame of the surrounding `<Sequence>`; the exit is shorter than the entrance and accelerates away, because an exit is not an entrance played backwards. ## Usage ```tsx import { FadeIn } from "@/remotion/primitives/fade-in"; <FadeIn durationInFrames={30} exit> <div>Hello world</div> </FadeIn> ``` Opacity runs the full duration here; the transform primitives finish theirs at 55% so the element lands solid. ## Props | Name | Type | Default | Description | | --- | --- | --- | --- | | `children` (required) | `ReactNode` | - | Content to animate. | | `durationInFrames` | `number` | `30` | Length of the enter animation in frames. | | `delayInFrames` | `number` | `0` | Frames to wait before the animation starts. | | `spring` | `"smooth" \| "snappy" \| "bouncy" \| Partial<SpringConfig> \| boolean` | - | Drive the entrance with a spring instead of the ease-out curve. | | `exit` | `boolean` | `false` | Animate back out, landing on the last frame of the surrounding Sequence. | | `exitInFrames` | `number` | `70% of durationInFrames` | Length of the exit. Exits are shorter than entrances. | | `exitAtInFrames` | `number` | - | Frame the exit starts on, overriding the end-of-window timing. | | `exitTravel` | `number` | `0.6` | Share of the enter distance the exit travels. | | `exitDirection` | `"reverse" \| "continue"` | `"reverse"` | reverse leaves the way it came in, continue carries on through. | | `block` | `boolean` | `false` | Fill the parent's width instead of shrink-wrapping the child. | | `style` | `CSSProperties` | - | Styles merged onto the wrapper. | | `from` | `number` | `0` | Opacity the fade starts from. | | `to` | `number` | `1` | Opacity the fade settles on. | ## Related - [Fade Out](https://remotionui.com/docs/components/fade-out.md) - [Slide Up](https://remotionui.com/docs/components/slide-up.md) ## Machine-readable references - Props and usage as JSON: https://remotionui.com/ai/components/fade-in.json - Component index: https://remotionui.com/ai/components.json --- # Fade Out > Held exit that accelerates away, timed to the last frame of its sequence. Source: https://remotionui.com/docs/components/fade-out ## Installation ```bash npx remotion-ui@latest add fade-out ``` Holds, then leaves on an ease-in curve. Leave `delayInFrames` out and the fade lands on the last frame of the surrounding `<Sequence>`, one less number to keep in sync when the window changes. ## Usage ```tsx import { FadeOut } from "@/remotion/primitives/fade-out"; <FadeOut durationInFrames={24}> <div>Goodbye</div> </FadeOut> ``` Uses an ease-in curve: an exit accelerates away, it never decelerates into nothing. ## Props | Name | Type | Default | Description | | --- | --- | --- | --- | | `children` (required) | `ReactNode` | - | Content to fade away. | | `durationInFrames` | `number` | `30` | Length of the fade in frames. | | `delayInFrames` | `number` | `end of the sequence` | Frame the fade starts on. Omitted, it lands on the last frame of the surrounding Sequence. | | `from` | `number` | `1` | Opacity held before the fade. | | `to` | `number` | `0` | Opacity it ends on. | | `block` | `boolean` | `false` | Fill the parent's width instead of shrink-wrapping. | | `style` | `CSSProperties` | - | Styles merged onto the wrapper. | ## Related - [Fade In](https://remotionui.com/docs/components/fade-in.md) ## Machine-readable references - Props and usage as JSON: https://remotionui.com/ai/components/fade-out.json - Component index: https://remotionui.com/ai/components.json --- # Glow Pulse > A rhythmic glow for CTAs and live indicators. Install with npx remotion-ui@latest add glow-pulse. Source: https://remotionui.com/docs/components/glow-pulse ## Installation ```bash npx remotion-ui@latest add glow-pulse ``` The thing that says *this one*. ```tsx import { GlowPulse } from "@/remotion/primitives/glow-pulse"; <GlowPulse mode="beat" periodInFrames={36}> <CtaPill /> </GlowPulse> ``` ## Why it is a wrapper The glow is a `drop-shadow` filter, not a `box-shadow`, so it follows the alpha of whatever it wraps (a pill, a ring, a piece of type, an SVG mark) instead of the bounding box. That is the entire reason this is a component and not a class: a box-shadow on a circular badge glows in a square. ## Two shapes `breathe` is a sine, for something ambient that should not demand attention. `beat` rises in the first eighth of the cycle and decays across the rest, which is why a live dot reads as pulsing rather than as fading in and out. Add `echo` for the second, smaller tap that turns a metronome into a heartbeat. ## floor matters more than intensity A live indicator that reaches zero reads as broken. The pulse rides above a standing glow set by `floor`, and dropping that to 0 is the fastest way to make a working component look like a bug. `scale` adds a small size change at the top of the pulse. It is optional, but a glow that changes brightness while the element stays exactly still reads as a lighting change rather than as the element itself pulsing. ## Usage ```tsx import { GlowPulse } from "@/remotion/primitives/glow-pulse"; <GlowPulse mode="beat" periodInFrames={36}> <CtaPill /> </GlowPulse> ``` The glow is a `drop-shadow` filter, so it follows the alpha of whatever it wraps (a pill, a ring, type, an SVG mark) rather than the bounding box. `floor` matters more than `intensity`: a live indicator that reaches zero reads as broken. ## Props | Name | Type | Default | Description | | --- | --- | --- | --- | | `children` | `ReactNode` | - | What glows. | | `color` | `string` | `"#e8b86d"` | Glow colour. | | `radius` | `number` | `26` | Glow radius at full brightness, in px. | | `intensity` | `number` | `1` | Brightness at the top of the pulse. | | `floor` | `number` | `0.28` | Brightness at the bottom. Never 0 for a live indicator. | | `periodInFrames` | `number` | `36` | Length of one pulse. | | `mode` | `"breathe" \| "beat"` | `"breathe"` | `breathe` is a sine; `beat` is a fast attack and a long decay. | | `scale` | `number` | `0.04` | Scale added at the top of the pulse. 0 glows without moving. | | `halo` | `number` | `2.4` | Halo behind the element, as a multiple of `radius`. 0 removes it. | | `echo` | `number` | `0` | Second, smaller tap per cycle: a heartbeat rather than a metronome. | ## Related - [Shake Emphasis](https://remotionui.com/docs/components/shake-emphasis.md) - [Neon Flicker Text](https://remotionui.com/docs/components/neon-flicker-text.md) - [End Card](https://remotionui.com/docs/components/end-card.md) ## Machine-readable references - Props and usage as JSON: https://remotionui.com/ai/components/glow-pulse.json - Component index: https://remotionui.com/ai/components.json --- # Motion Trail > Echo trails behind a moving element, rendered from earlier frames. Install with npx remotion-ui@latest add motion-trail. Source: https://remotionui.com/docs/components/motion-trail ## Installation ```bash npx remotion-ui@latest add motion-trail ``` Where the thing just was. ```tsx import { MotionTrail } from "@/remotion/primitives/motion-trail"; <MotionTrail count={6} gapInFrames={3}> <TheMovingThing /> </MotionTrail> ``` ## The trick An echo is not a copy of the element's *position*, it is the element itself, rendered at an earlier frame. `<Sequence from={n}>` shifts the frame its children see by `-n`, so an echo at `from={gap * i}` renders exactly what the subject looked like `gap * i` frames ago. That means the trail is correct for any motion at all: rotation, colour changes, shape changes, a chart redrawing itself. There is no path to describe, no previous position to store, and nothing to keep in sync when the subject's animation changes. ## The requirement **The child must animate from `useCurrentFrame()`.** A subject positioned by a prop, or by a parent's transform, looks identical on every past frame and every echo stacks in one place. This is the one way to hold it wrong. ## Cost `count` echoes render the subtree `count + 1` times per frame. Keep the subject small, and prefer a wider `gapInFrames` over a higher `count` when the trail needs length: a longer gap stretches the trail for free, where a higher count buys smoothness at full price. ## Behaviour at the start Echoes before frame `gap * i` do not exist yet, so a trail grows in naturally over its own length at the start of a composition rather than appearing fully formed on frame 0. ## Usage ```tsx import { MotionTrail } from "@/remotion/primitives/motion-trail"; <MotionTrail count={6} gapInFrames={3}> <TheMovingThing /> </MotionTrail> ``` An echo is not a copy of a position: it is the subject re-rendered at an earlier frame, via `<Sequence from={gap * i}>`. That makes the trail correct for any motion, including rotation and colour change, with no path to describe. It also costs `count + 1` renders of the subtree per frame, so prefer a wider gap over a higher count. ## Props | Name | Type | Default | Description | | --- | --- | --- | --- | | `children` | `ReactNode` | - | The moving element. It must animate from `useCurrentFrame()`. | | `count` | `number` | `6` | How many echoes trail behind. | | `gapInFrames` | `number` | `3` | Frames between echoes. Wider gaps stretch the trail for free. | | `opacity` | `number` | `0.45` | Opacity of the freshest echo. | | `falloff` | `number` | `1.6` | How fast echoes fade. 1 is linear, 2 keeps the tail short. | | `scale` | `number` | `0.82` | Scale of the oldest echo. 1 keeps them all the same size. | | `blur` | `number` | `4` | Blur on the oldest echo, in px. | | `color` | `string` | - | Tint the echoes. Omit to echo the element's own colours. | | `blendMode` | `CSS mix-blend-mode` | `"screen"` | How echoes composite. `screen` is right on a dark stage. | | `block` | `boolean` | `false` | Fill the parent instead of shrink-wrapping the subject. | ## Related - [Cursor Path](https://remotionui.com/docs/components/cursor-path.md) - [Confetti Burst](https://remotionui.com/docs/components/confetti-burst.md) - [Orbit Motion](https://remotionui.com/docs/components/orbit-motion.md) ## Machine-readable references - Props and usage as JSON: https://remotionui.com/ai/components/motion-trail.json - Component index: https://remotionui.com/ai/components.json --- # Orbit Motion > Elements orbiting a centre point, with depth. Install with npx remotion-ui@latest add orbit-motion. Source: https://remotionui.com/docs/components/orbit-motion ## Installation ```bash npx remotion-ui@latest add orbit-motion ``` Satellites around a hub. ```tsx import { OrbitMotion } from "@/remotion/primitives/orbit-motion"; <OrbitMotion periodInFrames={120} center={<Logo />} showPath> <Chip label="Scenes" /> <Chip label="Atoms" /> <Chip label="Cuts" /> </OrbitMotion> ``` ## Depth is what makes it an orbit The ellipse is the easy half. What separates an orbit from a circular slide is that a child on the far side of the ring is smaller, dimmer, and painted *behind* whatever sits at the centre. All three come from the same sine, so the pass behind the middle happens by itself. There is nothing to schedule and nothing to get out of sync. Set `depth={0}` for a flat, diagrammatic ring; raise it for a tilted, physical one. ## Multiple children Every child gets its own slot, evenly spaced, so a satellite diagram is the default case rather than something you assemble by hand. Give them different content. Identical children on an evenly spaced ring make the whole picture repeat every `periodInFrames / count` frames, which looks like a much faster loop than the one you asked for, and, if you are sampling stills, can make a moving component look frozen. ## Layout `centerX` and `centerY` are percentages of the frame; `radiusX` and `radiusY` are pixels. `upright` keeps children level while they travel, which is almost always what type wants; turn it off for something that should bank into the curve. ## Usage ```tsx import { OrbitMotion } from "@/remotion/primitives/orbit-motion"; <OrbitMotion periodInFrames={120} center={<Logo />}> <Chip label="One" /> <Chip label="Two" /> </OrbitMotion> ``` The ellipse is the easy half; depth is what makes it an orbit. One sine drives scale, opacity and `zIndex` together, so a satellite passes behind whatever is at the centre by itself. Give satellites different content: identical ones make the ring repeat every revolution divided by their count. ## Props | Name | Type | Default | Description | | --- | --- | --- | --- | | `children` | `ReactNode` | - | Each child gets its own slot on the ring, evenly spaced. | | `radiusX` | `number` | `210` | Horizontal radius, in px. | | `radiusY` | `number` | `78` | Vertical radius. Smaller reads as a tilted ring. | | `periodInFrames` | `number` | `120` | Frames for one revolution. | | `phase` | `number` | `0` | Where the first child starts, in degrees. | | `tilt` | `number` | `-12` | Tilt of the whole ring, in degrees. | | `direction` | `"cw" \| "ccw"` | `"cw"` | Which way it turns. | | `centerX` | `number` | `50` | Centre of the orbit, in percent of the frame. | | `centerY` | `number` | `50` | Centre of the orbit, in percent of the frame. | | `depth` | `number` | `0.28` | Scale difference between the near and far side. 0 is flat. | | `depthFade` | `number` | `0.4` | How much the far side dims. | | `upright` | `boolean` | `true` | Keep children upright instead of letting them ride the ring. | | `showPath` | `boolean` | `false` | Draw the ring itself. | | `pathColor` | `string` | `"rgba(255,255,255,0.14)"` | Colour of the drawn ring. | | `center` | `ReactNode` | - | What sits at the centre. | ## Related - [Ecosystem Orbit](https://remotionui.com/docs/components/ecosystem-orbit.md) - [Motion Trail](https://remotionui.com/docs/components/motion-trail.md) - [Squash Stretch](https://remotionui.com/docs/components/squash-stretch.md) ## Machine-readable references - Props and usage as JSON: https://remotionui.com/ai/components/orbit-motion.json - Component index: https://remotionui.com/ai/components.json --- # Parallax Layers > Depth-offset planes driven by one camera move. Install with npx remotion-ui@latest add parallax-layers. Source: https://remotionui.com/docs/components/parallax-layers ## Installation ```bash npx remotion-ui@latest add parallax-layers ``` Planes at different depths, moving at different rates, on one driver. ```tsx import { ParallaxLayers } from "@/remotion/primitives/parallax-layers"; <ParallaxLayers travel={420} layers={[ { content: <Sky />, depth: 0.2, blur: 2 }, { content: <Headline />, depth: 0.55 }, { content: <Foreground />, depth: 1, blur: 8 }, ]} /> ``` ## Where it sits Multi-layer, unlike `zoom-pan-frame`, which moves a camera over a single still. The split matters because parallax is a *relationship*: the illusion comes from planes moving at different rates against each other, so one driver has to feed all of them. Animating three layers separately gets you three animations that happen to overlap. ## Depth `depth` is the only number a caller has to think about. A plane at `depth={0}` is the focal plane and never moves; everything else is offset by `depth × travel` relative to it. Negative depths move the other way, which is what an element in front of the lens does. Layers are listed back to front, and a layer with no `depth` gets one from its position in the list, so the simplest call is just an ordered array. ## The sweep The move runs from -0.5 to 0.5 rather than 0 to 1, so the middle of the window is the layout you actually composed and the planes are offset in both directions around it. A sweep that started in frame and slid out would mean designing against a position nobody sees. `zoom` adds scale to the nearer planes as they travel, which is the difference between a dolly and a pan and the half people forget. Drive it from the frame (`startAtInFrames`, `durationInFrames`, `motion`), or pass `progress` and drive it from a scroll position, a spring, or a scene's own clock. ## Usage ```tsx import { ParallaxLayers } from "@/remotion/primitives/parallax-layers"; <ParallaxLayers travel={420} layers={[ { content: <Sky />, depth: 0.2, blur: 2 }, { content: <Headline />, depth: 0.55 }, { content: <Foreground />, depth: 1, blur: 8 }, ]} /> ``` Multi-layer, unlike `zoom-pan-frame`, which moves a camera over one still. Parallax is a relationship, so one driver feeds every plane and `depth` is the only number a caller sets. The sweep runs -0.5 to 0.5, so the middle of the window is the layout you composed. ## Props | Name | Type | Default | Description | | --- | --- | --- | --- | | `layers` | `ParallaxLayer[]` | - | Back to front. Each is `{ content, depth, blur, opacity, scale }`; depth 0 is the focal plane, 1 travels furthest, negative travels the other way. | | `travel` | `number` | `320` | Travel of a depth-1 plane across the whole move, in px. | | `angle` | `number` | `0` | Direction of the camera move. 0 tracks right, 90 cranes down. | | `zoom` | `number` | `0.12` | Extra scale the nearest plane picks up. 0 is a flat track. | | `progress` | `number` | - | Drive the move yourself, 0-1. Overrides the frame-based sweep. | | `startAtInFrames` | `number` | `0` | Frame the sweep starts on. | | `durationInFrames` | `number` | `the composition` | Length of the sweep. | | `motion` | `"ease" \| "linear"` | `"ease"` | `ease` settles at both ends; `linear` is a constant-speed dolly. | | `backgroundColor` | `string` | `"#07080e"` | Plate behind every plane. | ## Related - [Zoom Pan Frame](https://remotionui.com/docs/components/zoom-pan-frame.md) - [Depth of Field Blur](https://remotionui.com/docs/components/depth-of-field-blur.md) - [Bento Pan](https://remotionui.com/docs/components/bento-pan.md) ## Machine-readable references - Props and usage as JSON: https://remotionui.com/ai/components/parallax-layers.json - Component index: https://remotionui.com/ai/components.json --- # Progress Bar > Inline progress bar with determinate and indeterminate modes, segments and a value readout. Source: https://remotionui.com/docs/components/progress-bar ## Installation ```bash npx remotion-ui@latest add progress-bar ``` Fills from `from` to `progress` on an ease-out, with the leading edge carrying its own light: what separates progress from a rectangle changing width. It lays out inline rather than filling the frame, so it composes inside a card or a stat row. `indeterminate` loops a shuttle across the track for work with no known end. ## Usage ```tsx import { ProgressBar } from "@/remotion/primitives/progress-bar"; <ProgressBar progress={0.75} label="Rendering" showValue segments={4} /> ``` Lays out inline rather than filling the frame, so it composes inside a card or a stat row. ## Props | Name | Type | Default | Description | | --- | --- | --- | --- | | `progress` | `number` | `1` | Value the bar fills to, 0–1. | | `from` | `number` | `0` | Value the bar starts from, 0–1. | | `durationInFrames` | `number` | `60` | Frames the fill takes. | | `delayInFrames` | `number` | `0` | Frames before the fill starts. | | `spring` | `MotionSpring` | - | Drive the fill with a spring instead of the ease-out curve. | | `indeterminate` | `boolean` | `false` | Loop a shuttle across the track: work with no known end. | | `label` | `string` | - | Label above the track. | | `showValue` | `boolean` | `false` | Percentage readout on the right of the label row. | | `formatValue` | `(progress: number) => string` | - | Override the readout text. | | `segments` | `number` | - | Divide the track into equal steps. | | `color` | `string` | `"#e8b86d"` | Fill colour. | | `trackColor` | `string` | - | Colour of the empty track. | | `labelColor` | `string` | - | Colour of the label row. | | `height` | `number` | `scaled 12px` | Bar thickness in pixels. | | `radius` | `number` | `height` | Corner radius. | | `glow` | `boolean` | `true` | Soft light carried by the leading edge of the fill. | | `width` | `number \| string` | `"100%"` | Width of the whole control. | ## Related - [Counter](https://remotionui.com/docs/components/counter.md) - [Intro](https://remotionui.com/docs/components/intro.md) ## Machine-readable references - Props and usage as JSON: https://remotionui.com/ai/components/progress-bar.json - Component index: https://remotionui.com/ai/components.json --- # Rotate In > Swing into place in plane, or hinged in depth on the x or y axis. Source: https://remotionui.com/docs/components/rotate-in ## Installation ```bash npx remotion-ui@latest add rotate-in ``` Rotates from `degrees` to 0 while a small scale change ties the two into one gesture. `axis="x"` and `axis="y"` hinge in depth under `perspective`, which is how a card or a panel should arrive; `z` is the in-plane spin for badges and marks. ## Usage ```tsx import { RotateIn } from "@/remotion/primitives/rotate-in"; <RotateIn axis="x" degrees={-24} origin="bottom"> <div>Hinge into place</div> </RotateIn> ``` ## Props | Name | Type | Default | Description | | --- | --- | --- | --- | | `children` (required) | `ReactNode` | - | Content to animate. | | `durationInFrames` | `number` | `30` | Length of the enter animation in frames. | | `delayInFrames` | `number` | `0` | Frames to wait before the animation starts. | | `spring` | `"smooth" \| "snappy" \| "bouncy" \| Partial<SpringConfig> \| boolean` | - | Drive the entrance with a spring instead of the ease-out curve. | | `exit` | `boolean` | `false` | Animate back out, landing on the last frame of the surrounding Sequence. | | `exitInFrames` | `number` | `70% of durationInFrames` | Length of the exit. Exits are shorter than entrances. | | `exitAtInFrames` | `number` | - | Frame the exit starts on, overriding the end-of-window timing. | | `exitTravel` | `number` | `0.6` | Share of the enter distance the exit travels. | | `exitDirection` | `"reverse" \| "continue"` | `"reverse"` | reverse leaves the way it came in, continue carries on through. | | `block` | `boolean` | `false` | Fill the parent's width instead of shrink-wrapping the child. | | `style` | `CSSProperties` | - | Styles merged onto the wrapper. | | `degrees` | `number` | `-12` | Angle it starts at. Negative tilts anticlockwise. | | `axis` | `"z" \| "x" \| "y"` | `"z"` | z spins in plane; x and y hinge in depth. | | `perspective` | `number` | `1200` | Depth of the 3D projection for the x and y axes. | | `scaleFrom` | `number` | `0.96` | Scale at the start: a rotation that also grows reads as one gesture. | | `origin` | `TransformOrigin` | `"center"` | Point the rotation pivots around. | ## Related - [Spring In](https://remotionui.com/docs/components/spring-in.md) - [Scale In](https://remotionui.com/docs/components/scale-in.md) ## Machine-readable references - Props and usage as JSON: https://remotionui.com/ai/components/rotate-in.json - Component index: https://remotionui.com/ai/components.json --- # Scale In > Grow into place from just under full size, with an optional spring and exit. Source: https://remotionui.com/docs/components/scale-in ## Installation ```bash npx remotion-ui@latest add scale-in ``` Grows from `from` to full size, with opacity leading the scale. `from` stays close to 1 on purpose: a card scaling up from 0.5 reads as a zoom, which is a camera move rather than an arrival. Anything below ~0.85 wants `spring` behind it. ## Usage ```tsx import { ScaleIn } from "@/remotion/primitives/scale-in"; <ScaleIn from={0.9} spring="snappy"> <img src={staticFile("logo.png")} /> </ScaleIn> ``` Anything below ~0.85 wants a spring behind it, or the growth reads as a camera zoom. ## Props | Name | Type | Default | Description | | --- | --- | --- | --- | | `children` (required) | `ReactNode` | - | Content to animate. | | `durationInFrames` | `number` | `30` | Length of the enter animation in frames. | | `delayInFrames` | `number` | `0` | Frames to wait before the animation starts. | | `spring` | `"smooth" \| "snappy" \| "bouncy" \| Partial<SpringConfig> \| boolean` | - | Drive the entrance with a spring instead of the ease-out curve. | | `exit` | `boolean` | `false` | Animate back out, landing on the last frame of the surrounding Sequence. | | `exitInFrames` | `number` | `70% of durationInFrames` | Length of the exit. Exits are shorter than entrances. | | `exitAtInFrames` | `number` | - | Frame the exit starts on, overriding the end-of-window timing. | | `exitTravel` | `number` | `0.6` | Share of the enter distance the exit travels. | | `exitDirection` | `"reverse" \| "continue"` | `"reverse"` | reverse leaves the way it came in, continue carries on through. | | `block` | `boolean` | `false` | Fill the parent's width instead of shrink-wrapping the child. | | `style` | `CSSProperties` | - | Styles merged onto the wrapper. | | `from` | `number` | `0.92` | Scale at the start of the entrance. | | `origin` | `TransformOrigin` | `"center"` | Corner or edge the scale grows out of. | ## Related - [Spring In](https://remotionui.com/docs/components/spring-in.md) - [Fade In](https://remotionui.com/docs/components/fade-in.md) ## Machine-readable references - Props and usage as JSON: https://remotionui.com/ai/components/scale-in.json - Component index: https://remotionui.com/ai/components.json --- # Scanline CRT > CRT scanlines, aperture grille and tube curvature. Install with npx remotion-ui@latest add scanline-crt. Source: https://remotionui.com/docs/components/scanline-crt ## Installation ```bash npx remotion-ui@latest add scanline-crt ``` Put the picture back inside a tube. ```tsx import { ScanlineCrt } from "@/remotion/primitives/scanline-crt"; <ScanlineCrt curvature={0.6}> <YourScene /> </ScanlineCrt> ``` Pass `children` to put content inside the tube, or drop it over a stack as a bare overlay. It paints no plate of its own either way. ## Four overlays that only work together Bowed scanlines for the tube, a fine RGB grille for the phosphor mask, a rolling refresh bar for the shot-a-monitor look, and per-frame flicker for the mains hum. Take away the flicker and it reads as a static texture, which is the failure mode of every CSS CRT filter. The flicker is a slow hum plus a per-frame jitter. The hum is what stops it reading as random noise; the jitter is what stops the hum reading as a fade. ## Curvature is drawn Each scanline is a quadratic whose midpoint is pushed away from the centre of the tube in proportion to its distance from it, so lines near the top bow up and lines near the bottom bow down. That read (glass, not glass-effect) arrives long before any corner shading does. Content underneath is **not** geometrically warped. Warping a live subtree needs a displacement map per frame and costs far more than the effect is worth; the bowed lines plus the rounded tube face carry it. ## Give it a picture Every overlay here works by removing light: scanlines darken, the grille masks, the vignette shades. Over a near-black plate the whole component is invisible. If your tile looks empty, the tube has nothing to show. That is the first thing to check, not `intensity`. ## Stacking For emulsion rather than phosphor, reach for `animated-noise-grain`. The two stack, and grain over a CRT is exactly what a camera pointed at a monitor produces. ## Usage ```tsx import { ScanlineCrt } from "@/remotion/primitives/scanline-crt"; <ScanlineCrt curvature={0.6}> <YourScene /> </ScanlineCrt> ``` Curvature is drawn: each scanline is a quadratic whose midpoint is pushed away from the tube centre, so lines bow up at the top and down at the bottom. Content underneath is not geometrically warped. Every overlay here removes light, so over a near-black plate the component is invisible; give it a picture. ## Props | Name | Type | Default | Description | | --- | --- | --- | --- | | `children` | `ReactNode` | - | What the tube is showing. Omit to use it as a bare overlay. | | `lineCount` | `number` | `90` | How many scanlines across the frame. | | `lineOpacity` | `number` | `0.34` | Darkness of a scanline. | | `lineWidth` | `number` | `1.6` | Scanline weight in px, independent of output size. | | `curvature` | `number` | `0.55` | How hard the tube face bows. 0 draws dead straight lines. | | `cornerRadius` | `number` | `22` | Corner radius of the tube face, in px. | | `rollInFrames` | `number` | `96` | Frames for the refresh bar to cross. 0 removes it. | | `rollOpacity` | `number` | `0.16` | Brightness of the refresh bar. | | `flicker` | `number` | `0.05` | Frame-to-frame brightness jitter. | | `grille` | `number` | `0.22` | Strength of the RGB aperture grille. | | `vignette` | `number` | `0.55` | Corner darkening. | | `tint` | `string` | `"transparent"` | Phosphor tint over the picture. | | `tintBlend` | `CSS mix-blend-mode` | `"overlay"` | How the tint composites. | | `intensity` | `number` | `1` | Strength of every overlay at once. | ## Related - [Animated Noise Grain](https://remotionui.com/docs/components/animated-noise-grain.md) - [RGB Glitch Text](https://remotionui.com/docs/components/rgb-glitch-text.md) - [Terminal Simulator](https://remotionui.com/docs/components/terminal-simulator.md) ## Machine-readable references - Props and usage as JSON: https://remotionui.com/ai/components/scanline-crt.json - Component index: https://remotionui.com/ai/components.json --- # Shake Emphasis > A short impact shake with a decaying envelope. Install with npx remotion-ui@latest add shake-emphasis. Source: https://remotionui.com/docs/components/shake-emphasis ## Installation ```bash npx remotion-ui@latest add shake-emphasis ``` Something just landed. ```tsx import { ShakeEmphasis } from "@/remotion/primitives/shake-emphasis"; <ShakeEmphasis startAtInFrames={24}> <Headline /> </ShakeEmphasis> ``` ## Noise, not a sine A shake driven by `sin(frame)` is a vibration: every swing is the same size, so it reads as a motor rather than as an impact. This samples a deterministic value noise at `frequency` samples per second and smoothsteps between samples, which gives the uneven amplitude a real hit has. The smoothstep is what keeps it from strobing when `frequency` is high. ## The envelope is the component Displacement peaks on the impact frame and decays to nothing, so the element is at rest before and after. Nothing loops by default: a shake that keeps going is a vibration, and the emphasis is gone within half a second of the hit anyway. Pass `repeatEveryInFrames` only when the shake is riding a beat. `punch` compresses the element on impact and lets it overshoot past rest on the way back. Without it the shake reads as the camera moving rather than as the element being hit. ## Timing it An impact wants to land on a cut, a beat, or the frame a number finishes counting. `startAtInFrames` is in the surrounding sequence's frame space, so inside a `<Sequence>` it is relative to that sequence's start. `durationInFrames` is the decay, not a hold: 12 frames is a snap, 24 is a heavy landing, and much beyond that stops reading as an impact at all. ## Usage ```tsx import { ShakeEmphasis } from "@/remotion/primitives/shake-emphasis"; <ShakeEmphasis startAtInFrames={24}> <Headline /> </ShakeEmphasis> ``` Value noise, not a sine: every swing is a different size, which is the difference between an impact and a motor. The envelope decays to rest, so the element is still before and after: a shake that keeps going is a vibration. ## Props | Name | Type | Default | Description | | --- | --- | --- | --- | | `children` | `ReactNode` | - | What gets hit. | | `startAtInFrames` | `number` | `0` | Frame the impact lands on. | | `durationInFrames` | `number` | `18` | How long the shake takes to die out. Impacts are short. | | `intensity` | `number` | `16` | Peak displacement, in px. | | `rotation` | `number` | `1.6` | Peak rotation in degrees. 3 already reads as violent. | | `punch` | `number` | `0.05` | Scale compression on impact. 0 shakes without a hit. | | `frequency` | `number` | `22` | Rattle rate, in shakes per second. | | `axis` | `"both" \| "x" \| "y"` | `"both"` | Which way it moves. | | `decay` | `number` | `2.2` | How fast the shake dies. 1 is even, 3 is a sharp hit. | | `repeatEveryInFrames` | `number` | - | Repeat the impact on this interval. Omit for a single hit. | | `seed` | `number` | `1` | Changes the rattle without changing any other prop. | ## Related - [Squash Stretch](https://remotionui.com/docs/components/squash-stretch.md) - [Glow Pulse](https://remotionui.com/docs/components/glow-pulse.md) - [RGB Glitch Text](https://remotionui.com/docs/components/rgb-glitch-text.md) ## Machine-readable references - Props and usage as JSON: https://remotionui.com/ai/components/shake-emphasis.json - Component index: https://remotionui.com/ai/components.json --- # Skew In > Lean in and straighten up, an editorial entrance built from shear plus travel. Install with npx remotion-ui@latest add skew-in. Source: https://remotionui.com/docs/components/skew-in ## Installation ```bash npx remotion-ui@latest add skew-in ``` Leans in and straightens up. A shear and a slide, opposed on purpose. ## Why the shear opposes the travel The element leans *into* the direction it is travelling from, so it looks dragged upright by its own momentum rather than sliding in pre-formed. That opposition is the whole component: `slide-left` with a `skew()` in `style` leans the other way and reads as a wobble. ```tsx import { SkewIn } from "@/remotion/primitives/skew-in"; <SkewIn skew={16} travel={72} durationInFrames={40}> <h1>Leans in, straightens up</h1> </SkewIn> ``` ## Pivot `origin` defaults to `bottom left`. A shear pivoted at the centre lifts the baseline of a headline, and the line below it visibly jumps as the shear resolves. Put the pivot on the baseline corner and only the top of the element moves. ## Exits Like every wrapper primitive here, it takes `exit`, `exitAtInFrames`, `exitInFrames` and `exitDirection` from the shared enter/exit contract. Inside a `<Sequence durationInFrames={n}>`, `exit` alone lands the element out at the end of its slot. `exitDirection="continue"` carries the lean on through instead of straightening back. ## Usage ```tsx import { SkewIn } from "@/remotion/primitives/skew-in"; <SkewIn skew={16} travel={72} durationInFrames={40}> <h1>Leans in, straightens up</h1> </SkewIn> ``` The shear opposes the travel on purpose: the element looks dragged upright by its own momentum. ## Props | Name | Type | Default | Description | | --- | --- | --- | --- | | `children` | `ReactNode` | - | What leans in. | | `skew` | `number` | `14` | Horizontal shear it starts at, in degrees. | | `skewY` | `number` | `0` | Vertical shear it starts at. Small values only. | | `travel` | `number` | `56` | How far it slides in, in px. Travels against the lean. | | `direction` | `"left" \| "right"` | `"left"` | Which way the element leans on the way in. | | `origin` | `TransformOrigin` | `"bottom left"` | Pivot. A centre pivot lifts the baseline and the line below jumps. | | `durationInFrames` | `number` | `30` | Length of the entrance. | | `delayInFrames` | `number` | `0` | Frames to wait before it starts. | | `spring` | `MotionSpring` | - | Drive the entrance with a spring instead of the ease-out curve. | | `exit` | `boolean` | `false` | Land out at the end of the surrounding Sequence. | | `exitAtInFrames` | `number` | - | Frame the exit starts on. Overrides the automatic timing. | | `exitInFrames` | `number` | - | Length of the exit. Defaults to 70% of the entrance. | | `exitDirection` | `"reverse" \| "continue"` | `"reverse"` | Straighten back, or carry the lean on through. | | `block` | `boolean` | `false` | Fill the parent's width instead of shrink-wrapping. | ## Related - [Slide Left](https://remotionui.com/docs/components/slide-left.md) - [Rotate In](https://remotionui.com/docs/components/rotate-in.md) - [Spring In](https://remotionui.com/docs/components/spring-in.md) ## Machine-readable references - Props and usage as JSON: https://remotionui.com/ai/components/skew-in.json - Component index: https://remotionui.com/ai/components.json --- # Slide Left > Slide in from either side, with an optional mask reveal and an automatic exit. Source: https://remotionui.com/docs/components/slide-left ## Installation ```bash npx remotion-ui@latest add slide-left ``` Slides in on the horizontal, the reading axis, so it suits list rows and lower thirds where a rise would fight the line above. Set `from="right"` to come in from the other side, or `mask` to slide out of a clipped box. ## Usage ```tsx import { SlideLeft } from "@/remotion/primitives/slide-left"; <SlideLeft distance={60} from="left"> <p>Slide in from the left</p> </SlideLeft> ``` ## Props | Name | Type | Default | Description | | --- | --- | --- | --- | | `children` (required) | `ReactNode` | - | Content to animate. | | `durationInFrames` | `number` | `30` | Length of the enter animation in frames. | | `delayInFrames` | `number` | `0` | Frames to wait before the animation starts. | | `spring` | `"smooth" \| "snappy" \| "bouncy" \| Partial<SpringConfig> \| boolean` | - | Drive the entrance with a spring instead of the ease-out curve. | | `exit` | `boolean` | `false` | Animate back out, landing on the last frame of the surrounding Sequence. | | `exitInFrames` | `number` | `70% of durationInFrames` | Length of the exit. Exits are shorter than entrances. | | `exitAtInFrames` | `number` | - | Frame the exit starts on, overriding the end-of-window timing. | | `exitTravel` | `number` | `0.6` | Share of the enter distance the exit travels. | | `exitDirection` | `"reverse" \| "continue"` | `"reverse"` | reverse leaves the way it came in, continue carries on through. | | `block` | `boolean` | `false` | Fill the parent's width instead of shrink-wrapping the child. | | `style` | `CSSProperties` | - | Styles merged onto the wrapper. | | `distance` | `number` | `scaled 60px` | Horizontal offset in pixels at the start. Under mask, defaults to the element's own width. | | `from` | `"left" \| "right"` | `"left"` | Side the child travels in from. | | `mask` | `boolean` | `false` | Clip the child to its own box so it slides out of a mask. | ## Related - [Slide Up](https://remotionui.com/docs/components/slide-up.md) - [Stagger Children](https://remotionui.com/docs/components/stagger-children.md) ## Machine-readable references - Props and usage as JSON: https://remotionui.com/ai/components/slide-left.json - Component index: https://remotionui.com/ai/components.json --- # Slide Up > Rise into place, with an optional mask reveal and an automatic exit. Source: https://remotionui.com/docs/components/slide-up ## Installation ```bash npx remotion-ui@latest add slide-up ``` Rises into place while opacity leads the travel: the fade is finished at 55% of the move, so the element lands solid rather than still resolving as it stops. `mask` clips the child to its own box so it rises out of a mask instead, the editorial move for a headline. Under a mask the travel defaults to the element's own height, which is the only distance that actually clears it. ## Usage ```tsx import { SlideUp } from "@/remotion/primitives/slide-up"; <SlideUp mask exit> <h1>Title</h1> </SlideUp> ``` ## Props | Name | Type | Default | Description | | --- | --- | --- | --- | | `children` (required) | `ReactNode` | - | Content to animate. | | `durationInFrames` | `number` | `30` | Length of the enter animation in frames. | | `delayInFrames` | `number` | `0` | Frames to wait before the animation starts. | | `spring` | `"smooth" \| "snappy" \| "bouncy" \| Partial<SpringConfig> \| boolean` | - | Drive the entrance with a spring instead of the ease-out curve. | | `exit` | `boolean` | `false` | Animate back out, landing on the last frame of the surrounding Sequence. | | `exitInFrames` | `number` | `70% of durationInFrames` | Length of the exit. Exits are shorter than entrances. | | `exitAtInFrames` | `number` | - | Frame the exit starts on, overriding the end-of-window timing. | | `exitTravel` | `number` | `0.6` | Share of the enter distance the exit travels. | | `exitDirection` | `"reverse" \| "continue"` | `"reverse"` | reverse leaves the way it came in, continue carries on through. | | `block` | `boolean` | `false` | Fill the parent's width instead of shrink-wrapping the child. | | `style` | `CSSProperties` | - | Styles merged onto the wrapper. | | `distance` | `number` | `scaled 40px` | Vertical offset in pixels at the start. Under mask, defaults to the element's own height. | | `mask` | `boolean` | `false` | Clip the child to its own box so it rises out of a mask instead of fading up. | | `maskPadding` | `number` | `0` | Extra room inside the mask so descenders are not clipped. | ## Related - [Slide Left](https://remotionui.com/docs/components/slide-left.md) - [Fade In](https://remotionui.com/docs/components/fade-in.md) ## Machine-readable references - Props and usage as JSON: https://remotionui.com/ai/components/slide-up.json - Component index: https://remotionui.com/ai/components.json --- # Spring In > Spring-driven scale and rise, with snappy, smooth and bouncy presets. Source: https://remotionui.com/docs/components/spring-in ## Installation ```bash npx remotion-ui@latest add spring-in ``` Scale and a short rise driven by `spring()`, so the element carries weight into its stop instead of easing to a halt. `config="bouncy"` overshoots: both the scale and the rise pass their resting value and settle back, which is the reason to use a spring at all. ## Usage ```tsx import { SpringIn } from "@/remotion/primitives/spring-in"; <SpringIn config="bouncy" durationInFrames={40}> <div>Physical entrance</div> </SpringIn> ``` `config="bouncy"` overshoots both the scale and the rise, then settles: the reason to use a spring at all. ## Props | Name | Type | Default | Description | | --- | --- | --- | --- | | `children` (required) | `ReactNode` | - | Content to animate. | | `durationInFrames` | `number` | `30` | Length of the enter animation in frames. | | `delayInFrames` | `number` | `0` | Frames to wait before the animation starts. | | `exit` | `boolean` | `false` | Animate back out, landing on the last frame of the surrounding Sequence. | | `exitInFrames` | `number` | `70% of durationInFrames` | Length of the exit. Exits are shorter than entrances. | | `exitAtInFrames` | `number` | - | Frame the exit starts on, overriding the end-of-window timing. | | `exitTravel` | `number` | `0.6` | Share of the enter distance the exit travels. | | `exitDirection` | `"reverse" \| "continue"` | `"reverse"` | reverse leaves the way it came in, continue carries on through. | | `block` | `boolean` | `false` | Fill the parent's width instead of shrink-wrapping the child. | | `style` | `CSSProperties` | - | Styles merged onto the wrapper. | | `config` | `"smooth" \| "snappy" \| "bouncy" \| Partial<SpringConfig>` | `"snappy"` | Spring preset, or an override on the snappy config. | | `from` | `number` | `0.88` | Scale at the start of the entrance. | | `travel` | `number` | `scaled 14px` | How far it rises as it springs. | | `origin` | `TransformOrigin` | `"center"` | Point the scale grows from. | ## Related - [Scale In](https://remotionui.com/docs/components/scale-in.md) - [Rotate In](https://remotionui.com/docs/components/rotate-in.md) ## Machine-readable references - Props and usage as JSON: https://remotionui.com/ai/components/spring-in.json - Component index: https://remotionui.com/ai/components.json --- # Squash Stretch > The animation principle, as a primitive. Install with npx remotion-ui@latest add squash-stretch. Source: https://remotionui.com/docs/components/squash-stretch ## Installation ```bash npx remotion-ui@latest add squash-stretch ``` Weight, without a physics engine. ```tsx import { SquashStretch } from "@/remotion/primitives/squash-stretch"; <SquashStretch mode="bounce" periodInFrames={36}> <Ball /> </SquashStretch> ``` ## Three shapes of one idea `bounce` is the textbook ball: it flattens on contact, elongates through the fast part of the travel, and hangs round at the apex where it is slowest. `pulse` is the same deform without the travel, for a logo or an icon that needs weight in place. `impact` fires once, for something landing into a layout. Pair it with an entrance primitive, which owns the arrival, and let this own the landing. ## Volume preservation `scaleX` is the reciprocal square root of `scaleY`, which keeps `scaleX² × scaleY` constant, the volume of a body of revolution, and the same rule an animator draws by. Squashing one axis without widening the other is the single thing that makes a deform read as a scale bug rather than as rubber, because the eye tracks area. ## Pivot `origin` defaults to `bottom`, the floor contact. A deform around the centre lifts the element off its own baseline and the floor stops reading as a floor. Use `center` only when the element is genuinely free-floating. ## Timing `contact` is how much of the cycle the flatten lasts. Short contacts read as hard surfaces; long ones read as soft ones. The squash is the frame everyone remembers, so if you are picking a poster frame or a loop point, pick a contact. ## Usage ```tsx import { SquashStretch } from "@/remotion/primitives/squash-stretch"; <SquashStretch mode="bounce" periodInFrames={36}> <Ball /> </SquashStretch> ``` Volume is preserved: `scaleX` is the reciprocal square root of `scaleY`, because the eye tracks area and a one-axis squash reads as a scale bug. The pivot is the bottom by default; deforming around the centre lifts the element off its own baseline and the floor stops reading as a floor. ## Props | Name | Type | Default | Description | | --- | --- | --- | --- | | `children` | `ReactNode` | - | What deforms. | | `mode` | `"bounce" \| "pulse" \| "impact"` | `"bounce"` | Travel and deform, breathe in place, or deform once. | | `periodInFrames` | `number` | `36` | Length of one cycle. | | `travel` | `number` | `90` | Bounce height, in px. 0 deforms in place. | | `squash` | `number` | `0.28` | How hard it flattens on contact. Above 0.4 reads as cartoon. | | `stretch` | `number` | `0.16` | How far it elongates at speed. | | `startAtInFrames` | `number` | `0` | Frame the cycle starts on. | | `contact` | `number` | `0.22` | How much of the cycle the contact lasts, 0-1. | | `origin` | `"bottom" \| "center" \| "top"` | `"bottom"` | Pivot. `bottom` is the floor contact. | ## Related - [Spring In](https://remotionui.com/docs/components/spring-in.md) - [Shake Emphasis](https://remotionui.com/docs/components/shake-emphasis.md) - [Counter](https://remotionui.com/docs/components/counter.md) ## Machine-readable references - Props and usage as JSON: https://remotionui.com/ai/components/squash-stretch.json - Component index: https://remotionui.com/ai/components.json --- # Stagger Children > Offset children onto their own sequences, forward, reverse, centre or edge order, in and out. Source: https://remotionui.com/docs/components/stagger-children ## Installation ```bash npx remotion-ui@latest add stagger-children ``` Wraps each child in a `<Sequence layout="none">` on its own slot, so every child animates from its local frame 0 and needs no delay of its own. `order` changes which child goes first: `center` runs outwards from the middle, `edges` runs inwards. Both read as one gesture across a row rather than a queue. `exitStaggerInFrames` moves each child's exit earlier in the order it arrived, without cutting its slot short, so nothing unmounts under the layout. ## Usage ```tsx import { StaggerChildren } from "@/remotion/primitives/stagger-children"; import { SlideLeft } from "@/remotion/primitives/slide-left"; <StaggerChildren staggerInFrames={8} exitStaggerInFrames={6}> {items.map((item) => ( <SlideLeft key={item} exit><span>{item}</span></SlideLeft> ))} </StaggerChildren> ``` Each child gets a Sequence with layout="none", so it animates from its own frame 0. Inside a bounded window the slot carries an end too, which is what times each child's exit. ## Props | Name | Type | Default | Description | | --- | --- | --- | --- | | `children` (required) | `ReactNode` | - | Child elements to stagger in sequence. | | `staggerInFrames` | `number` | `8` | Frames between one child starting and the next. | | `baseDelayInFrames` | `number` | `0` | Frames before the first child starts. | | `order` | `"forward" \| "reverse" \| "center" \| "edges"` | `"forward"` | Which child goes first. center runs outwards from the middle, edges runs inwards. | | `exitStaggerInFrames` | `number` | `0` | Frames between one child leaving and the next, in the order they arrived. 0 lands the group together. | ## Related - [Slide Left](https://remotionui.com/docs/components/slide-left.md) - [Fade In](https://remotionui.com/docs/components/fade-in.md) ## Machine-readable references - Props and usage as JSON: https://remotionui.com/ai/components/stagger-children.json - Component index: https://remotionui.com/ai/components.json --- # Captions > Word-timed captions, karaoke highlights, and subtitle tracks driven by transcript data. Source: https://remotionui.com/docs/components/captions Caption components take timed words or SRT cues and render them in sync with the frame. Most accept the `@remotion/captions` format, so a transcript drops straight in. ## Components - [Caption Emoji Beat](https://remotionui.com/docs/components/caption-emoji-beat.md): Emoji punctuation landing on beats. Install with npx remotion-ui@latest add caption-emoji-beat. - [Caption Highlight](https://remotionui.com/docs/components/caption-highlight.md): TikTok-style word highlight captions for Remotion. Install with npx remotion-ui@latest add caption-highlight. - [Caption Scene](https://remotionui.com/docs/components/caption-scene.md): Lower-third captions synced to audio. - [Karaoke Captions](https://remotionui.com/docs/components/karaoke-captions.md): Active-word caption styling for social clips. - [Speaker Label Captions](https://remotionui.com/docs/components/speaker-label-captions.md): Multi-speaker caption track with name tags and colour coding. Install with npx remotion-ui@latest add speaker-label-captions. - [SRT Caption Track](https://remotionui.com/docs/components/srt-caption-track.md): Render Remotion captions straight from an SRT or WebVTT file. Install with npx remotion-ui@latest add srt-caption-track. - [Subtitle Translate](https://remotionui.com/docs/components/subtitle-translate.md): Dual-language stacked subtitles. Install with npx remotion-ui@latest add subtitle-translate. - [Transcript Scroll](https://remotionui.com/docs/components/transcript-scroll.md): Full transcript scrolling with the active line marked. Install with npx remotion-ui@latest add transcript-scroll. - [Word Pop Captions](https://remotionui.com/docs/components/word-pop-captions.md): One word at a time, alone on frame. Install with npx remotion-ui@latest add word-pop-captions. --- # Caption Emoji Beat > Emoji punctuation landing on beats. Install with npx remotion-ui@latest add caption-emoji-beat. Source: https://remotionui.com/docs/components/caption-emoji-beat ## Installation ```bash npx remotion-ui@latest add caption-emoji-beat ``` Emoji stamps landing on the beat, over an optional caption line. ```tsx import { CaptionEmojiBeat } from "@/remotion/primitives/caption-emoji-beat"; <CaptionEmojiBeat text="Punctuate the beat, not the sentence" beats={[ { emoji: "🔥", atInFrames: 10, x: 22, y: 26, rotate: -8 }, { emoji: "🚀", atInFrames: 80, x: 50, y: 16, scale: 96 }, ]} /> ``` ## Beats are scheduled, not detected Each stamp lands on a frame you give it rather than on an audio envelope read at render time. The beats of a track are known when the edit is cut, and a detector, even a good one, drifts against the music it is supposed to be hitting. If you have beat times in seconds, multiply by `fps` and pass frames. ## The wobble decays A stamp arrives with overshoot, swings once, then releases. The swing is keyed to its own landing rather than to the clock, so every emoji wobbles by the same amount whenever it arrives, and it decays to nothing: a held frame is still, and only arrivals move. `holdInFrames` is how long a stamp stays at full size before the release, which is shorter than the landing and accelerates away. ## Placement `x` and `y` are percentages of the frame, so a layout survives a change of resolution. Keep stamps clear of the caption line's own box; the text is centred and wraps inside 12% side margins. ## Usage ```tsx import { CaptionEmojiBeat } from "@/remotion/primitives/caption-emoji-beat"; <CaptionEmojiBeat text="Punctuate the beat, not the sentence" beats={[ { emoji: "🔥", atInFrames: 10, x: 22, y: 26, rotate: -8 }, { emoji: "🚀", atInFrames: 80, x: 50, y: 16, scale: 96 }, ]} /> ``` Beats are scheduled on frames rather than detected from audio: the beats are known when the edit is cut, and a render-time detector drifts against the music it is meant to hit. The wobble is keyed to each stamp's own landing, so it decays to nothing and a held frame is still. ## Props | Name | Type | Default | Description | | --- | --- | --- | --- | | `beats` | `EmojiBeat[]` | `required` | `{ emoji, atInFrames, x, y, scale?, rotate? }`. x/y are percentages of the frame. | | `text` | `string` | `undefined` | Caption line the emoji punctuate. Omit for emoji alone. | | `size` | `number` | `84` | Base emoji size in px, overridable per beat. | | `landInFrames` | `number` | `7` | Frames an emoji takes to land. | | `holdInFrames` | `number` | `26` | Frames it holds at full size before releasing. | | `overshoot` | `number` | `1.35` | Scale overshoot on the way in. 1 lands flat. | | `wobbleInDegrees` | `number` | `9` | Swing after landing. Decays to nothing. | | `textAtInFrames` | `number` | `0` | Frame the caption line arrives on. | | `frame` | `number` | `undefined` | Frame override: pass the parent frame inside a `<Sequence>`. | ## Related - [Confetti Burst](https://remotionui.com/docs/components/confetti-burst.md) - [Karaoke Captions](https://remotionui.com/docs/components/karaoke-captions.md) - [Beat Pulse Grid](https://remotionui.com/docs/components/beat-pulse-grid.md) ## Machine-readable references - Props and usage as JSON: https://remotionui.com/ai/components/caption-emoji-beat.json - Component index: https://remotionui.com/ai/components.json --- # Caption Highlight > TikTok-style word highlight captions for Remotion. Install with npx remotion-ui@latest add caption-highlight. Source: https://remotionui.com/docs/components/caption-highlight ## Installation ```bash npx remotion-ui@latest add caption-highlight ``` Word-by-word highlight driven by caption token timestamps. ## Usage ```tsx import { CaptionHighlight } from "@/remotion/primitives/caption-highlight"; <CaptionHighlight page={page} activeColor="#60a5fa" /> ``` Advanced. Installs @remotion/captions. ## Props | Name | Type | Default | Description | | --- | --- | --- | --- | | `page` (required) | `TikTokPage` | - | Caption page from createTikTokStyleCaptions. | | `activeColor` | `string` | `"#ff6b00"` | Highlight color for the active word. | | `inactiveColor` | `string` | `"#111111"` | Color for inactive words. | | `fontSize` | `number` | `64 (scaled)` | Caption font size in pixels. | | `fontWeight` | `number \| string` | `650` | Resting weight. | | `activeWeight` | `number \| string` | `800` | Weight the active word steps to. | | `emphasisScale` | `number` | `EMPHASIS.subtle (1.05)` | Peak scale of the active word. | | `textAlign` | `"left" \| "center"` | `"center"` | Line alignment. | | `frame` | `number` | - | Frame override: pass the parent frame inside a Sequence. | ## Related - [Caption Scene](https://remotionui.com/docs/components/caption-scene.md) - [caption-utils](https://remotionui.com/docs/components/caption-utils.md) ## Machine-readable references - Props and usage as JSON: https://remotionui.com/ai/components/caption-highlight.json - Component index: https://remotionui.com/ai/components.json --- # Caption Scene > Lower-third captions synced to audio. Source: https://remotionui.com/docs/components/caption-scene ## Installation ```bash npx remotion-ui@latest add caption-scene ``` Full caption scene with safe-area positioning and page sequencing. ## Usage ```tsx import { CaptionScene } from "@/remotion/scenes/caption-scene"; <CaptionScene captions={captions} /> ``` Advanced. Installs @remotion/captions. ## Props | Name | Type | Default | Description | | --- | --- | --- | --- | | `captions` (required) | `Caption[]` | - | Remotion caption array. | | `combineTokensWithinMilliseconds` | `number` | `1200` | Words per caption page. | | `placement` | `"lower-third" \| "center"` | `"lower-third"` | Caption vertical placement. | | `mode` | `"highlight" \| "karaoke-scale" \| "karaoke-underline"` | `"highlight"` | Caption emphasis style. | ## Related - [Caption Highlight](https://remotionui.com/docs/components/caption-highlight.md) - [Social Clip](https://remotionui.com/docs/components/social-clip.md) ## Machine-readable references - Props and usage as JSON: https://remotionui.com/ai/components/caption-scene.json - Component index: https://remotionui.com/ai/components.json --- # Karaoke Captions > Active-word caption styling for social clips. Source: https://remotionui.com/docs/components/karaoke-captions ## Installation ```bash npx remotion-ui@latest add karaoke-captions ``` Caption primitive for active-word emphasis. Each word crosses one ramp (colour, scale and lift together) with an underline that wipes across the word's own timing. ## Usage ```tsx import { KaraokeCaptions } from "@/remotion/primitives/karaoke-captions"; <KaraokeCaptions page={page} mode="scale" /> ``` Use with caption-utils groupCaptionsIntoPages(). ## Props | Name | Type | Default | Description | | --- | --- | --- | --- | | `page` (required) | `TikTokPage` | - | Caption page from @remotion/captions. | | `mode` | `"scale" \| "underline"` | `"underline"` | Active word emphasis style. Both modes also pop and lift the word. | | `fontSize` | `number` | `66 (scaled)` | Caption size in px. | | `fontWeight` | `number \| string` | `800` | Caption weight. | | `emphasisScale` | `number` | `EMPHASIS.subtle (1.05)` | Peak scale of the active word. | | `activeColor` | `string` | `"#ff6b00"` | Color the active word crosses to. | | `completedColor` | `string` | `"#111111"` | Color for words already spoken. | | `inactiveColor` | `string` | `"rgba(17,17,17,0.32)"` | Color for words not yet spoken. | | `trackColor` | `string` | - | Underline track behind the wipe. Defaults to inactiveColor. | | `frame` | `number` | - | Frame override: pass the parent frame inside a Sequence. | ## Related - [Caption Highlight](https://remotionui.com/docs/components/caption-highlight.md) - [Caption Scene](https://remotionui.com/docs/components/caption-scene.md) ## Machine-readable references - Props and usage as JSON: https://remotionui.com/ai/components/karaoke-captions.json - Component index: https://remotionui.com/ai/components.json --- # Speaker Label Captions > Multi-speaker caption track with name tags and colour coding. Install with npx remotion-ui@latest add speaker-label-captions. Source: https://remotionui.com/docs/components/speaker-label-captions ## Installation ```bash npx remotion-ui@latest add speaker-label-captions ``` A caption track for more than one voice: name tag, colour, and a side of the frame per speaker. ```tsx import { SpeakerLabelCaptions } from "@/remotion/primitives/speaker-label-captions"; import { parseSubtitles } from "@/remotion/lib/caption-utils"; <SpeakerLabelCaptions cues={parseSubtitles(vttSource)} speakers={[ { name: "Nadia", color: "#e8b86d", align: "left" }, { name: "Sam", color: "#2dd4bf", align: "right" }, ]} /> ``` ## Identity three ways Tag, colour and alignment all carry the speaker, because each one fails somewhere: a tag alone is slow to read at caption speed, colour alone is invisible to a good share of viewers, and alignment alone cannot separate three voices. Undeclared speakers get a colour from the palette and alternate sides in the order they first appear. ## Cues Timings are in milliseconds, so a track parsed from SRT or WebVTT drops straight in: `parseSubtitles` already fills `speaker` from a WebVTT `<v Name>` tag. Between cues the last card holds rather than clearing. A card blinking out in every pause is more distracting than one that waits for the next line. `showPrevious` keeps the line before it on screen, dimmed to about a third; it is context, and matching the live line's weight would defeat both. ## Where it sits This is a track, not a frame: `talking-head-layout` handles the shot composition. They compose: put this over that. ## Usage ```tsx import { SpeakerLabelCaptions } from "@/remotion/primitives/speaker-label-captions"; import { parseSubtitles } from "@/remotion/lib/caption-utils"; <SpeakerLabelCaptions cues={parseSubtitles(vttSource)} speakers={[ { name: "Nadia", color: "#e8b86d", align: "left" }, { name: "Sam", color: "#2dd4bf", align: "right" }, ]} /> ``` Speaker identity is carried by tag, colour and side at once, because each fails alone: a tag is slow to read at caption speed, colour is invisible to many viewers, and alignment cannot separate three voices. Between cues the last card holds; blinking out in every pause is worse than waiting. ## Props | Name | Type | Default | Description | | --- | --- | --- | --- | | `cues` | `SubtitleCue[]` | `required` | `{ text, startMs, endMs, speaker? }`, the shape `parseSubtitles` returns. | | `speakers` | `SpeakerStyle[]` | `[]` | `{ name, color?, align? }` per voice. Undeclared voices are assigned. | | `defaultSpeaker` | `string` | `"Speaker"` | Name for cues that carry none. | | `fontSize` | `number` | `42` | Caption size. Tag and padding scale off it. | | `cardColor` | `string` | `rgba(12,12,18,0.82)` | Plate behind a line. | | `maxWidth` | `number` | `0.7` | Card width as a share of the frame. | | `showPrevious` | `boolean` | `true` | Keep the previous speaker's card on screen, dimmed. | | `enterInFrames` | `number` | `10` | Frames a card takes to arrive. | | `frame` | `number` | `undefined` | Frame override: pass the parent frame inside a `<Sequence>`. | ## Related - [SRT Caption Track](https://remotionui.com/docs/components/srt-caption-track.md) - [Transcript Scroll](https://remotionui.com/docs/components/transcript-scroll.md) - [Talking Head Layout](https://remotionui.com/docs/components/talking-head-layout.md) ## Machine-readable references - Props and usage as JSON: https://remotionui.com/ai/components/speaker-label-captions.json - Component index: https://remotionui.com/ai/components.json --- # SRT Caption Track > Render Remotion captions straight from an SRT or WebVTT file. Install with npx remotion-ui@latest add srt-caption-track. Source: https://remotionui.com/docs/components/srt-caption-track ## Installation ```bash npx remotion-ui@latest add srt-caption-track ``` Renders a caption track directly from an SRT or WebVTT file. This is a utility, not a look. Every caption style in the registry takes a `TikTokPage`, which until now had to be hand-authored, so the styles could only be demoed against a handful of fake words. This turns a real transcript into those pages and sequences them. ## Any caption style `renderPage` swaps in whichever style should draw the page. The default is `caption-highlight`. ```tsx <SrtCaptionTrack src={staticFile("episode.srt")} renderPage={(page) => <KaraokeCaptions page={page} mode="underline" />} /> ``` ## Subtitle files have no word timing An SRT cue says "these nine words happen between 4.2s and 6.8s" and nothing more, so a word-highlight style fed raw cues has nothing to highlight. `wordTiming="distribute"` (the default) spreads each cue's span across its words weighted by length, which tracks a read closely enough for a highlight to follow it. `wordTiming="cue"` keeps each cue as one token instead: honest, but only useful for styles that show a whole line at once. If real word timestamps are available (from Whisper, for instance), pass them through `captions` and no distribution happens. ## Loading `src` is fetched behind `delayRender()`, so the render waits for the file rather than producing empty frames. Pass `source` instead when the transcript text is already in hand. ## Usage ```tsx import { SrtCaptionTrack } from "@/remotion/primitives/srt-caption-track"; <SrtCaptionTrack src={staticFile("episode.srt")} /> // Any caption style can render the pages. <SrtCaptionTrack src={staticFile("episode.srt")} renderPage={(page) => <KaraokeCaptions page={page} mode="underline" />} /> ``` Utility, not a look. Installs @remotion/captions and caption-highlight. ## Props | Name | Type | Default | Description | | --- | --- | --- | --- | | `src` | `string` | - | URL of an SRT or WebVTT file. Fetched behind delayRender(). | | `source` | `string` | - | Raw subtitle text, when the transcript is already in hand. | | `captions` | `Caption[]` | - | Pre-parsed captions, e.g. from Whisper, which has real word timing. | | `wordTiming` | `"distribute" \| "cue"` | `"distribute"` | Subtitle files have no word timestamps. `distribute` spreads each cue across its words by length so highlight styles have something to highlight. | | `combineTokensWithinMilliseconds` | `number` | `1200` | Tokens closer than this share a page. | | `offsetInFrames` | `number` | `0` | Shift the whole track. Positive delays it. | | `renderPage` | `(page: TikTokPage, index: number) => ReactNode` | - | Draws one page. Defaults to CaptionHighlight. | | `activeColor` | `string` | `"#ff6b00"` | Passed to the default renderer. | | `inactiveColor` | `string` | `"#ffffff"` | Passed to the default renderer. | | `fontSize` | `number` | - | Passed to the default renderer. | ## Related - [Caption Highlight](https://remotionui.com/docs/components/caption-highlight.md) - [Karaoke Captions](https://remotionui.com/docs/components/karaoke-captions.md) - [Caption Scene](https://remotionui.com/docs/components/caption-scene.md) ## Machine-readable references - Props and usage as JSON: https://remotionui.com/ai/components/srt-caption-track.json - Component index: https://remotionui.com/ai/components.json --- # Subtitle Translate > Dual-language stacked subtitles. Install with npx remotion-ui@latest add subtitle-translate. Source: https://remotionui.com/docs/components/subtitle-translate ## Installation ```bash npx remotion-ui@latest add subtitle-translate ``` Two languages stacked in one subtitle block. ```tsx import { SubtitleTranslate } from "@/remotion/primitives/subtitle-translate"; <SubtitleTranslate cues={[ { text: "The transcript is the edit.", translation: "La transcripción es el montaje.", startMs: 0, endMs: 1450, }, ]} languageLabels={["EN", "ES"]} /> ``` ## The lines are not equals The primary carries full weight and ink; the secondary is smaller and dimmer. Style them the same and the block reads as one four-line caption: the viewer has to work out which half is theirs before they can read either. `primary` swaps which language leads without touching the data, so the same cue list serves both cuts of a video. ## Timing The secondary trails the primary by `secondaryOffsetInFrames`. Both landing on the same frame doubles the amount of new text at once; a few frames give the eye an order to take them in. Nothing renders between cues. Unlike a single-line speaker track, this block is tall enough that holding it through a pause covers the shot. ## Language tags `languageLabels` puts a fixed-width tag beside each line, so both lines start on the same left edge even though their type sizes differ. Omit it when the languages are obvious from their scripts. ## Usage ```tsx import { SubtitleTranslate } from "@/remotion/primitives/subtitle-translate"; <SubtitleTranslate cues={[ { text: "The transcript is the edit.", translation: "La transcripción es el montaje.", startMs: 0, endMs: 1450, }, ]} languageLabels={["EN", "ES"]} /> ``` The two lines are deliberately unequal in weight and ink: styled the same, the block reads as one four-line caption and the viewer has to work out which half is theirs. The secondary trails by a few frames so the eye is given an order. Nothing renders between cues; the block is tall enough that holding it would cover the shot. ## Props | Name | Type | Default | Description | | --- | --- | --- | --- | | `cues` | `TranslatedCue[]` | `required` | A `SubtitleCue` plus `translation`. | | `primary` | `"source" \| "translation"` | `"source"` | Which language leads. Swaps without touching the data. | | `fontSize` | `number` | `46` | Size of the primary line. | | `secondaryScale` | `number` | `0.72` | Secondary size, as a share of `fontSize`. | | `languageLabels` | `[string, string]` | `undefined` | Fixed-width tags beside each line, e.g. `["EN", "ES"]`. | | `backgroundColor` | `string` | `rgba(10,10,14,0.72)` | Plate behind both lines. `transparent` drops it. | | `maxWidth` | `number` | `0.78` | Block width as a share of the frame. | | `enterInFrames` | `number` | `10` | Frames a cue takes to arrive. | | `secondaryOffsetInFrames` | `number` | `4` | Frames the second line trails the first by. | | `frame` | `number` | `undefined` | Frame override: pass the parent frame inside a `<Sequence>`. | ## Related - [SRT Caption Track](https://remotionui.com/docs/components/srt-caption-track.md) - [Speaker Label Captions](https://remotionui.com/docs/components/speaker-label-captions.md) - [Caption Highlight](https://remotionui.com/docs/components/caption-highlight.md) ## Machine-readable references - Props and usage as JSON: https://remotionui.com/ai/components/subtitle-translate.json - Component index: https://remotionui.com/ai/components.json --- # Transcript Scroll > Full transcript scrolling with the active line marked. Install with npx remotion-ui@latest add transcript-scroll. Source: https://remotionui.com/docs/components/transcript-scroll ## Installation ```bash npx remotion-ui@latest add transcript-scroll ``` A readable transcript that scrolls, with the line being spoken marked. ```tsx import { TranscriptScroll } from "@/remotion/primitives/transcript-scroll"; import { parseSubtitles } from "@/remotion/lib/caption-utils"; <TranscriptScroll cues={parseSubtitles(vttSource)} width={740} height={400} /> ``` ## A document, not an overlay The lines before and after stay on screen, which is the point: the viewer sees where a quote sits in the conversation. When only the current line should exist, use `srt-caption-track` or `karaoke-captions` instead. ## The page glides Scroll position interpolates between the outgoing and incoming line's offsets over `settleInFrames`, rather than snapping to whichever line is active. Driving it off the index alone makes the page jump a full line height every time the transcript advances. Offsets are measured per line rather than assumed from a fixed pitch. A speaker tag adds height, and a fixed pitch drifts out of register down a long transcript. Wrapping is estimated from the character count at the component's own measure; the estimate rounds up, because an extra line of spacing is harmless where an overlap is not. ## Reading order `activeColor`, `readColor` and `idleColor` separate what is being said from what has been said and what is coming. `fadeEdges` masks the top and bottom so lines enter and leave the block instead of being cut off by it. ## Usage ```tsx import { TranscriptScroll } from "@/remotion/primitives/transcript-scroll"; import { parseSubtitles } from "@/remotion/lib/caption-utils"; <TranscriptScroll cues={parseSubtitles(vttSource)} width={740} height={400} /> ``` A document, not an overlay: surrounding lines stay on screen so a quote keeps its place in the conversation. Scroll position interpolates between the outgoing and incoming offsets rather than snapping to the active index, and every line's height is measured because a speaker tag would otherwise drift a fixed pitch out of register. ## Props | Name | Type | Default | Description | | --- | --- | --- | --- | | `cues` | `SubtitleCue[]` | `required` | `{ text, startMs, endMs, speaker? }`, in order. | | `width` | `number` | `720` | Block width. Wrapping is estimated at this measure. | | `height` | `number` | `420` | Visible height of the scrolling window. | | `fontSize` | `number` | `34` | Body size. Tags and spacing scale off it. | | `activeColor` | `string` | `"#fafafa"` | Ink of the line being spoken. | | `idleColor` | `string` | `rgba(250,250,250,0.3)` | Ink of lines not yet reached. | | `readColor` | `string` | `idleColor` | Ink of lines already read, when it should differ. | | `showSpeakers` | `boolean` | `true` | Name printed above a line when the speaker changes. | | `showMarker` | `boolean` | `true` | Accent rule down the left edge of the active line. | | `fadeEdges` | `number` | `90` | Mask height at the top and bottom, in px. 0 disables it. | | `settleInFrames` | `number` | `16` | Frames the scroll takes to settle on a new line. | | `frame` | `number` | `undefined` | Frame override: pass the parent frame inside a `<Sequence>`. | ## Related - [SRT Caption Track](https://remotionui.com/docs/components/srt-caption-track.md) - [Speaker Label Captions](https://remotionui.com/docs/components/speaker-label-captions.md) - [Karaoke Captions](https://remotionui.com/docs/components/karaoke-captions.md) ## Machine-readable references - Props and usage as JSON: https://remotionui.com/ai/components/transcript-scroll.json - Component index: https://remotionui.com/ai/components.json --- # Word Pop Captions > One word at a time, alone on frame. Install with npx remotion-ui@latest add word-pop-captions. Source: https://remotionui.com/docs/components/word-pop-captions ## Installation ```bash npx remotion-ui@latest add word-pop-captions ``` One word at a time, filling the frame. ```tsx import { WordPopCaptions } from "@/remotion/primitives/word-pop-captions"; import { groupCaptionsIntoPages } from "@/remotion/lib/caption-utils"; const [page] = groupCaptionsIntoPages(captions, 4000); <WordPopCaptions page={page} strokeWidth={4} /> ``` ## Where it sits No line context, deliberately. `caption-highlight` and `karaoke-captions` both show a full line with an active word, which is right when the sentence matters. This is the other style: the word *is* the frame, the eye has nothing to read ahead to, and the cut rate carries the energy. Because only one token is on screen, nothing reflows: each word can be scaled, tilted and stroked without disturbing a neighbour. ## Gaps stay empty Between tokens the component renders nothing rather than holding the last word. A word left standing through a pause attributes silence to whoever spoke it, and in this style there is no line for it to sit inside. ## Rhythm `tiltInDegrees` alternates direction word to word; a single tilt direction at speed reads as one frame stuttering. `accentEvery` recolours every nth word, which keeps a long run from flattening out. Set it to `0` for one colour throughout. `popInFrames` is short by default: a word may only hold for 200ms, so the arrival has to be over well inside that. ## Usage ```tsx import { WordPopCaptions } from "@/remotion/primitives/word-pop-captions"; import { groupCaptionsIntoPages } from "@/remotion/lib/caption-utils"; const [page] = groupCaptionsIntoPages(captions, 4000); <WordPopCaptions page={page} strokeWidth={4} /> ``` No line context at all, which is what separates it from `caption-highlight` and `karaoke-captions`. Between tokens it renders nothing rather than holding the last word: a word left standing through a pause attributes the silence to whoever spoke it. The tilt alternates because one direction at speed reads as a stutter. ## Props | Name | Type | Default | Description | | --- | --- | --- | --- | | `page` | `TikTokPage` | `required` | Token page from `groupCaptionsIntoPages`. One token is shown at a time. | | `color` | `string` | `"#fafafa"` | Word ink. | | `accentColor` | `string` | `"#e8b86d"` | Ink for every nth word. | | `accentEvery` | `number` | `3` | Accent cadence. 0 keeps one colour throughout. | | `fontSize` | `number` | `scaled 120` | Defaults to a width-scaled 120px. | | `uppercase` | `boolean` | `true` | Uppercase the word: the default look for this style. | | `popScale` | `number` | `1.16` | Peak scale on arrival before it settles to 1. | | `tiltInDegrees` | `number` | `2.5` | Arrival tilt. Alternates direction word to word. | | `popInFrames` | `number` | `6` | Frames the pop takes to settle. | | `strokeWidth` | `number` | `0` | Chunky outline behind the word, as used on social captions. | | `frame` | `number` | `undefined` | Frame override: pass the parent frame inside a `<Sequence>`. | ## Related - [Karaoke Captions](https://remotionui.com/docs/components/karaoke-captions.md) - [Caption Highlight](https://remotionui.com/docs/components/caption-highlight.md) - [SRT Caption Track](https://remotionui.com/docs/components/srt-caption-track.md) ## Machine-readable references - Props and usage as JSON: https://remotionui.com/ai/components/word-pop-captions.json - Component index: https://remotionui.com/ai/components.json --- # Audio > Waveforms, meters, and beat-reactive visuals that read an audio file on every frame. Source: https://remotionui.com/docs/components/audio Audio components analyse an audio source and turn its amplitude or frequency data into motion. Use them for audiograms, podcast clips, and anything that should move with the sound. ## Components - [Audio Pulse](https://remotionui.com/docs/components/audio-pulse.md): Audio-reactive pulse rings. - [Audio Reactive Scale](https://remotionui.com/docs/components/audio-reactive-scale.md): Scale any child by per-frame audio amplitude in Remotion. Install with npx remotion-ui@latest add audio-reactive-scale. - [Audio Scrubber](https://remotionui.com/docs/components/audio-scrubber.md): Waveform with travelling playhead and time labels. Install with npx remotion-ui@latest add audio-scrubber. - [Audiogram Bars](https://remotionui.com/docs/components/audiogram-bars.md): Audio-reactive spectrum bar visualization. - [Audiogram Scene](https://remotionui.com/docs/components/audiogram-scene.md): Podcast audiogram layout with spectrum bars. - [Beat Pulse Grid](https://remotionui.com/docs/components/beat-pulse-grid.md): Grid cells pulsing with the track. Install with npx remotion-ui@latest add beat-pulse-grid. - [Voice Note Bubble](https://remotionui.com/docs/components/voice-note-bubble.md): Chat-style audio message with waveform and playhead. Install with npx remotion-ui@latest add voice-note-bubble. - [VU Meter](https://remotionui.com/docs/components/vu-meter.md): Segmented level meter with peak hold. Install with npx remotion-ui@latest add vu-meter. - [Waveform Bars Radial](https://remotionui.com/docs/components/waveform-bars-radial.md): Circular bars around a centre element. Install with npx remotion-ui@latest add waveform-bars-radial. - [Waveform Line](https://remotionui.com/docs/components/waveform-line.md): Audio waveform line visualization. --- # Audio Pulse > Audio-reactive pulse rings. Source: https://remotionui.com/docs/components/audio-pulse ## Installation ```bash npx remotion-ui@latest add audio-pulse ``` Bass-reactive pulse rings for podcast and music visuals. ## Usage ```tsx import { AudioPulse } from "@/remotion/primitives/audio-pulse"; <AudioPulse src={staticFile("voice.wav")} /> ``` Advanced. Installs @remotion/media-utils. ## Props | Name | Type | Default | Description | | --- | --- | --- | --- | | `src` (required) | `string` | - | Audio source. | | `size` | `number` | `240` | Pulse diameter in px. | | `color` | `string` | `"#e8b86d"` | Ring and core color. | | `ringCount` | `number` | `3` | Number of reactive rings. | | `sensitivity` | `number` | `1` | Multiplier on the measured level before it drives the rings. | | `frame` | `number` | - | Frame override: pass the parent frame inside a Sequence. | ## Related - [Waveform Line](https://remotionui.com/docs/components/waveform-line.md) - [Audiogram Scene](https://remotionui.com/docs/components/audiogram-scene.md) ## Machine-readable references - Props and usage as JSON: https://remotionui.com/ai/components/audio-pulse.json - Component index: https://remotionui.com/ai/components.json --- # Audio Reactive Scale > Scale any child by per-frame audio amplitude in Remotion. Install with npx remotion-ui@latest add audio-reactive-scale. Source: https://remotionui.com/docs/components/audio-reactive-scale ## Installation ```bash npx remotion-ui@latest add audio-reactive-scale ``` Wraps anything and scales it by the track's per-frame amplitude. It draws nothing of its own on purpose: a logo, a chart, or a whole scene can be made to breathe with the music by wrapping it, and the wrapper stays composable with the enter/exit primitives above and below it. ## Picking a band `band` selects which part of the spectrum drives the motion. `bass` (the default) is weighted toward the low end so the element moves on the kick rather than on hats. `full` follows overall loudness, which suits speech. ## Shared amplitude The level comes from `useAudioAmplitude()` in `audio-viz-utils`, the same path `audio-pulse` uses. Two components pointed at one track therefore pump in step instead of each running their own FFT with slightly different constants. ## Source format `useWindowedAudioData()` only accepts uncompressed audio, so `src` must be a `.wav`. Pass it through `staticFile()`. ## Usage ```tsx import { AudioReactiveScale } from "@/remotion/primitives/audio-reactive-scale"; <AudioReactiveScale src={staticFile("track.wav")} maxScale={1.2}> <Img src={staticFile("logo.png")} /> </AudioReactiveScale> ``` Shares `useAudioAmplitude()` with audio-pulse, so two components on one track pump in step. ## Props | Name | Type | Default | Description | | --- | --- | --- | --- | | `src` (required) | `string` | - | Audio source. `useWindowedAudioData()` requires an uncompressed .wav. | | `children` (required) | `ReactNode` | - | Anything to scale with the track. | | `minScale` | `number` | `1` | Scale at silence. | | `maxScale` | `number` | `1.16` | Scale at a full-amplitude hit. | | `band` | `"low" \| "mid" \| "high" \| "full" \| "bass"` | `"bass"` | Which slice of the spectrum drives the motion. | | `sensitivity` | `number` | `1` | Multiplies the level before compression. | | `compression` | `number` | `0.78` | Exponent on the level. Below 1 lifts quiet passages. | | `axis` | `"both" \| "x" \| "y"` | `"both"` | Restrict the scale to one axis. | | `tilt` | `number` | `0` | Degrees of rotation at a full hit. | | `minOpacity` | `number` | `1` | Opacity at silence. Left at 1 the wrapper never touches opacity. | | `frame` | `number` | - | Frame override: pass the parent frame inside a Sequence. | ## Related - [Audio Pulse](https://remotionui.com/docs/components/audio-pulse.md) - [Audiogram Bars](https://remotionui.com/docs/components/audiogram-bars.md) - [Waveform Line](https://remotionui.com/docs/components/waveform-line.md) ## Machine-readable references - Props and usage as JSON: https://remotionui.com/ai/components/audio-reactive-scale.json - Component index: https://remotionui.com/ai/components.json --- # Audio Scrubber > Waveform with travelling playhead and time labels. Install with npx remotion-ui@latest add audio-scrubber. Source: https://remotionui.com/docs/components/audio-scrubber ## Installation ```bash npx remotion-ui@latest add audio-scrubber ``` A waveform with a travelling playhead, chapter marks and time labels. ```tsx import { AudioScrubber } from "@/remotion/primitives/audio-scrubber"; <AudioScrubber durationInFrames={120} marks={[{ atInFrames: 66, label: "Quote" }]} /> ``` ## Position comes from frames Not from audio analysis. The playhead lands exactly on the frame the edit says it should, rather than wherever a detector thinks the audio is, and the scrubber can front a clip that is only being described. ## The waveform is static The colour boundary moves through it. That is the shape of a file, known before playback; animating the bar heights would be a live spectrum, which is `audiogram-bars`. Pass measured levels as `waveform`, or let a deterministic envelope be generated from `seed`. `mirrored` centres the bars the way an editor draws them; turn it off for a baseline-anchored bar chart. ## Marks `marks` places rules at frame positions with optional labels: chapter points, quotes, the cut you are about to make. They sit under the playhead, so the playhead is never hidden behind one. ## Usage ```tsx import { AudioScrubber } from "@/remotion/primitives/audio-scrubber"; <AudioScrubber durationInFrames={120} marks={[{ atInFrames: 66, label: "Quote" }]} /> ``` Position comes from frames rather than audio analysis, so the playhead lands on the frame the edit says it should. The waveform is static and the colour boundary moves through it; animating the heights would make it a live spectrum, which is `audiogram-bars`. Marks sit under the playhead so it is never hidden behind one. ## Props | Name | Type | Default | Description | | --- | --- | --- | --- | | `durationInFrames` | `number` | `required` | Clip length. The playhead crosses the track over exactly this. | | `waveform` | `number[]` | `generated` | Bar heights 0–1. Omitted, a deterministic envelope is built from `seed`. | | `barCount` | `number` | `96` | Bars drawn when the waveform is generated. | | `width` | `number` | `720` | Overall width, time labels included. | | `height` | `number` | `96` | Track height. Type scales off it. | | `playedColor` | `string` | `"#e8b86d"` | Bars already played. | | `unplayedColor` | `string` | `rgba(250,250,250,0.2)` | Bars not yet reached. | | `marks` | `{ atInFrames, label? }[]` | `undefined` | Chapter rules at frame positions. | | `mirrored` | `boolean` | `true` | Centre the bars the way an editor draws them. | | `showTime` | `boolean` | `true` | Elapsed and total readouts either side of the track. | | `delayInFrames` | `number` | `0` | Frames before the playhead starts moving. | | `frame` | `number` | `undefined` | Frame override: pass the parent frame inside a `<Sequence>`. | ## Related - [Voice Note Bubble](https://remotionui.com/docs/components/voice-note-bubble.md) - [Audiogram Bars](https://remotionui.com/docs/components/audiogram-bars.md) - [Waveform Line](https://remotionui.com/docs/components/waveform-line.md) ## Machine-readable references - Props and usage as JSON: https://remotionui.com/ai/components/audio-scrubber.json - Component index: https://remotionui.com/ai/components.json --- # Audiogram Bars > Audio-reactive spectrum bar visualization. Source: https://remotionui.com/docs/components/audiogram-bars ## Installation ```bash npx remotion-ui@latest add audiogram-bars ``` Log-spaced spectrum bands with decaying peak caps, driven by `visualizeAudio()` from `@remotion/media-utils`. ## Usage ```tsx import { AudiogramBars } from "@/remotion/primitives/audiogram-bars"; <AudiogramBars src={staticFile("podcast.wav")} height={120} /> ``` Advanced. Installs @remotion/media-utils. ## Props | Name | Type | Default | Description | | --- | --- | --- | --- | | `src` (required) | `string` | - | Audio file URL or staticFile path. | | `height` | `number` | `120` | Bar container height. | | `barColor` | `string` | `"#e8b86d"` | Bar fill color. | | `barColorEnd` | `string` | - | Second color for a gradient across the spectrum. Defaults to barColor. | | `barGap` | `number` | `3` | Gap between bars in px. | | `numberOfSamples` | `number` | `128` | FFT size used to sample the spectrum. | | `maxBarCount` | `number` | `48` | Log-spaced bands drawn from the spectrum. | | `align` | `"bottom" \| "center"` | `"bottom"` | Grow bars from the baseline or mirror them around it. | | `showPeaks` | `boolean` | `true` | Draw the decaying peak cap above each bar. | | `showReflection` | `boolean` | `false` | Faded mirrored copy below the baseline. Ignored when align is center. | | `frame` | `number` | - | Frame override: pass the parent frame inside a Sequence. | ## Related - [Audiogram Scene](https://remotionui.com/docs/components/audiogram-scene.md) ## Machine-readable references - Props and usage as JSON: https://remotionui.com/ai/components/audiogram-bars.json - Component index: https://remotionui.com/ai/components.json --- # Audiogram Scene > Podcast audiogram layout with spectrum bars. Source: https://remotionui.com/docs/components/audiogram-scene ## Installation ```bash npx remotion-ui@latest add audiogram-scene ``` Podcast-style layout combining title and live audio visualization. ## Usage ```tsx import { AudiogramScene } from "@/remotion/scenes/audiogram-scene"; <AudiogramScene src={staticFile("podcast.wav")} title="Episode 1" /> ``` ## Props | Name | Type | Default | Description | | --- | --- | --- | --- | | `src` (required) | `string` | - | Audio file URL or staticFile path. | | `title` | `string` | - | Episode title. | | `subtitle` | `string` | - | Optional subtitle. | | `logoSrc` | `string` | - | Optional brand mark above the title. | ## Related - [Audiogram Bars](https://remotionui.com/docs/components/audiogram-bars.md) - [Social Clip](https://remotionui.com/docs/components/social-clip.md) ## Machine-readable references - Props and usage as JSON: https://remotionui.com/ai/components/audiogram-scene.json - Component index: https://remotionui.com/ai/components.json --- # Beat Pulse Grid > Grid cells pulsing with the track. Install with npx remotion-ui@latest add beat-pulse-grid. Source: https://remotionui.com/docs/components/beat-pulse-grid ## Installation ```bash npx remotion-ui@latest add beat-pulse-grid ``` A grid of cells pulsing with the audio. ```tsx import { BeatPulseGrid } from "@/remotion/primitives/beat-pulse-grid"; <BeatPulseGrid src={audioSrc} columns={14} rows={7} mapping="radial" /> ``` ## Every cell has its own band A grid where each cell follows the overall level is one big flashing rectangle; the point of a grid is that its parts can disagree. `mapping` decides how the spectrum is laid over the geometry: `column` runs it left to right, `row` top to bottom, and `radial` maps it outward from the centre, which reads as a pulse travelling through the grid on the kick. ## The decaying trace Cells carry their band's peak, dimmed, under the live level: the same trick as a peak-hold meter. At 30fps a one-frame transient is invisible, and the trace is what makes the beat legible instead of a flicker. `floor` cuts the noise floor so quiet passages stay dark rather than shimmering, and the kick lifts every cell slightly, which is what makes the pattern read as one instrument rather than many. ## Scheduled beats instead When the beats are already known from the edit, `caption-emoji-beat` takes explicit frames. This component is for reacting to a track you are actually playing. ## Usage ```tsx import { BeatPulseGrid } from "@/remotion/primitives/beat-pulse-grid"; <BeatPulseGrid src={audioSrc} columns={14} rows={7} mapping="radial" /> ``` Each cell is bound to a band rather than the overall level: a grid where every cell agrees is one flashing rectangle. Cells carry their band's decaying peak under the live level, the same trick as a peak-hold meter, because a one-frame transient is invisible at 30fps. ## Props | Name | Type | Default | Description | | --- | --- | --- | --- | | `src` | `string` | `required` | Audio source. `.wav` only. | | `columns` | `number` | `12` | Cells across. | | `rows` | `number` | `6` | Cells down. | | `cellSize` | `number` | `34` | Cell edge length in px. | | `mapping` | `"column" \| "radial" \| "row"` | `"radial"` | How the spectrum is laid over the geometry. | | `idleColor` | `string` | `rgba(250,250,250,0.07)` | Cell colour at rest. | | `color` | `string` | `"#e8b86d"` | Cell colour at level. | | `peakColor` | `string` | `"#f472b6"` | Colour of the loudest cells. | | `pulseScale` | `number` | `0.28` | Extra scale a cell takes at full level. | | `floor` | `number` | `0.06` | Level below which a cell stays dark. Cuts the noise floor. | | `frame` | `number` | `undefined` | Frame override: pass the parent frame inside a `<Sequence>`. | ## Related - [Caption Emoji Beat](https://remotionui.com/docs/components/caption-emoji-beat.md) - [Audiogram Bars](https://remotionui.com/docs/components/audiogram-bars.md) - [Heatmap Grid](https://remotionui.com/docs/components/heatmap-grid.md) ## Machine-readable references - Props and usage as JSON: https://remotionui.com/ai/components/beat-pulse-grid.json - Component index: https://remotionui.com/ai/components.json --- # Voice Note Bubble > Chat-style audio message with waveform and playhead. Install with npx remotion-ui@latest add voice-note-bubble. Source: https://remotionui.com/docs/components/voice-note-bubble ## Installation ```bash npx remotion-ui@latest add voice-note-bubble ``` A chat-style audio message: waveform, playhead and running time. ```tsx import { VoiceNoteBubble } from "@/remotion/primitives/voice-note-bubble"; <VoiceNoteBubble durationInFrames={120} sender="Sam" avatar="S" /> ``` ## The waveform is static Only the colour moves through it, which is how every messaging app draws this. A bar chart that animated its heights would be a live spectrum: a different claim entirely, and one that contradicts the fact that a voice note's shape is known before you press play. The bar being crossed blends between the two colours, so the boundary travels smoothly instead of stepping bar by bar. ## Position comes from frames `durationInFrames` drives the playhead, not audio analysis, so the bubble can front a note that is described rather than played, and the playhead lands on the frame the edit says it should. `delayInFrames` staggers a second bubble in a conversation. ## Waveform data Pass real per-bar levels as `waveform` when you have them. Otherwise a deterministic envelope is generated from `seed`: bursts of syllables inside phrases with short gaps, because flat noise reads as a machine and a single sine reads as a tone. Changing `seed` changes the shape and nothing else. ## Usage ```tsx import { VoiceNoteBubble } from "@/remotion/primitives/voice-note-bubble"; <VoiceNoteBubble durationInFrames={120} sender="Sam" avatar="S" /> ``` The waveform is static and only the colour moves through it, as every messaging app draws it; animating bar heights would be a live spectrum, which contradicts the fact that a voice note's shape is known before playback. Position comes from frames, not analysis, so the bubble can front a note that is only described. ## Props | Name | Type | Default | Description | | --- | --- | --- | --- | | `durationInFrames` | `number` | `required` | Length of the note. The playhead crosses the bar over exactly this. | | `waveform` | `number[]` | `generated` | Bar heights 0–1. Omitted, a deterministic envelope is built from `seed`. | | `barCount` | `number` | `42` | Bars drawn when the waveform is generated. | | `seed` | `number` | `1` | Changes the generated envelope and nothing else. | | `barHeight` | `number` | `44` | Tallest bar. Type and padding scale off it. | | `avatar` | `string` | `undefined` | Initial or emoji in the round badge. | | `sender` | `string` | `undefined` | Name above the waveform. | | `showTime` | `boolean` | `true` | Elapsed / total readout under the bar. | | `align` | `"left" \| "right"` | `"left"` | Side of the frame the bubble sits on. | | `showPlayhead` | `boolean` | `true` | Dot riding the played/unplayed boundary. | | `delayInFrames` | `number` | `0` | Frames before the playhead starts moving. | | `frame` | `number` | `undefined` | Frame override: pass the parent frame inside a `<Sequence>`. | ## Related - [Audio Scrubber](https://remotionui.com/docs/components/audio-scrubber.md) - [Audiogram Bars](https://remotionui.com/docs/components/audiogram-bars.md) - [chat-bubble](https://remotionui.com/docs/components/chat-bubble.md) ## Machine-readable references - Props and usage as JSON: https://remotionui.com/ai/components/voice-note-bubble.json - Component index: https://remotionui.com/ai/components.json --- # VU Meter > Segmented level meter with peak hold. Install with npx remotion-ui@latest add vu-meter. Source: https://remotionui.com/docs/components/vu-meter ## Installation ```bash npx remotion-ui@latest add vu-meter ``` A segmented level meter with peak hold. ```tsx import { VuMeter } from "@/remotion/primitives/vu-meter"; <VuMeter src={audioSrc} orientation="vertical" labels={["L", "R"]} /> ``` ## Level, not spectrum `audiogram-bars` and `waveform-bars-radial` show *what* the frequencies are doing. This shows only how loud it is: the reading an engineer actually watches, and the one that still works at 40px wide in the corner of a frame. ## Peak hold At 30fps a transient that lights the top segment for one frame is invisible. The marker comes from the decaying peaks the audio library already tracks, so it is reconstructed from the waveform on every frame rather than held in component state: a render is stateless and may start on any frame, and a ref-held marker would differ between a preview scrub and a full render. `peakFallPerFrame` sets how fast the marker drops back. ## Two channels The second channel is weighted toward the upper half of the spectrum. It is not a real stereo split (the analysis is mono), but it is what stops a pair from looking like one meter drawn twice. Pass `channels={1}` when honesty matters more than the look. The top eighth of the scale takes `peakColor`, the third below it `warnColor`; a partly lit top segment reads as a level sitting between two steps rather than snapping down to the lower one. ## Usage ```tsx import { VuMeter } from "@/remotion/primitives/vu-meter"; <VuMeter src={audioSrc} orientation="vertical" labels={["L", "R"]} /> ``` Level rather than spectrum: the reading that still works at 40px wide. The peak marker is reconstructed from the library's decaying peaks on every frame instead of being held in state: a render is stateless and may start on any frame, so a ref-held marker would differ between a preview scrub and a full render. ## Props | Name | Type | Default | Description | | --- | --- | --- | --- | | `src` | `string` | `required` | Audio source. `.wav` only. | | `orientation` | `"vertical" \| "horizontal"` | `"vertical"` | Which way the segments stack. | | `segments` | `number` | `18` | Segments in one channel. | | `channels` | `1 \| 2` | `2` | Second channel is weighted toward the upper spectrum. | | `thickness` | `number` | `26` | Segment size across the short axis. | | `length` | `number` | `260` | Meter length along its own axis. | | `color` | `string` | `"#2dd4bf"` | Segments below the warm zone. | | `warnColor` | `string` | `"#e8b86d"` | Segments in the top third. | | `peakColor` | `string` | `"#f472b6"` | Segments in the top eighth. | | `showPeakHold` | `boolean` | `true` | Peak marker that falls back slowly. | | `peakFallPerFrame` | `number` | `0.018` | How fast the peak marker drops. | | `labels` | `[string, string]` | `undefined` | Channel captions, e.g. `["L", "R"]`. | | `sensitivity` | `number` | `1` | Lifts or lowers the reading before it hits the segments. | | `frame` | `number` | `undefined` | Frame override: pass the parent frame inside a `<Sequence>`. | ## Related - [Audiogram Bars](https://remotionui.com/docs/components/audiogram-bars.md) - [Audio Pulse](https://remotionui.com/docs/components/audio-pulse.md) - [Waveform Bars Radial](https://remotionui.com/docs/components/waveform-bars-radial.md) ## Machine-readable references - Props and usage as JSON: https://remotionui.com/ai/components/vu-meter.json - Component index: https://remotionui.com/ai/components.json --- # Waveform Bars Radial > Circular bars around a centre element. Install with npx remotion-ui@latest add waveform-bars-radial. Source: https://remotionui.com/docs/components/waveform-bars-radial ## Installation ```bash npx remotion-ui@latest add waveform-bars-radial ``` A spectrum wrapped into a circle, around whatever sits in the middle. ```tsx import { WaveformBarsRadial } from "@/remotion/primitives/waveform-bars-radial"; <WaveformBarsRadial src={audioSrc} radius={112} barCount={80}> <CoverArt /> </WaveformBarsRadial> ``` ## Where it sits Different geometry from `audiogram-bars`, which is a straight row. A ring frames a centre element instead of underlining it and reads at any aspect ratio, which is why it is the shape social audio clips use. ## Mirroring `mirror` reflects the spectrum across the vertical axis and is on by default. A ring that runs low-to-high all the way round puts every bit of energy on one side, so the shape wobbles rather than pulses. Mirroring also halves the number of distinct bands the ring needs, so the spectrum is not stretched across twice as many bars as it has resolution for. ## Motion at rest `spinPerSecond` turns the whole ring slowly. It matters more than it looks: through a quiet passage the bars barely move, and a still ring is exactly what the preview audit reports as a dead frame. `bidirectional` grows bars inward as well as outward, which suits a thin centre element. The source must be a `.wav` (`useWindowedAudioData` accepts nothing else), and while it loads the bars run on the library's deterministic idle envelope rather than sitting flat. ## Usage ```tsx import { WaveformBarsRadial } from "@/remotion/primitives/waveform-bars-radial"; <WaveformBarsRadial src={audioSrc} radius={112} barCount={80}> <CoverArt /> </WaveformBarsRadial> ``` Mirroring is on by default because a ring running low-to-high all the way round puts every bit of energy on one side, so it wobbles rather than pulses; it also halves the bands needed. The slow spin matters: through a quiet passage a still ring is exactly what the preview audit reports as dead. ## Props | Name | Type | Default | Description | | --- | --- | --- | --- | | `src` | `string` | `required` | Audio source. `.wav` only; `useWindowedAudioData` accepts nothing else. | | `children` | `ReactNode` | `undefined` | Content in the middle of the ring: artwork, a logo, a title. | | `radius` | `number` | `150` | Radius of the circle the bars stand on. | | `barCount` | `number` | `72` | Bars around the ring. | | `barWidth` | `number` | `5` | Bar thickness in px. | | `minLength` | `number` | `10` | Bar length at silence. | | `maxLength` | `number` | `90` | Bar length at full level. | | `peakColor` | `string` | `undefined` | Second colour for bars above 75% level. | | `mirror` | `boolean` | `true` | Reflect the spectrum across the vertical axis. | | `spinPerSecond` | `number` | `6` | Degrees the ring turns per second. 0 holds it still. | | `bidirectional` | `boolean` | `false` | Bars grow inward as well as outward. | | `frame` | `number` | `undefined` | Frame override: pass the parent frame inside a `<Sequence>`. | ## Related - [Audiogram Bars](https://remotionui.com/docs/components/audiogram-bars.md) - [Audio Pulse](https://remotionui.com/docs/components/audio-pulse.md) - [Waveform Line](https://remotionui.com/docs/components/waveform-line.md) ## Machine-readable references - Props and usage as JSON: https://remotionui.com/ai/components/waveform-bars-radial.json - Component index: https://remotionui.com/ai/components.json --- # Waveform Line > Audio waveform line visualization. Source: https://remotionui.com/docs/components/waveform-line ## Installation ```bash npx remotion-ui@latest add waveform-line ``` Mirrored amplitude envelope powered by `@remotion/media-utils`, with the played portion tinted. Pass `variant="line"` for the raw oscilloscope trace. ## Usage ```tsx import { WaveformLine } from "@/remotion/primitives/waveform-line"; <WaveformLine src={staticFile("voice.wav")} /> ``` Advanced. Installs @remotion/media-utils. ## Props | Name | Type | Default | Description | | --- | --- | --- | --- | | `src` (required) | `string` | - | Audio source. | | `width` | `number` | - | Drawing width. Defaults to the composition width; pass the slot width inside padding. | | `height` | `number` | `144` | SVG waveform height. | | `variant` | `"envelope" \| "line"` | `"envelope"` | Mirrored amplitude band, or the raw oscilloscope trace. | | `samples` | `number` | `88 / 128` | Envelope buckets (88) or trace samples (128). | | `windowInSeconds` | `number` | `1.2` | Audio window drawn around the current frame. | | `mirror` | `boolean` | `false` | Reflected copy of the trace. Ignored by the envelope variant, which is already mirrored. | | `progress` | `number` | - | Optional 0-1 played progress override. | | `amplitudeScale` | `number` | `0.94 / 0.48` | Vertical gain: envelope default 0.94, line default 0.48. | | `normalize` | `boolean` | `true` | Normalize the visible window for readable quiet audio. | | `showBaseline` | `boolean` | `true` | Render the center baseline. | ## Related - [Audiogram Bars](https://remotionui.com/docs/components/audiogram-bars.md) - [Audio Pulse](https://remotionui.com/docs/components/audio-pulse.md) ## Machine-readable references - Props and usage as JSON: https://remotionui.com/ai/components/waveform-line.json - Component index: https://remotionui.com/ai/components.json --- # Charts & metrics > Animated charts and live numbers that build from your data. Source: https://remotionui.com/docs/components/charts Charts take plain arrays of values and animate them into bars, lines, areas, and dials. Pass your own data and the layout, scales, and timing follow. ## Components - [Animated Bar Chart](https://remotionui.com/docs/components/animated-bar-chart.md): Ranked bar chart scene with a real value axis. - [Bar Chart Race](https://remotionui.com/docs/components/bar-chart-race.md): Ranked bars reorder over time. Install with npx remotion-ui@latest add bar-chart-race. - [Bubble Chart Pack](https://remotionui.com/docs/components/bubble-chart-pack.md): Circle-packed values settling into place. Install with npx remotion-ui@latest add bubble-chart-pack. - [Candlestick Chart](https://remotionui.com/docs/components/candlestick-chart.md): OHLC candles printing left to right with a moving average. Install with npx remotion-ui@latest add candlestick-chart. - [Comparison Bars](https://remotionui.com/docs/components/comparison-bars.md): Two-series before/after with delta callout. Install with npx remotion-ui@latest add comparison-bars. - [Donut Chart](https://remotionui.com/docs/components/donut-chart.md): Multi-segment donut with labels. Install with npx remotion-ui@latest add donut-chart. - [Funnel Chart](https://remotionui.com/docs/components/funnel-chart.md): Stage bars narrowing with drop-off percentages. Install with npx remotion-ui@latest add funnel-chart. - [Gantt Timeline](https://remotionui.com/docs/components/gantt-timeline.md): Task bars laid across a shared column grid. Install with npx remotion-ui@latest add gantt-timeline. - [Gauge Dial](https://remotionui.com/docs/components/gauge-dial.md): Needle sweeps to target. Install with npx remotion-ui@latest add gauge-dial. - [Heatmap Grid](https://remotionui.com/docs/components/heatmap-grid.md): Cell grid filling by intensity, contribution-graph style. Install with npx remotion-ui@latest add heatmap-grid. - [Line Chart Draw](https://remotionui.com/docs/components/line-chart-draw.md): SVG line chart that draws itself on. - [Metric Ticker](https://remotionui.com/docs/components/metric-ticker.md): KPI cards that count themselves in. - [Pie Slice Reveal](https://remotionui.com/docs/components/pie-slice-reveal.md): Slices sweep in sequentially. Install with npx remotion-ui@latest add pie-slice-reveal. - [Radar Chart](https://remotionui.com/docs/components/radar-chart.md): Multi-axis spider chart drawing its polygon. Install with npx remotion-ui@latest add radar-chart. - [Scatter Plot Pop](https://remotionui.com/docs/components/scatter-plot-pop.md): Points pop in on stagger, optional trend line. Install with npx remotion-ui@latest add scatter-plot-pop. - [Sparkline Row](https://remotionui.com/docs/components/sparkline-row.md): Compact trend lines that read at small sizes. Install with npx remotion-ui@latest add sparkline-row. - [Stacked Area Chart](https://remotionui.com/docs/components/stacked-area-chart.md): Bands stacked on a shared baseline, wiping in from the left. Install with npx remotion-ui@latest add stacked-area-chart. - [Treemap Blocks](https://remotionui.com/docs/components/treemap-blocks.md): Nested rectangles sized by value. Install with npx remotion-ui@latest add treemap-blocks. - [Waterfall Chart](https://remotionui.com/docs/components/waterfall-chart.md): Bridge chart carrying a running total through signed steps. Install with npx remotion-ui@latest add waterfall-chart. --- # Animated Bar Chart > Ranked bar chart scene with a real value axis. Source: https://remotionui.com/docs/components/animated-bar-chart ## Installation ```bash npx remotion-ui@latest add animated-bar-chart ``` Bars are measured against a rounded axis rather than the largest value, so the longest bar stops short of the frame edge and the ticks under it read as a scale. Each bar's length and its counter share one spring, and `highlightLabel` lifts the row you are actually talking about. ## Usage ```tsx import { AnimatedBarChart } from "@/remotion/scenes/animated-bar-chart"; <AnimatedBarChart title="Views by format" data={[{ label: "Shorts", value: 124000, delta: "+32%" }]} highlightLabel="Shorts" /> ``` Bars and their counters share one spring, so the number never leads the bar. ## Props | Name | Type | Default | Description | | --- | --- | --- | --- | | `data` (required) | `ChartDatum[]` | - | Bar labels and values. Optional `color` and `delta` per bar. | | `title` | `string` | - | Scene headline. | | `subtitle` | `string` | - | Supporting line under the title. | | `maxValue` | `number` | - | Fixed axis top. Defaults to a rounded domain above the largest bar. | | `valueFormatter` | `(value: number) => string` | `formatCompactNumber` | Formats the value on the end of each bar. | | `highlightLabel` | `string` | - | Label of the bar that carries accentColor. | | `showAxis` | `boolean` | `true` | Gridlines and the value axis under the bars. | | `maxBars` | `number` | `6` | Bars beyond this count are dropped rather than squeezed. | | `barColor` | `string` | `"#2dd4bf"` | Series colour. | | `accentColor` | `string` | `"#e8b86d"` | Colour for the highlighted bar. | ## Related - [Metric Ticker](https://remotionui.com/docs/components/metric-ticker.md) - [Line Chart Draw](https://remotionui.com/docs/components/line-chart-draw.md) - [Data Story](https://remotionui.com/docs/components/data-story.md) ## Machine-readable references - Props and usage as JSON: https://remotionui.com/ai/components/animated-bar-chart.json - Component index: https://remotionui.com/ai/components.json --- # Bar Chart Race > Ranked bars reorder over time. Install with npx remotion-ui@latest add bar-chart-race. Source: https://remotionui.com/docs/components/bar-chart-race ## Installation ```bash npx remotion-ui@latest add bar-chart-race ``` Ranked bars that overtake each other as the clock runs. ```tsx import { BarChartRace } from "@/remotion/primitives/bar-chart-race"; <BarChartRace series={[ { label: "Studio", values: [42, 58, 66, 72, 78, 84] }, { label: "Motion", values: [18, 34, 57, 76, 92, 108] }, ]} steps={["Q1", "Q2", "Q3", "Q4", "Q5", "Q6"]} framesPerStep={18} /> ``` ## Data shape Raw time series, one value per keyframe, interpolated at render, not pre-computed rankings. `framesPerStep` sets how long the clock takes to travel between two keyframes, so the whole race runs for `framesPerStep × (steps − 1)`. `steps` supplies the running caption. Every series should carry the same number of values. A short one holds its last value rather than dropping off the board. ## Why the overtakes look right Rank is fractional, not an integer sort position: each series measures how far above it every other series sits, softened by a sigmoid. An integer rank makes bars teleport a full row the instant two values cross, which is exactly the moment the format exists to show. The softening width scales with the leader's value, so a crossover reads the same whether the chart counts in tens or in millions. ## Where it sits `animated-bar-chart` is the static counterpart: one fixed ranking revealed with a value axis. Use that when the order never changes. `visibleRows` bounds the board; series ranked below it fade out instead of clipping, so dropping off reads as losing rather than as a render bug. ## Usage ```tsx import { BarChartRace } from "@/remotion/primitives/bar-chart-race"; <BarChartRace series={[ { label: "Studio", values: [42, 58, 66, 72, 78, 84] }, { label: "Motion", values: [18, 34, 57, 76, 92, 108] }, ]} steps={["Q1", "Q2", "Q3", "Q4", "Q5", "Q6"]} framesPerStep={18} /> ``` Rank is fractional, not an integer sort position: each series measures how far above it the others sit, softened by a sigmoid. Integer ranks make bars teleport a full row the instant two values cross, the exact moment the format exists to show. Takes raw time series and interpolates them, not pre-computed rankings. ## Props | Name | Type | Default | Description | | --- | --- | --- | --- | | `series` | `RaceSeries[]` | `required` | One entry per contender: `{ label, values, color? }`, one value per keyframe. | | `steps` | `string[]` | `undefined` | Keyframe captions, e.g. years. Shown as the running clock. | | `framesPerStep` | `number` | `26` | Frames spent travelling between two keyframes. | | `visibleRows` | `number` | `6` | How many rows stay on the board. Below that, series fade out. | | `width` | `number` | `900` | Overall width, label column included. | | `rowHeight` | `number` | `66` | Bar height. Type scales off it. | | `gap` | `number` | `14` | Space between rows. | | `labelWidth` | `number` | `200` | Width reserved for the row labels. | | `showStepLabel` | `boolean` | `true` | Large step caption in the bottom-right corner. | | `valueFormatter` | `(value: number) => string` | `compact` | Formats the figure inside each bar. | | `delayInFrames` | `number` | `0` | Frames to wait before the clock starts. | | `exitAtInFrames` | `number` | `undefined` | Frame the bars collapse on. Omit to hold the final standings. | | `frame` | `number` | `undefined` | Frame override: pass the parent frame inside a `<Sequence>`. | ## Related - [Animated Bar Chart](https://remotionui.com/docs/components/animated-bar-chart.md) - [leaderboard-rows](https://remotionui.com/docs/components/leaderboard-rows.md) - [Counter](https://remotionui.com/docs/components/counter.md) ## Machine-readable references - Props and usage as JSON: https://remotionui.com/ai/components/bar-chart-race.json - Component index: https://remotionui.com/ai/components.json --- # Bubble Chart Pack > Circle-packed values settling into place. Install with npx remotion-ui@latest add bubble-chart-pack. Source: https://remotionui.com/docs/components/bubble-chart-pack ## Installation ```bash npx remotion-ui@latest add bubble-chart-pack ``` Value bubbles packing themselves into a cluster, largest first. ```tsx import { BubbleChartPack } from "@/remotion/primitives/bubble-chart-pack"; <BubbleChartPack bubbles={[ { label: "Atoms", value: 42 }, { label: "Blocks", value: 31 }, { label: "Signals", value: 26 }, ]} staggerInFrames={12} /> ``` ## Area, not radius Radius scales with the square root of the value, so the area (which is what the eye actually compares) stays proportional to the number. Scaling radius directly makes a bubble worth twice another look four times as big. ## The pack is deterministic Circles are placed largest first, each walking out along a spiral from the origin until it clears everything already placed. It is not the densest possible pack, but the same data always produces the same arrangement. A layout that reshuffled between renders would make the chart untrustworthy, and density is worth less than that. The cluster is laid out in its own units and scaled once to fit `width` × `height`, so the same data fills the frame at any size. ## Motion Bubbles travel outward from the centre as they grow, so the cluster expands rather than assembling out of unrelated dots. With `exitAtInFrames` the smallest leave first and the cluster contracts back onto its heaviest value. Labels and values are hidden on bubbles too small to hold them, so a long tail of minor values stays clean. ## Usage ```tsx import { BubbleChartPack } from "@/remotion/primitives/bubble-chart-pack"; <BubbleChartPack bubbles={[ { label: "Atoms", value: 42 }, { label: "Blocks", value: 31 }, { label: "Signals", value: 26 }, ]} staggerInFrames={12} /> ``` Radius scales with the square root of the value, so area, what the eye compares, stays proportional. The pack is a deterministic spiral placement followed by a compaction pass toward the centre: the same data always produces the same arrangement, which is worth more here than density. ## Props | Name | Type | Default | Description | | --- | --- | --- | --- | | `bubbles` | `ChartDatum[]` | `required` | `{ label, value, color? }`. Area is proportional to value. | | `width` | `number` | `860` | Box the cluster is scaled to fit. | | `height` | `number` | `520` | Box height. | | `colors` | `string[]` | `gold / teal / pink / indigo / amber` | Fallback colours, cycled. | | `showLabels` | `boolean` | `true` | Labels inside bubbles large enough to hold them. | | `showValues` | `boolean` | `true` | Value line under the label, hidden on small bubbles. | | `padding` | `number` | `6` | Gap held between neighbours, in layout units. | | `durationInFrames` | `number` | `26` | Length of one bubble's settle. | | `staggerInFrames` | `number` | `7` | Frames between bubbles, largest first. | | `exitAtInFrames` | `number` | `undefined` | Frame the cluster contracts on. | | `frame` | `number` | `undefined` | Frame override: pass the parent frame inside a `<Sequence>`. | ## Related - [Scatter Plot Pop](https://remotionui.com/docs/components/scatter-plot-pop.md) - [Donut Chart](https://remotionui.com/docs/components/donut-chart.md) - [Treemap Blocks](https://remotionui.com/docs/components/treemap-blocks.md) ## Machine-readable references - Props and usage as JSON: https://remotionui.com/ai/components/bubble-chart-pack.json - Component index: https://remotionui.com/ai/components.json --- # Candlestick Chart > OHLC candles printing left to right with a moving average. Install with npx remotion-ui@latest add candlestick-chart. Source: https://remotionui.com/docs/components/candlestick-chart ## Installation ```bash npx remotion-ui@latest add candlestick-chart ``` A price tape: open-high-low-close candles printing in order, with an optional moving average running behind them. ```tsx import { CandlestickChart } from "@/remotion/primitives/candlestick-chart"; <CandlestickChart candles={[{ open: 101, high: 106, low: 99, close: 104, label: "W1" }]} movingAverage={6} staggerInFrames={3.4} /> ``` ## Candles grow from their open Each candle grows out of its own open price in both directions, not up from the axis. The open is where the period started, so it is the only anchor that leaves a half-drawn candle telling the truth. The wick runs slightly ahead of the body, which is how a real tape prints: the extremes are known before the period closes. A doji, where open equals close, still gets a minimum body height rather than disappearing. ## The average `movingAverage` is a simple mean over that many closes, plotted only where a full window exists, since a partial window would draw an average of fewer candles than the legend claims. The line trails the candles by a few frames instead of drawing after all of them, so it reads as a running calculation over what is already on screen. ## Scale The value axis is taken from the highs and lows and is *not* anchored at zero: price charts are read for range, and a zero baseline would flatten a day's movement into a hairline. `showLastPrice` pins the final close against the right edge in the colour of its own candle. ## Usage ```tsx import { CandlestickChart } from "@/remotion/primitives/candlestick-chart"; <CandlestickChart candles={[{ open: 101, high: 106, low: 99, close: 104, label: "W1" }]} movingAverage={6} staggerInFrames={3.4} /> ``` Candles grow out of their own open in both directions, so a half-drawn candle still tells the truth; the wick runs a little ahead of the body, as a real tape prints. The average is plotted only where a full window exists. The axis is not anchored at zero: price is read for range, and a zero baseline flattens the movement. ## Props | Name | Type | Default | Description | | --- | --- | --- | --- | | `candles` | `Candle[]` | `required` | `{ open, high, low, close, label? }`, oldest first. | | `width` | `number` | `900` | Drawing width. Type scales off it. | | `height` | `number` | `460` | Drawing height. | | `upColor` | `string` | `"#2dd4bf"` | Candles that closed at or above their open. | | `downColor` | `string` | `"#f472b6"` | Candles that closed below their open. | | `movingAverage` | `number` | `7` | Window for the simple moving average. 0 hides the line. | | `showLastPrice` | `boolean` | `true` | Final close pinned against the right edge. | | `showAxis` | `boolean` | `true` | Gridlines and price labels down the left gutter. | | `durationInFrames` | `number` | `12` | Length of one candle's growth. | | `staggerInFrames` | `number` | `3` | Frames between one candle and the next. | | `exitAtInFrames` | `number` | `undefined` | Frame the tape clears on, oldest first. | | `frame` | `number` | `undefined` | Frame override: pass the parent frame inside a `<Sequence>`. | ## Related - [Line Chart Draw](https://remotionui.com/docs/components/line-chart-draw.md) - [Sparkline Row](https://remotionui.com/docs/components/sparkline-row.md) - [Stacked Area Chart](https://remotionui.com/docs/components/stacked-area-chart.md) ## Machine-readable references - Props and usage as JSON: https://remotionui.com/ai/components/candlestick-chart.json - Component index: https://remotionui.com/ai/components.json --- # Comparison Bars > Two-series before/after with delta callout. Install with npx remotion-ui@latest add comparison-bars. Source: https://remotionui.com/docs/components/comparison-bars ## Installation ```bash npx remotion-ui@latest add comparison-bars ``` Before-and-after pairs, with the percentage change called out beside each one. ```tsx import { ComparisonBars } from "@/remotion/primitives/comparison-bars"; <ComparisonBars rows={[ { label: "Time to first cut", before: 240, after: 96 }, { label: "Renders / week", before: 120, after: 310 }, ]} seriesLabels={["Before", "After"]} staggerInFrames={18} /> ``` ## One scale for every row Both bars in every pair are measured against the largest value in the whole set. Scaling each row to itself is what makes a small category look like it beat a large one, since the pairs have to stay comparable to each other, not only internally. ## The pair reads as a change The second bar trails the first by `pairOffsetInFrames`. That short gap is what makes the two bars read as one movement rather than as neighbours that happen to be adjacent, and it is brief enough that both are still growing at once. The figure inside the coloured bar waits until the bar is wide enough to hold it, and the delta chip waits until the bar has stopped: it is the conclusion of the pair, so it cannot arrive first. ## Deltas `delta` is computed from `before` and `after` unless you pass your own string. A rise takes `afterColor`, a fall takes `downColor`; when a fall is the good outcome (render times, error counts), pass `delta` explicitly to say so. ## Usage ```tsx import { ComparisonBars } from "@/remotion/primitives/comparison-bars"; <ComparisonBars rows={[ { label: "Time to first cut", before: 240, after: 96 }, { label: "Renders / week", before: 120, after: 310 }, ]} seriesLabels={["Before", "After"]} staggerInFrames={18} /> ``` Every bar is measured against the largest value in the whole set, so pairs stay comparable to each other and not only internally. The second bar trails the first by a few frames, which is what makes a pair read as one change rather than two adjacent bars. ## Props | Name | Type | Default | Description | | --- | --- | --- | --- | | `rows` | `ComparisonRowDatum[]` | `required` | `{ label, before, after, delta? }`. The delta is computed when omitted. | | `width` | `number` | `820` | Overall width, label column included. | | `rowHeight` | `number` | `74` | Height of one pair, both bars and their gap included. | | `gap` | `number` | `26` | Space between rows. | | `labelWidth` | `number` | `190` | Width reserved for the row labels. | | `beforeColor` | `string` | `rgba(250,250,250,0.22)` | Baseline bar. Muted on purpose: it is the thing being beaten. | | `afterColor` | `string` | `"#e8b86d"` | New-value bar, and the colour of a rising delta. | | `downColor` | `string` | `"#f472b6"` | Delta colour when the change is a fall. | | `seriesLabels` | `[string, string]` | `undefined` | Legend above the rows, e.g. `["Before", "After"]`. | | `showDelta` | `boolean` | `true` | Percentage-change chip at the end of the second bar. | | `durationInFrames` | `number` | `30` | Length of one bar's growth. | | `staggerInFrames` | `number` | `12` | Frames between one row and the next. | | `pairOffsetInFrames` | `number` | `6` | Frames the second bar trails the first by. | | `exitAtInFrames` | `number` | `undefined` | Frame the rows start leaving on, in arrival order. | | `frame` | `number` | `undefined` | Frame override: pass the parent frame inside a `<Sequence>`. | ## Related - [Animated Bar Chart](https://remotionui.com/docs/components/animated-bar-chart.md) - [Stat Card](https://remotionui.com/docs/components/stat-card.md) - [Funnel Chart](https://remotionui.com/docs/components/funnel-chart.md) ## Machine-readable references - Props and usage as JSON: https://remotionui.com/ai/components/comparison-bars.json - Component index: https://remotionui.com/ai/components.json --- # Donut Chart > Multi-segment donut with labels. Install with npx remotion-ui@latest add donut-chart. Source: https://remotionui.com/docs/components/donut-chart ## Installation ```bash npx remotion-ui@latest add donut-chart ``` A composition breakdown whose slices sweep on one after another. ```tsx import { DonutChart } from "@/remotion/primitives/donut-chart"; <DonutChart segments={[ { label: "Direct", value: 4820 }, { label: "Search", value: 3140 }, { label: "Social", value: 1960 }, ]} totalLabel="Sessions" staggerInFrames={16} /> ``` ## Where it sits `stat-card` already owns the single-value ring, so this one is strictly multi-segment. For a filled circle rather than a ring, use `pie-slice-reveal`. ## The centre number `showTotal` counts the segments that have actually landed, not the grand total scaled by progress. The ring and the number therefore agree on every frame. A total that races ahead of the arcs is the usual tell of a chart animated in two unrelated places. ## Timing Each segment sweeps over `durationInFrames` and starts `staggerInFrames` after the one before, so the total run is `stagger × (segments − 1) + duration`. The legend rows fade in with their own slice. Pass `exitAtInFrames` to dismiss the chart: it fades and scales down rather than unwinding the sweep, since a ring that retracts reads as data being withdrawn. ## Usage ```tsx import { DonutChart } from "@/remotion/primitives/donut-chart"; <DonutChart segments={[ { label: "Direct", value: 4820 }, { label: "Search", value: 3140 }, { label: "Social", value: 1960 }, ]} totalLabel="Sessions" staggerInFrames={16} /> ``` The centre total counts the segments that have actually landed, so ring and number agree on every frame. Each segment is a dashed circle rotated to its own start angle, which keeps every arc on one radius. `stat-card` owns the single-value ring; this one is strictly multi-segment. ## Props | Name | Type | Default | Description | | --- | --- | --- | --- | | `segments` | `ChartDatum[]` | `required` | `{ label, value, color? }`, drawn clockwise in the order given. | | `size` | `number` | `360` | Outer diameter in px. All type scales off it. | | `thickness` | `number` | `46` | Ring thickness. Below a tenth of `size` it reads as a hairline. | | `colors` | `string[]` | `gold / teal / pink / indigo` | Fallback colours, cycled for segments with no `color`. | | `showLegend` | `boolean` | `true` | Legend rows beside the ring, arriving with their own slice. | | `showTotal` | `boolean` | `true` | Running total in the hole. | | `totalLabel` | `string` | `"Total"` | Caption under the total. | | `valueFormatter` | `(value: number) => string` | `compact` | Formats the centre total. | | `durationInFrames` | `number` | `26` | Length of one segment's sweep. | | `staggerInFrames` | `number` | `9` | Frames between one segment and the next. | | `exitAtInFrames` | `number` | `undefined` | Frame the chart is dismissed on. | | `frame` | `number` | `undefined` | Frame override: pass the parent frame inside a `<Sequence>`. | ## Related - [Pie Slice Reveal](https://remotionui.com/docs/components/pie-slice-reveal.md) - [Stat Card](https://remotionui.com/docs/components/stat-card.md) - [Progress Bar](https://remotionui.com/docs/components/progress-bar.md) ## Machine-readable references - Props and usage as JSON: https://remotionui.com/ai/components/donut-chart.json - Component index: https://remotionui.com/ai/components.json --- # Funnel Chart > Stage bars narrowing with drop-off percentages. Install with npx remotion-ui@latest add funnel-chart. Source: https://remotionui.com/docs/components/funnel-chart ## Installation ```bash npx remotion-ui@latest add funnel-chart ``` Stage bands narrowing toward the bottom, with the loss between each pair printed alongside. ```tsx import { FunnelChart } from "@/remotion/primitives/funnel-chart"; <FunnelChart stages={[ { label: "Visited docs", value: 42800 }, { label: "Ran the CLI", value: 18600 }, { label: "Shipped it", value: 1750 }, ]} staggerInFrames={15} /> ``` ## The taper is the number Each band runs from its own width down to the *next* stage's width, so the shape carries the drop before anyone reads a label. The last band is a rectangle: there is no next stage to taper to, and inventing one would overstate the final step. ## Why the labels sit outside Names and values live in a left gutter, not inside the bands. A real funnel ends narrow, and type set inside the last band would either overflow it or shrink until it was unreadable, which is usually where the interesting number is. `labelWidth` sizes that gutter; drop-off chips get their own on the right. ## Timing Bands wipe downward in order. Each drop-off chip waits for the band *below* it, because the chip is a claim about two stages and cannot land before both exist. With `exitAtInFrames` the funnel drains bottom-up, narrow end first. ## Usage ```tsx import { FunnelChart } from "@/remotion/primitives/funnel-chart"; <FunnelChart stages={[ { label: "Visited docs", value: 42800 }, { label: "Ran the CLI", value: 18600 }, { label: "Shipped it", value: 1750 }, ]} staggerInFrames={15} /> ``` Each band tapers from its own width to the next stage's, so the shape carries the loss before a label is read; the last band is a rectangle because there is no next stage to taper to. Names and values sit in a left gutter: a real funnel ends narrow, and type inside the last band would have to shrink until it was unreadable. ## Props | Name | Type | Default | Description | | --- | --- | --- | --- | | `stages` | `FunnelStage[]` | `required` | `{ label, value, color? }`, top to bottom. | | `width` | `number` | `820` | Overall width: label gutter, funnel and drop-off gutter. | | `height` | `number` | `420` | Overall height. Bands split it evenly. | | `gap` | `number` | `10` | Space between bands. | | `tailOpacity` | `number` | `0.5` | Opacity of the last band; earlier bands ramp toward 1. | | `labelWidth` | `number` | `30% of width` | Left gutter holding stage names and values. | | `showDropoff` | `boolean` | `true` | Drop-off chip between consecutive stages. | | `showConversion` | `boolean` | `false` | Share of the first stage, printed beside each value. | | `durationInFrames` | `number` | `22` | Length of one band's wipe. | | `staggerInFrames` | `number` | `12` | Frames between one band and the next. | | `exitAtInFrames` | `number` | `undefined` | Frame the funnel drains on, narrow end first. | | `frame` | `number` | `undefined` | Frame override: pass the parent frame inside a `<Sequence>`. | ## Related - [Comparison Bars](https://remotionui.com/docs/components/comparison-bars.md) - [Animated Bar Chart](https://remotionui.com/docs/components/animated-bar-chart.md) - [Stat Card](https://remotionui.com/docs/components/stat-card.md) ## Machine-readable references - Props and usage as JSON: https://remotionui.com/ai/components/funnel-chart.json - Component index: https://remotionui.com/ai/components.json --- # Gantt Timeline > Task bars laid across a shared column grid. Install with npx remotion-ui@latest add gantt-timeline. Source: https://remotionui.com/docs/components/gantt-timeline ## Installation ```bash npx remotion-ui@latest add gantt-timeline ``` A schedule: task bars wiping out across a shared column grid. ```tsx import { GanttTimeline } from "@/remotion/primitives/gantt-timeline"; <GanttTimeline tasks={[ { label: "Registry build", start: 1, end: 4, progress: 0.8 }, { label: "Launch", start: 7.6, end: 7.6, milestone: true }, ]} columns={["W1", "W2", "W3", "W4", "W5", "W6", "W7", "W8"]} markerAt={5.5} markerLabel="Today" /> ``` ## Column units, not pixels `start` and `end` are positions on the column grid, so a task moves by editing one number and every rule, bar and marker stays in register. Fractional values are fine: `7.6` lands six tenths into the eighth column. ## Bars wipe from their own start Never from the left margin. The animation then says *when* a task begins as well as how long it runs. Rows stagger downward, which is the order a schedule is read. `progress` draws a solid fill inside a dimmed bar, and it fills only after the bar has finished wiping so the two readings never compete. `milestone` ignores `end` and drops a diamond at `start`. ## The marker `markerAt` draws a dashed rule at any column position. Its label sits on a filled chip, because the rule can land anywhere, including straight through a column heading. ## Usage ```tsx import { GanttTimeline } from "@/remotion/primitives/gantt-timeline"; <GanttTimeline tasks={[ { label: "Registry build", start: 1, end: 4, progress: 0.8 }, { label: "Launch", start: 7.6, end: 7.6, milestone: true }, ]} columns={["W1", "W2", "W3", "W4", "W5", "W6", "W7", "W8"]} markerAt={5.5} markerLabel="Today" /> ``` Positions are column units rather than pixels, so a task moves by editing one number and everything stays in register. Bars wipe out from their own start edge, never from the left margin, so the animation says when a task begins as well as how long it runs. The marker label sits on a filled chip because the rule can land through a column heading. ## Props | Name | Type | Default | Description | | --- | --- | --- | --- | | `tasks` | `GanttTask[]` | `required` | `{ label, start, end, progress?, color?, milestone? }` in column units. | | `columns` | `string[]` | `required` | Column headings. Their count sets the span of the timeline. | | `width` | `number` | `900` | Overall width, label column included. | | `rowHeight` | `number` | `48` | Height of one task row. Type scales off it. | | `gap` | `number` | `12` | Space between rows. | | `labelWidth` | `number` | `240` | Width reserved for the task names. | | `markerAt` | `number` | `undefined` | Column position for a dashed vertical rule, e.g. today. | | `markerLabel` | `string` | `undefined` | Chip label on that rule. | | `durationInFrames` | `number` | `24` | Length of one bar's wipe. | | `staggerInFrames` | `number` | `8` | Frames between one row and the next. | | `exitAtInFrames` | `number` | `undefined` | Frame the rows start leaving on, top-down. | | `frame` | `number` | `undefined` | Frame override: pass the parent frame inside a `<Sequence>`. | ## Related - [Roadmap Lanes](https://remotionui.com/docs/components/roadmap-lanes.md) - [Kanban Move](https://remotionui.com/docs/components/kanban-move.md) - [Changelog Entry](https://remotionui.com/docs/components/changelog-entry.md) ## Machine-readable references - Props and usage as JSON: https://remotionui.com/ai/components/gantt-timeline.json - Component index: https://remotionui.com/ai/components.json --- # Gauge Dial > Needle sweeps to target. Install with npx remotion-ui@latest add gauge-dial. Source: https://remotionui.com/docs/components/gauge-dial ## Installation ```bash npx remotion-ui@latest add gauge-dial ``` An instrument dial: arc fill, tick marks, and a needle that sweeps to its target. ```tsx import { GaugeDial } from "@/remotion/primitives/gauge-dial"; <GaugeDial value={78} label="Render budget" unit="%" durationInFrames={70} /> ``` ## Two curves on purpose The needle rides the overshoot curve and the arc does not. A needle that swings past and settles back is what a real instrument does; a coloured arc that retreats reads as the value itself changing its mind. The readout counts from the arc's progress, so the number never disagrees with the fill. ## Shape `sweepInDegrees` is the total travel, centred on twelve o'clock: 250° is the default car-dashboard look, 180° gives a half-moon meter. `thickness` covers both the track and the fill; ticks are inset from it so the needle can cross them without colliding. Ticks the needle has passed sit brighter than the ones ahead, which keeps the reading legible where the needle covers the arc. ## Exit `exitAtInFrames` unwinds the dial back to rest as it fades, like an instrument powering down rather than a panel dissolving in place. ## Usage ```tsx import { GaugeDial } from "@/remotion/primitives/gauge-dial"; <GaugeDial value={78} label="Render budget" unit="%" durationInFrames={70} /> ``` The needle rides the overshoot curve and the arc does not: a needle that settles back is instrument-like, while a coloured arc that retreats reads as the value changing its mind. The readout counts from the arc's progress, so number and fill never disagree. ## Props | Name | Type | Default | Description | | --- | --- | --- | --- | | `value` | `number` | `required` | Target the needle sweeps to. | | `min` | `number` | `0` | Value at the start of the arc. | | `max` | `number` | `100` | Value at the end of the arc. | | `size` | `number` | `360` | Outer diameter in px. Type scales off it. | | `thickness` | `number` | `26` | Track and fill thickness. | | `sweepInDegrees` | `number` | `250` | Total travel, centred on twelve o'clock. 180 gives a half-moon meter. | | `label` | `string` | `undefined` | Caption under the readout. | | `unit` | `string` | `""` | Suffix on the readout, e.g. `"%"`. | | `tickCount` | `number` | `9` | Tick marks around the arc. 0 hides them. | | `valueFormatter` | `(value: number) => string` | `rounded` | Formats the readout. | | `durationInFrames` | `number` | `44` | Length of the sweep. | | `delayInFrames` | `number` | `0` | Frames to wait before the sweep starts. | | `exitAtInFrames` | `number` | `undefined` | Frame the dial unwinds on. | | `frame` | `number` | `undefined` | Frame override: pass the parent frame inside a `<Sequence>`. | ## Related - [Progress Bar](https://remotionui.com/docs/components/progress-bar.md) - [Stat Card](https://remotionui.com/docs/components/stat-card.md) - [Counter](https://remotionui.com/docs/components/counter.md) ## Machine-readable references - Props and usage as JSON: https://remotionui.com/ai/components/gauge-dial.json - Component index: https://remotionui.com/ai/components.json --- # Heatmap Grid > Cell grid filling by intensity, contribution-graph style. Install with npx remotion-ui@latest add heatmap-grid. Source: https://remotionui.com/docs/components/heatmap-grid ## Installation ```bash npx remotion-ui@latest add heatmap-grid ``` A contribution graph that fills in on a diagonal wave. ```tsx import { HeatmapGrid } from "@/remotion/primitives/heatmap-grid"; <HeatmapGrid cells={weeks} rowLabels={["Mon", "", "Wed", "", "Fri", "", "Sun"]} columnStaggerInFrames={3.4} rowStaggerInFrames={1.6} /> ``` `cells` is row-major. Ragged rows are padded with empty cells, so a partial final week needs no placeholder values. ## The wave Cells are staggered by `column × columnStaggerInFrames + row × rowStaggerInFrames`. Keep the row stagger smaller than the column stagger and the fill sweeps as a diagonal front. Staggering by flat index instead makes the fill snake back to the left edge on every new row, which reads as a glitch. The exit drains along the same diagonal. ## Reading intensity Intensity drives colour *and* a small scale step. Colour alone is hard to judge at cell size on a dark stage; the size difference is what lets a busy column register in peripheral vision. Empty cells stay at `emptyColor` and never scale up, so a quiet week stays quiet. `maxValue` pins the top of the ramp. Leave it unset and the busiest cell present defines it. Set it explicitly when several grids need to be compared. ## Usage ```tsx import { HeatmapGrid } from "@/remotion/primitives/heatmap-grid"; <HeatmapGrid cells={weeks} rowLabels={["Mon", "", "Wed", "", "Fri", "", "Sun"]} columnStaggerInFrames={3.4} /> ``` Staggering by column plus row makes the fill sweep as a diagonal front; a flat index stagger snakes back to the left edge on every new row and reads as a glitch. Intensity drives colour and a small scale step together, since colour alone is hard to judge at cell size on a dark stage. ## Props | Name | Type | Default | Description | | --- | --- | --- | --- | | `cells` | `number[][]` | `required` | Row-major intensities. Ragged rows are padded with empty cells. | | `maxValue` | `number` | `busiest cell` | Top of the ramp. Set it explicitly to compare two grids. | | `cellSize` | `number` | `34` | Cell edge length in px. | | `gap` | `number` | `8` | Space between cells. | | `color` | `string` | `"#e8b86d"` | Colour at full intensity. | | `emptyColor` | `string` | `rgba(250,250,250,0.07)` | Colour of a zero cell. | | `rowLabels` | `string[]` | `undefined` | Labels down the left gutter, one per row. | | `columnLabels` | `string[]` | `undefined` | Labels along the top. Sparse arrays are fine. | | `showLegend` | `boolean` | `true` | "Less → more" ramp under the grid. | | `durationInFrames` | `number` | `14` | Length of one cell's fill. | | `columnStaggerInFrames` | `number` | `3` | Frames added per column as the wave crosses. | | `rowStaggerInFrames` | `number` | `1.5` | Frames added per row. Keep it below the column stagger. | | `exitAtInFrames` | `number` | `undefined` | Frame the grid drains on, along the same diagonal. | | `frame` | `number` | `undefined` | Frame override: pass the parent frame inside a `<Sequence>`. | ## Related - [Commit Graph](https://remotionui.com/docs/components/commit-graph.md) - [Beat Pulse Grid](https://remotionui.com/docs/components/beat-pulse-grid.md) - [Treemap Blocks](https://remotionui.com/docs/components/treemap-blocks.md) ## Machine-readable references - Props and usage as JSON: https://remotionui.com/ai/components/heatmap-grid.json - Component index: https://remotionui.com/ai/components.json --- # Line Chart Draw > SVG line chart that draws itself on. Source: https://remotionui.com/docs/components/line-chart-draw ## Installation ```bash npx remotion-ui@latest add line-chart-draw ``` A line chart on a rounded value axis, drawn on by a single progress value: the stroke evolves along its own length, the gradient fill is wiped in behind it, and each dot lands as the tip passes. Curves are a clamped cardinal spline, so the line never overshoots past a value that is not in the data. Set `showAxis={false}` and `includeZero={false}` for a sparkline. ## Usage ```tsx import { LineChartDraw } from "@/remotion/primitives/line-chart-draw"; <LineChartDraw points={[ { x: 0, y: 12000, label: "Jan" }, { x: 1, y: 24000, label: "Feb" }, ]} /> ``` Advanced. Installs @remotion/paths. ## Props | Name | Type | Default | Description | | --- | --- | --- | --- | | `points` (required) | `ChartPoint[]` | - | Chart points. `label` supplies the x-axis tick. | | `width` | `number` | - | Drawing width. Defaults to the composition width; pass the slot width inside padding. | | `height` | `number` | - | Drawing height. Defaults to 40% of the composition height. | | `color` | `string` | `"#e8b86d"` | Line, area and dot colour. | | `strokeWidth` | `number` | - | Line weight. Scales with the chart width by default. | | `variant` | `"smooth" \| "linear"` | `"smooth"` | Clamped cardinal spline, or straight segments. | | `showAxis` | `boolean` | `true` | Gridlines and value labels on rounded ticks. | | `showXLabels` | `boolean` | `true` | Category labels under the plot. | | `showArea` | `boolean` | `true` | Gradient fill, wiped in with the draw. | | `showDots` | `boolean` | `true` | Dot deposited on each point as the line passes it. | | `showHead` | `boolean` | `true` | Glowing dot riding the tip while the line draws. | | `showEndLabel` | `boolean` | `false` | Value callout on the final point. | | `includeZero` | `boolean` | `true` | Anchor the axis at zero. Turn off for sparklines. | | `valueFormatter` | `(value: number) => string` | - | Formats axis ticks and the end label. | | `durationInFrames` | `number` | `70` | Draw-on duration. | | `delayInFrames` | `number` | `0` | Delay before the draw starts. | | `frame` | `number` | - | Frame override: pass the parent frame inside a Sequence. | ## Related - [Animated Bar Chart](https://remotionui.com/docs/components/animated-bar-chart.md) - [Metric Ticker](https://remotionui.com/docs/components/metric-ticker.md) - [Path Draw](https://remotionui.com/docs/components/path-draw.md) ## Machine-readable references - Props and usage as JSON: https://remotionui.com/ai/components/line-chart-draw.json - Component index: https://remotionui.com/ai/components.json --- # Metric Ticker > KPI cards that count themselves in. Source: https://remotionui.com/docs/components/metric-ticker ## Installation ```bash npx remotion-ui@latest add metric-ticker ``` Cards divide the full content width so the row reads as one panel. Values count up on the card's own spring; a signed `delta` picks the arrow, the chip colour and the tint of the `trend` sparkline underneath, which is drawn by [line-chart-draw](https://remotionui.com/docs/components/line-chart-draw.md). ## Usage ```tsx import { MetricTicker } from "@/remotion/scenes/metric-ticker"; <MetricTicker title="Channel momentum" metrics={[ { label: "Views", value: 124000, delta: "+18%", trend: [62, 84, 96, 124] }, ]} /> ``` A signed delta (+/-) picks the arrow, the chip colour, and the sparkline tint. ## Props | Name | Type | Default | Description | | --- | --- | --- | --- | | `metrics` (required) | `MetricTickerItem[]` | - | Metric cards: label, value, and optional from, prefix, suffix, delta, trend, color. Set from above value for a metric that counts down. | | `title` | `string` | - | Scene title. | | `eyebrow` | `string` | - | Short label above the title. | | `valueFormatter` | `(value: number) => string` | `formatCompactNumber` | Formats the counted value. | | `maxCards` | `number` | `4` | Cards beyond this count are dropped rather than squeezed. | | `accentColor` | `string` | `"#e8b86d"` | Value colour, overridable per metric. | | `backgroundColor` | `string` | `"#080810"` | Scene background. | ## Related - [Animated Bar Chart](https://remotionui.com/docs/components/animated-bar-chart.md) - [Line Chart Draw](https://remotionui.com/docs/components/line-chart-draw.md) - [Data Story](https://remotionui.com/docs/components/data-story.md) ## Machine-readable references - Props and usage as JSON: https://remotionui.com/ai/components/metric-ticker.json - Component index: https://remotionui.com/ai/components.json --- # Pie Slice Reveal > Slices sweep in sequentially. Install with npx remotion-ui@latest add pie-slice-reveal. Source: https://remotionui.com/docs/components/pie-slice-reveal ## Installation ```bash npx remotion-ui@latest add pie-slice-reveal ``` A filled pie whose wedges open clockwise from twelve o'clock, one at a time. ```tsx import { PieSliceReveal } from "@/remotion/primitives/pie-slice-reveal"; <PieSliceReveal slices={[ { label: "Pro", value: 44 }, { label: "Team", value: 26 }, { label: "Free", value: 18 }, ]} staggerInFrames={18} /> ``` ## Where it sits Solid wedges, so the whole is the point. When the comparison matters more than the total, `donut-chart` frees the centre for a headline number. ## Slice separation `gapInDegrees` is taken off the end of each wedge rather than drawn as a stroke between them. A stroked divider sits on top of whichever slice was painted last and nicks the outer edge of the circle. `explode` pushes every wedge out along its own bisector. Because the bisector is still moving while a slice opens, the wedge slides outward as it sweeps. The pie is drawn slightly smaller than its box to leave room for that offset. ## Labels Percentages appear at 70% of a slice's sweep, so a label never sits on a wedge too narrow to hold it. `labelColor` defaults to near-black, since the slice colours are light enough that dark type is the readable choice on all of them. ## Usage ```tsx import { PieSliceReveal } from "@/remotion/primitives/pie-slice-reveal"; <PieSliceReveal slices={[ { label: "Pro", value: 44 }, { label: "Team", value: 26 }, { label: "Free", value: 18 }, ]} staggerInFrames={18} /> ``` The gap is cut out of the wedge rather than stroked between wedges: a stroked divider sits on top of whichever slice was painted last and nicks the outer edge of the circle. Solid wedges, so the whole is the point; use `donut-chart` when the centre should carry a number. ## Props | Name | Type | Default | Description | | --- | --- | --- | --- | | `slices` | `ChartDatum[]` | `required` | `{ label, value, color? }`, swept clockwise from twelve o'clock. | | `size` | `number` | `380` | Diameter in px, offset for the explode included. | | `colors` | `string[]` | `gold / teal / pink / indigo / amber` | Fallback colours, cycled. | | `showLabels` | `boolean` | `true` | Percentages inside each slice, from 70% of its sweep. | | `explode` | `number` | `0.04` | How far each slice sits off centre, as a share of the radius. | | `gapInDegrees` | `number` | `1.4` | Angular gap, taken off the end of each wedge. | | `durationInFrames` | `number` | `24` | Length of one slice's sweep. | | `staggerInFrames` | `number` | `14` | Frames between one slice and the next. | | `exitAtInFrames` | `number` | `undefined` | Frame the slices fan out on. | | `frame` | `number` | `undefined` | Frame override: pass the parent frame inside a `<Sequence>`. | ## Related - [Donut Chart](https://remotionui.com/docs/components/donut-chart.md) - [Stat Card](https://remotionui.com/docs/components/stat-card.md) - [Comparison Bars](https://remotionui.com/docs/components/comparison-bars.md) ## Machine-readable references - Props and usage as JSON: https://remotionui.com/ai/components/pie-slice-reveal.json - Component index: https://remotionui.com/ai/components.json --- # Radar Chart > Multi-axis spider chart drawing its polygon. Install with npx remotion-ui@latest add radar-chart. Source: https://remotionui.com/docs/components/radar-chart ## Installation ```bash npx remotion-ui@latest add radar-chart ``` A spider chart whose polygon reaches out one axis at a time. ```tsx import { RadarChart } from "@/remotion/primitives/radar-chart"; <RadarChart axes={["Speed", "Polish", "Reuse", "Docs", "Types", "Motion"]} series={[ { label: "Before", values: [42, 38, 24, 30, 46, 34] }, { label: "After", values: [88, 92, 84, 78, 90, 86] }, ]} maxValue={100} /> ``` ## Axis by axis, not scale-up Vertices are staggered clockwise rather than the whole polygon scaling from the centre. A polygon that grows says nothing about which axis is strong; reaching axis by axis assembles the shape in the order the labels are read, and the silhouette only resolves when the last vertex lands. Several series stagger against each other by `seriesOffsetInFrames`, so a comparison arrives as two statements rather than one tangle. ## The web arrives whole Rings and spokes fade in together, ahead of the data. They are the measuring instrument, not part of the reading. Animating them would suggest the scale itself was changing. ## Sizing The SVG box is the web plus a margin computed from the longest axis label, so long names are not clipped and short ones do not waste space. `maxValue` pins the outer ring; leave it unset and the largest value present defines it, which is rarely what you want when two charts sit side by side. ## Usage ```tsx import { RadarChart } from "@/remotion/primitives/radar-chart"; <RadarChart axes={["Speed", "Polish", "Reuse", "Docs", "Types", "Motion"]} series={[ { label: "Before", values: [42, 38, 24, 30, 46, 34] }, { label: "After", values: [88, 92, 84, 78, 90, 86] }, ]} maxValue={100} /> ``` Vertices reach out one axis at a time rather than the polygon scaling as a whole: a growing polygon says nothing about which axis is strong. The web arrives whole and ahead of the data: it is the instrument, and animating it would suggest the scale was changing. The box grows with the longest axis label so nothing clips. ## Props | Name | Type | Default | Description | | --- | --- | --- | --- | | `axes` | `string[]` | `required` | Axis names, clockwise from the top. Three minimum. | | `series` | `RadarSeries[]` | `required` | `{ label, values, color? }`, one value per axis in axis order. | | `size` | `number` | `420` | Diameter of the web. Labels sit outside it. | | `maxValue` | `number` | `largest value` | Value at the outer ring. Pin it when comparing two charts. | | `ringCount` | `number` | `4` | Concentric rings behind the polygons. | | `showLabels` | `boolean` | `true` | Axis names around the web. | | `showVertices` | `boolean` | `true` | Dot on each vertex. | | `fillOpacity` | `number` | `0.22` | Fill under each polygon. | | `durationInFrames` | `number` | `18` | Length of one vertex's reach. | | `staggerInFrames` | `number` | `5` | Frames between axes, sweeping clockwise. | | `seriesOffsetInFrames` | `number` | `10` | Frames one series trails the previous one by. | | `exitAtInFrames` | `number` | `undefined` | Frame the polygons collapse to the centre on. | | `frame` | `number` | `undefined` | Frame override: pass the parent frame inside a `<Sequence>`. | ## Related - [Line Chart Draw](https://remotionui.com/docs/components/line-chart-draw.md) - [Comparison Bars](https://remotionui.com/docs/components/comparison-bars.md) - [Scatter Plot Pop](https://remotionui.com/docs/components/scatter-plot-pop.md) ## Machine-readable references - Props and usage as JSON: https://remotionui.com/ai/components/radar-chart.json - Component index: https://remotionui.com/ai/components.json --- # Scatter Plot Pop > Points pop in on stagger, optional trend line. Install with npx remotion-ui@latest add scatter-plot-pop. Source: https://remotionui.com/docs/components/scatter-plot-pop ## Installation ```bash npx remotion-ui@latest add scatter-plot-pop ``` A correlation cloud that fills left to right, with a least-squares trend line that lands after the last point. ```tsx import { ScatterPlotPop } from "@/remotion/primitives/scatter-plot-pop"; <ScatterPlotPop points={[{ x: 4, y: 24, weight: 0.8 }, { x: 11, y: 39 }]} xLabel="Scenes per project" staggerInFrames={3} /> ``` ## Order of arrival The stagger follows ascending `x`, not array order, so the cloud fills the way the axis is read no matter how the data arrived. Points leave in the same order. The trend line waits for the last point. Drawn earlier it would assert a correlation over data the viewer has not been shown yet. ## Fitting The fit is least squares over the raw values and only then projected to the screen. Fitting in screen space inverts the slope, since y grows downward there. `showTrend={false}` drops it for data with no meaningful relationship. ## Weight `weight` scales a dot between `minRadius` and `maxRadius` and defaults to 1. Omit it on every point and the cloud is uniform. Each dot carries a soft halo at about twice its radius, which keeps overlapping points readable without an explicit stroke. ## Usage ```tsx import { ScatterPlotPop } from "@/remotion/primitives/scatter-plot-pop"; <ScatterPlotPop points={[{ x: 4, y: 24, weight: 0.8 }, { x: 11, y: 39 }]} xLabel="Scenes per project" staggerInFrames={3} /> ``` The stagger follows ascending x, not array order, so the cloud fills the way the axis is read. The fit is least squares over the raw values and only then projected: fitting in screen space inverts the slope, since y grows downward there. ## Props | Name | Type | Default | Description | | --- | --- | --- | --- | | `points` | `ScatterPoint[]` | `required` | `{ x, y, weight?, color? }` in data units. | | `width` | `number` | `860` | Drawing width. Type scales off it. | | `height` | `number` | `480` | Drawing height. | | `minRadius` | `number` | `7` | Dot radius at weight 0. | | `maxRadius` | `number` | `20` | Dot radius at the heaviest weight present. | | `showTrend` | `boolean` | `true` | Least-squares trend line, drawn after the last dot lands. | | `showAxis` | `boolean` | `true` | Gridlines and value labels on both axes. | | `xLabel` | `string` | `undefined` | Caption under the x axis. | | `yLabel` | `string` | `undefined` | Rotated caption beside the y axis. | | `durationInFrames` | `number` | `16` | Length of one dot's pop. | | `staggerInFrames` | `number` | `2.5` | Frames between dots, in ascending x order. | | `exitAtInFrames` | `number` | `undefined` | Frame the cloud drains on. | | `frame` | `number` | `undefined` | Frame override: pass the parent frame inside a `<Sequence>`. | ## Related - [Line Chart Draw](https://remotionui.com/docs/components/line-chart-draw.md) - [Bubble Chart Pack](https://remotionui.com/docs/components/bubble-chart-pack.md) - [Sparkline Row](https://remotionui.com/docs/components/sparkline-row.md) ## Machine-readable references - Props and usage as JSON: https://remotionui.com/ai/components/scatter-plot-pop.json - Component index: https://remotionui.com/ai/components.json --- # Sparkline Row > Compact trend lines that read at small sizes. Install with npx remotion-ui@latest add sparkline-row. Source: https://remotionui.com/docs/components/sparkline-row ## Installation ```bash npx remotion-ui@latest add sparkline-row ``` A metrics stack: label, a small trend line that draws itself on, the current figure, and a signed delta. ```tsx import { SparklineRow } from "@/remotion/primitives/sparkline-row"; <SparklineRow rows={[ { label: "Renders / day", values: [180, 240, 210, 320, 480, 610], delta: "+24%" }, { label: "Median render", values: [92, 84, 86, 74, 66, 61], delta: "-18%" }, ]} staggerInFrames={20} /> ``` ## Every row scales to itself A sparkline is read for shape, not level. Rows are normalised individually, so a metric that moves between 4 and 6 keeps its shape next to one in the thousands. A shared axis would flatten it into a straight line. ## Layout Only the spark is SVG. Label, value and delta are CSS, so the row can carry tabular figures and a coloured delta without fighting SVG text metrics. `width` divides between the label (flexible), `sparkWidth` (fixed) and the value column. `delta` colours itself from its sign: `+` reads as up, `-` or `−` as down, anything else stays neutral. The delta waits for the line to finish drawing: it is the conclusion of the row, not its opening. ## Timing Rows draw in order, `staggerInFrames` apart, and leave in the same order when `exitAtInFrames` is set, so the stack empties top-down instead of blinking out as one block. ## Usage ```tsx import { SparklineRow } from "@/remotion/primitives/sparkline-row"; <SparklineRow rows={[ { label: "Renders / day", values: [180, 240, 320, 480, 610], delta: "+24%" }, { label: "Median render", values: [92, 86, 74, 66, 61], delta: "-18%" }, ]} staggerInFrames={20} /> ``` Every row scales to its own domain: a sparkline is read for shape, and a shared axis would flatten a metric that moves between 4 and 6 next to one in the thousands. Only the spark is SVG; label, value and delta are CSS, so the row keeps tabular figures without fighting SVG text metrics. ## Props | Name | Type | Default | Description | | --- | --- | --- | --- | | `rows` | `SparklineSeries[]` | `required` | `{ label, values, value?, delta?, color? }`, oldest value first. | | `width` | `number` | `720` | Overall width of the stack. | | `rowHeight` | `number` | `96` | Height of one row. Type scales off it. | | `sparkWidth` | `number` | `260` | Width of the spark itself. | | `upColor` | `string` | `"#2dd4bf"` | Colour for a `+` delta. | | `downColor` | `string` | `"#f472b6"` | Colour for a `-` delta. | | `showArea` | `boolean` | `true` | Gradient wash under each line. | | `durationInFrames` | `number` | `34` | Length of one row's draw. | | `staggerInFrames` | `number` | `12` | Frames between one row and the next. | | `exitAtInFrames` | `number` | `undefined` | Frame the stack starts emptying on, top-down. | | `frame` | `number` | `undefined` | Frame override: pass the parent frame inside a `<Sequence>`. | ## Related - [Line Chart Draw](https://remotionui.com/docs/components/line-chart-draw.md) - [Stat Card](https://remotionui.com/docs/components/stat-card.md) - [Scatter Plot Pop](https://remotionui.com/docs/components/scatter-plot-pop.md) ## Machine-readable references - Props and usage as JSON: https://remotionui.com/ai/components/sparkline-row.json - Component index: https://remotionui.com/ai/components.json --- # Stacked Area Chart > Bands stacked on a shared baseline, wiping in from the left. Install with npx remotion-ui@latest add stacked-area-chart. Source: https://remotionui.com/docs/components/stacked-area-chart ## Installation ```bash npx remotion-ui@latest add stacked-area-chart ``` Composition over time: bands stacked on one baseline, uncovered left to right. ```tsx import { StackedAreaChart } from "@/remotion/primitives/stacked-area-chart"; <StackedAreaChart series={[ { label: "Reels", values: [140, 210, 300, 430, 520] }, { label: "Ads", values: [90, 130, 210, 300, 340] }, ]} labels={["Jan", "Mar", "May", "Jul", "Aug"]} durationInFrames={62} /> ``` ## The reveal is a wipe, not a fade A clip travels across the plot. A stacked area is read as a history, so uncovering it in time order is the only reveal that agrees with the axis underneath it. An opacity fade or a vertical grow says the values changed, which they did not. Bands are drawn bottom-up, each trailing the one below by `bandOffsetInFrames`, so the stack assembles in reading order rather than as one moving wall. ## Stacking Each band's upper edge is the sum of every series at or below it, and that same edge is the next band's floor. Pass series in the order you want them stacked; the first is the baseline band. Both edges of a band are smoothed with the same spline and the lower one is walked backwards to close the shape, so the two curves meet exactly instead of leaving a sliver at the seam. ## Axis The value axis is snapped to round numbers off the *total* stack, not off any one series, so the top of the chart is the top of the sum. ## Usage ```tsx import { StackedAreaChart } from "@/remotion/primitives/stacked-area-chart"; <StackedAreaChart series={[ { label: "Reels", values: [140, 210, 300, 430, 520] }, { label: "Ads", values: [90, 130, 210, 300, 340] }, ]} labels={["Jan", "Mar", "May", "Jul", "Aug"]} durationInFrames={62} /> ``` The reveal is a clip travelling across the plot, not a fade or a vertical grow: a stacked area is read as a history, so uncovering it in time order is the only reveal that agrees with the axis. Band edges share one spline and the lower edge is walked backwards to close the shape, so no sliver appears at the seam. ## Props | Name | Type | Default | Description | | --- | --- | --- | --- | | `series` | `StackedSeries[]` | `required` | `{ label, values, color? }`, first entry is the baseline band. | | `labels` | `string[]` | `undefined` | Category labels along the x axis, one per value. | | `width` | `number` | `880` | Drawing width. Type scales off it. | | `height` | `number` | `460` | Drawing height. | | `showAxis` | `boolean` | `true` | Gridlines and value labels down the left gutter. | | `showLegend` | `boolean` | `true` | Series names above the plot, arriving with their band. | | `showBoundaries` | `boolean` | `true` | Hairline along the top of each band. | | `fillOpacity` | `number` | `0.85` | Band fill opacity. | | `durationInFrames` | `number` | `60` | Length of the wipe across the whole plot. | | `bandOffsetInFrames` | `number` | `8` | Frames one band trails the band below it by. | | `exitAtInFrames` | `number` | `undefined` | Frame the stack retreats on, top band first. | | `frame` | `number` | `undefined` | Frame override: pass the parent frame inside a `<Sequence>`. | ## Related - [Line Chart Draw](https://remotionui.com/docs/components/line-chart-draw.md) - [Sparkline Row](https://remotionui.com/docs/components/sparkline-row.md) - [Animated Bar Chart](https://remotionui.com/docs/components/animated-bar-chart.md) ## Machine-readable references - Props and usage as JSON: https://remotionui.com/ai/components/stacked-area-chart.json - Component index: https://remotionui.com/ai/components.json --- # Treemap Blocks > Nested rectangles sized by value. Install with npx remotion-ui@latest add treemap-blocks. Source: https://remotionui.com/docs/components/treemap-blocks ## Installation ```bash npx remotion-ui@latest add treemap-blocks ``` Value blocks tiled to fill the frame, arriving largest first. ```tsx import { TreemapBlocks } from "@/remotion/primitives/treemap-blocks"; <TreemapBlocks blocks={[ { label: "Atoms", value: 46 }, { label: "Blocks", value: 31 }, { label: "Signals", value: 26 }, ]} staggerInFrames={12} /> ``` ## Squarified, not sliced The layout is the Bruls–Huizing–van Wijk squarified algorithm: rows grow along the shorter side of whatever space is left, and a row closes as soon as adding the next value would worsen its aspect ratio. Slice-and-dice layouts turn small values into long splinters that cannot be labelled and misread badly at a glance; keeping every tile near square is the only reason a treemap is legible. The layout is pure geometry over the values, so the same data always produces the same map. ## Labels A block prints its name and value only when the tile can hold them. A label that overflows its own rectangle reads as a rendering fault. In a long-tailed set the small tiles are deliberately left blank; the area still carries them. ## Motion Blocks scale up from their own centres in descending order, so the map builds outward from its dominant value. With `exitAtInFrames` the smallest leave first and the map collapses back onto that value. Use `bubble-chart-pack` when the values should not tile, since a treemap implies the parts make up a whole. ## Usage ```tsx import { TreemapBlocks } from "@/remotion/primitives/treemap-blocks"; <TreemapBlocks blocks={[ { label: "Atoms", value: 46 }, { label: "Blocks", value: 31 }, { label: "Signals", value: 26 }, ]} staggerInFrames={12} /> ``` Squarified layout (Bruls, Huizing & van Wijk): rows grow along the shorter free side and close when the next value would worsen the aspect ratio. Slice-and-dice turns small values into unlabelable splinters. A tile prints its label only when it can hold it: overflowing type reads as a rendering fault, and the area still carries the small values. ## Props | Name | Type | Default | Description | | --- | --- | --- | --- | | `blocks` | `ChartDatum[]` | `required` | `{ label, value, color? }`. Area is proportional to value. | | `width` | `number` | `820` | Box the tiles fill. | | `height` | `number` | `460` | Box height. | | `gap` | `number` | `8` | Space between tiles. | | `cornerRadius` | `number` | `12` | Tile corner radius, clamped on small tiles. | | `showShare` | `boolean` | `true` | Percentage of the total, printed beside the value. | | `durationInFrames` | `number` | `20` | Length of one tile's arrival. | | `staggerInFrames` | `number` | `6` | Frames between tiles, largest first. | | `exitAtInFrames` | `number` | `undefined` | Frame the map collapses on, smallest first. | | `frame` | `number` | `undefined` | Frame override: pass the parent frame inside a `<Sequence>`. | ## Related - [Bubble Chart Pack](https://remotionui.com/docs/components/bubble-chart-pack.md) - [Heatmap Grid](https://remotionui.com/docs/components/heatmap-grid.md) - [Donut Chart](https://remotionui.com/docs/components/donut-chart.md) ## Machine-readable references - Props and usage as JSON: https://remotionui.com/ai/components/treemap-blocks.json - Component index: https://remotionui.com/ai/components.json --- # Waterfall Chart > Bridge chart carrying a running total through signed steps. Install with npx remotion-ui@latest add waterfall-chart. Source: https://remotionui.com/docs/components/waterfall-chart ## Installation ```bash npx remotion-ui@latest add waterfall-chart ``` Floating bars that carry a running total from one figure to another. ```tsx import { WaterfallChart } from "@/remotion/primitives/waterfall-chart"; <WaterfallChart steps={[ { label: "Q1 open", value: 320, isTotal: true }, { label: "New", value: 180 }, { label: "Churn", value: -74 }, { label: "Q2 close", value: 484, isTotal: true }, ]} staggerInFrames={15} /> ``` ## Bars grow from the running total Each bar starts at the level the previous step left behind and grows by its own change. That is what separates a waterfall from a bar chart: position carries as much information as length, and growing every bar from the axis would throw the position away. ## Subtotals A step marked `isTotal` is drawn from the axis and resets the running total to its own value. That is how an opening or closing column stays honest instead of being a bar that happens to reach the same height. Signs come from the values themselves: a rise takes `upColor`, a fall `downColor`, a total `totalColor`, and the printed change keeps its sign. ## Connectors Dashed connectors leave the level a step lands on and wait for that bar to stop moving, so they never point at a level still in flight. They are skipped in front of a subtotal, which starts from the axis rather than from the step before it. ## Usage ```tsx import { WaterfallChart } from "@/remotion/primitives/waterfall-chart"; <WaterfallChart steps={[ { label: "Q1 open", value: 320, isTotal: true }, { label: "New", value: 180 }, { label: "Churn", value: -74 }, { label: "Q2 close", value: 484, isTotal: true }, ]} staggerInFrames={15} /> ``` Bars grow from the running total they start at, not from the axis: in a waterfall the position carries as much as the length. `isTotal` draws from the axis and resets the running total, which is how an opening or closing column stays honest. Connectors wait for their bar to stop before extending. ## Props | Name | Type | Default | Description | | --- | --- | --- | --- | | `steps` | `WaterfallStep[]` | `required` | `{ label, value, isTotal?, color? }`. `value` is a signed change unless `isTotal`. | | `width` | `number` | `860` | Drawing width. Type scales off it. | | `height` | `number` | `440` | Drawing height. | | `upColor` | `string` | `"#2dd4bf"` | Bars that add to the running total. | | `downColor` | `string` | `"#f472b6"` | Bars that subtract. | | `totalColor` | `string` | `"#e8b86d"` | Subtotal columns drawn from the axis. | | `showConnectors` | `boolean` | `true` | Dashed rules from one bar's landing level to the next bar's base. | | `showValues` | `boolean` | `true` | Signed change printed above or below each bar. | | `showAxis` | `boolean` | `true` | Gridlines and value labels down the left gutter. | | `durationInFrames` | `number` | `20` | Length of one bar's growth. | | `staggerInFrames` | `number` | `10` | Frames between one step and the next. | | `exitAtInFrames` | `number` | `undefined` | Frame the bridge starts clearing on, left to right. | | `frame` | `number` | `undefined` | Frame override: pass the parent frame inside a `<Sequence>`. | ## Related - [Animated Bar Chart](https://remotionui.com/docs/components/animated-bar-chart.md) - [Comparison Bars](https://remotionui.com/docs/components/comparison-bars.md) - [Funnel Chart](https://remotionui.com/docs/components/funnel-chart.md) ## Machine-readable references - Props and usage as JSON: https://remotionui.com/ai/components/waterfall-chart.json - Component index: https://remotionui.com/ai/components.json --- # Paths & shapes > SVG draw-on, shape morphs, logo reveals, and cursor paths. Source: https://remotionui.com/docs/components/paths-and-shapes These components animate vector geometry: strokes that draw on, shapes that morph, and cursors that follow a path. They work with your own SVG paths as well as the built-in shapes. ## Components - [Arrow Annotate](https://remotionui.com/docs/components/arrow-annotate.md): A hand-drawn arrow that draws itself, with the head landing on the curve's own tangent. - [Badge Stamp](https://remotionui.com/docs/components/badge-stamp.md): A seal that lands like a stamp, oversized and over-rotated, settling with the rotation still unwinding after the scale has stopped. - [Blob Morph](https://remotionui.com/docs/components/blob-morph.md): An organic blob that never settles, travelling a ring of generated shapes and coming back to where it started. - [Connector Lines](https://remotionui.com/docs/components/connector-lines.md): The edges between anchored elements, and nothing else, the primitive under a diagram. - [Cursor Path](https://remotionui.com/docs/components/cursor-path.md): Cursor travelling a route, with drawn trail and click ripples. - [Dashed Path Travel](https://remotionui.com/docs/components/dashed-path-travel.md): Anything travelling any route, laying a dashed trail behind it. - [Logo Reveal](https://remotionui.com/docs/components/logo-reveal.md): Logo mark draw-on with wordmark and tagline beats. - [Path Draw](https://remotionui.com/docs/components/path-draw.md): SVG stroke reveal with auto-fit framing and multi-path stagger. - [Shape Morph](https://remotionui.com/docs/components/shape-morph.md): One shape becoming another, and another, on a single progress ramp. - [Simulated Cursor](https://remotionui.com/docs/components/simulated-cursor.md): Frame-timed cursor with press, ripples, hit targets and labels. - [SVG Mask Reveal](https://remotionui.com/docs/components/svg-mask-reveal.md): An arbitrary SVG shape used as a reveal mask over anything. --- # Arrow Annotate > A hand-drawn arrow that draws itself, with the head landing on the curve's own tangent. Source: https://remotionui.com/docs/components/arrow-annotate ## Installation ```bash npx remotion-ui@latest add arrow-annotate ``` The shaft grows from its start and the head lands over the last quarter of the stroke, angled to the curve's tangent rather than to the straight line between the ends, so the arrow points where it is actually travelling. The hand-drawn quality is two passes over the same curve at a sub-pixel offset, the way a pen doubles back on a line. It is not a wobbling path: moving the points per frame reads as a *shaking* arrow, which is a different and much worse effect. Set `sketch={false}` for a single clean stroke. Endpoints are fractions of the box, so the same arrow works at any size, and `bow` pushes the midpoint along the line's own normal. The curve therefore stays proportional whatever the arrow's length or angle. Negative values bow the other way. The stroke draws on an editorial curve rather than an ease-out. A strong ease-out spends most of its duration barely moving, so a drawing stroke on it finishes in its first frames and then crawls; a pen keeps roughly one speed. ## Usage ```tsx import { ArrowAnnotate } from "@/remotion/primitives/arrow-annotate"; <ArrowAnnotate from={{ x: 0.08, y: 0.16 }} to={{ x: 0.82, y: 0.74 }} bow={0.28} label="this one" durationInFrames={70} exitAtInFrames={92} /> ``` The head is angled to the curve's own tangent, not to the straight line between the ends, so the arrow points where it is travelling. The hand-drawn quality is two passes at a sub-pixel offset, not a path whose points move per frame, which reads as a shaking arrow. The stroke draws on an editorial curve; a strong ease-out would finish in its first frames and then crawl. ## Props | Name | Type | Default | Description | | --- | --- | --- | --- | | `from` | `{ x: number; y: number }` | `{ x: 0.08, y: 0.16 }` | Start of the shaft, as a fraction of the box. | | `to` | `{ x: number; y: number }` | `{ x: 0.82, y: 0.74 }` | The point the head lands on, as a fraction of the box. | | `bow` | `number` | `0.28` | How far the shaft bows off the straight line, as a fraction of the distance. Negative bows the other way. | | `label` | `string` | - | Text set beside the start of the shaft. | | `labelSize` | `number` | `16` | Label type size in box units. The default suits a small annotation over a screenshot; raise it when the arrow is the subject of the frame. | | `width` | `number` | `320` | Box width in pixels. | | `height` | `number` | `220` | Box height in pixels. | | `stroke` | `string` | `"#E8B86D"` | Colour of the shaft, head and label. | | `strokeWidth` | `number` | `3` | Shaft weight. The second sketch pass runs at 60% of it. | | `headSize` | `number` | `18` | Length of the head's barbs, in box units. | | `sketch` | `boolean` | `true` | Draws the shaft twice at a sub-pixel offset. False for a single clean stroke. | | `delayInFrames` | `number` | `0` | Frames to wait before the shaft starts drawing. | | `durationInFrames` | `number` | `40` | Frames the shaft takes. The head lands over the last quarter. | | `exitAtInFrames` | `number` | - | Frame the arrow starts leaving. Omit to leave it on screen. | | `exitInFrames` | `number` | `14` | Frames the exit takes. | ## Related - [Path Draw](https://remotionui.com/docs/components/path-draw.md) - [Handwriting Text](https://remotionui.com/docs/components/handwriting-text.md) - [Cursor Path](https://remotionui.com/docs/components/cursor-path.md) ## Machine-readable references - Props and usage as JSON: https://remotionui.com/ai/components/arrow-annotate.json - Component index: https://remotionui.com/ai/components.json --- # Badge Stamp > A seal that lands like a stamp, oversized and over-rotated, settling with the rotation still unwinding after the scale has stopped. Source: https://remotionui.com/docs/components/badge-stamp ## Installation ```bash npx remotion-ui@latest add badge-stamp ``` The seal comes in at more than twice its size and further round than it will finish, hits its mark, and settles. Scale and rotation run on separate springs so the rotation is still unwinding fractionally after the scale has stopped. That offset is what sells the weight. Collapse them onto one spring and the stamp reads as a sticker being placed. The shockwave is thrown from the impact frame rather than from the start, so it can never arrive before the thing that caused it. Ink strength eases back a little after the hit, the way pressure comes off a real stamp. Ring text runs on two separate half-arcs, both left to right. Letters stand up from the direction of travel, so a single full-circle path would print everything on the bottom half upside down: `ringText` takes the top, `ringTextBottom` the bottom, and each should be short enough not to run past the side of the ring. ## Usage ```tsx import { BadgeStamp } from "@/remotion/primitives/badge-stamp"; <BadgeStamp label="APPROVED" ringText="REMOTIONUI" ringTextBottom="VERIFIED BUILD" sublabel="2026" delayInFrames={14} exitAtInFrames={92} /> ``` Scale and rotation run on separate springs, so the rotation is still unwinding after the scale has stopped, and that offset is what sells the weight, and collapsing them onto one spring makes the seal read as a sticker being placed. The shockwave is thrown from the impact frame rather than from the start, so it cannot arrive before its cause. Ring text uses two half-arcs because letters stand up from the direction of travel. ## Props | Name | Type | Default | Description | | --- | --- | --- | --- | | `label` | `string` | `"APPROVED"` | The word in the middle of the seal. | | `ringText` | `string` | `"REMOTIONUI"` | Text curved around the top. Keep it short enough not to run past the sides. | | `ringTextBottom` | `string` | `"VERIFIED BUILD"` | Text curved around the bottom, on its own left-to-right arc so it reads upright. | | `sublabel` | `string` | `"2026"` | Line under the label. | | `size` | `number` | `220` | Rendered size in pixels. | | `color` | `string` | `"#E8B86D"` | Ink colour for every part of the seal. | | `rotation` | `number` | `-9` | Degrees the stamp settles at. | | `windUp` | `number` | `16` | How much further round it starts, in degrees. | | `delayInFrames` | `number` | `6` | Frame the stamp lands on. | | `exitAtInFrames` | `number` | - | Frame the stamp starts leaving. Omit to leave it on screen. | | `exitInFrames` | `number` | `16` | Frames the exit takes. | | `impactRing` | `boolean` | `true` | Shockwave thrown off on impact. | ## Related - [Confetti Burst](https://remotionui.com/docs/components/confetti-burst.md) - [Glow Pulse](https://remotionui.com/docs/components/glow-pulse.md) - [Logo Reveal](https://remotionui.com/docs/components/logo-reveal.md) ## Machine-readable references - Props and usage as JSON: https://remotionui.com/ai/components/badge-stamp.json - Component index: https://remotionui.com/ai/components.json --- # Blob Morph > An organic blob that never settles, travelling a ring of generated shapes and coming back to where it started. Source: https://remotionui.com/docs/components/blob-morph ## Installation ```bash npx remotion-ui@latest add blob-morph ``` The blob loops through a ring of generated outlines and returns to the first, so the wrap from the end of the period back to the start lands on the same geometry and the loop has no seam. There is no entrance and no exit. It is alive from the first frame. Outlines are generated, not authored: points around a circle, displaced by three sine harmonics whose phases come from the `seed`. Two harmonics leave a shape that reads as symmetrical; the third breaks it. Every variant uses the same point count, so they all reduce to the same number of curve commands and morph into each other without the interpolator inventing segments. Control arms are computed from the point count rather than being a constant: the arm wants to be `(4/3)·tan(π/2N)` of the radius, taken along the neighbours' chord. A guessed constant gives you a polygon when it is too short and scalloped bulges between the points when it is too long, and both look like a bug rather than a blob. `rotation` is continuous rather than wrapping, so for a seamless loop set it to 0 or a multiple of 360. It is an SVG shape, not a background. Give it a colour and put it behind something, or hand the same idea to `svg-mask-reveal` as a mask. ## Usage ```tsx import { BlobMorph } from "@/remotion/primitives/blob-morph"; <BlobMorph size={320} periodInFrames={96} amplitude={0.22} seed={1} /> ``` Outlines are generated from three sine harmonics seeded by the seed prop: two alone leave a shape that reads as symmetrical. Every variant shares a point count so they reduce to the same curve commands and morph without invented segments. Control arms are computed from the point count, (4/3)·tan(π/2N) of the radius along the neighbours' chord: a guessed constant gives a polygon when short and scalloped bulges when long. No entrance or exit: it is alive from frame 0. ## Props | Name | Type | Default | Description | | --- | --- | --- | --- | | `size` | `number` | `260` | Rendered size in pixels. | | `fill` | `string` | `"#E8B86D"` | Blob fill. Pass undefined for an outline only. | | `stroke` | `string` | - | Outline colour. Omit for a filled blob. | | `strokeWidth` | `number` | `3` | Outline weight, when stroke is set. | | `periodInFrames` | `number` | `150` | Frames for one full trip around the ring of shapes. | | `states` | `number` | `4` | How many shapes the loop travels through. Three to six reads as organic. | | `points` | `number` | `10` | Points around the outline. More points, more detail and more wobble. | | `amplitude` | `number` | `0.22` | How far the outline deviates from a circle, as a fraction of the radius. | | `seed` | `number` | `1` | Changes the shape family without changing anything else. | | `rotation` | `number` | `12` | Degrees per period. Continuous, so a seamless loop wants 0 or a multiple of 360. | ## Related - [Shape Morph](https://remotionui.com/docs/components/shape-morph.md) - [Aurora Background](https://remotionui.com/docs/components/aurora-bg.md) - [SVG Mask Reveal](https://remotionui.com/docs/components/svg-mask-reveal.md) ## Machine-readable references - Props and usage as JSON: https://remotionui.com/ai/components/blob-morph.json - Component index: https://remotionui.com/ai/components.json --- # Connector Lines > The edges between anchored elements, and nothing else, the primitive under a diagram. Source: https://remotionui.com/docs/components/connector-lines ## Installation ```bash npx remotion-ui@latest add connector-lines ``` This draws lines between named points and leaves the boxes to you. Position your own nodes at the same fractional coordinates the anchors use, as the preview does, and the lines and the layout stay in register at any size. That is why anchors are fractions rather than pixels. Three edge shapes ship. `curve` bows toward the midpoint's own normal, so the bow stays proportional whatever the edge's length or angle; `elbow` turns once at right angles, for hierarchies read as columns; `straight` goes direct. Edges draw in order with a stagger, each on its own `pathLength={1}`, so a long curve and a short hop take the same time and the diagram assembles at an even pace. An edge naming an anchor that does not exist is dropped rather than drawn to the origin, which would put a line through the corner of the box. `dashed` fades its edges in rather than drawing them: a dash pattern cannot both space the line and reveal it. Use it when the lines are a relationship rather than a flow. For a full scene with payloads travelling the edges, use `data-flow-pipes`. ## Usage ```tsx import { ConnectorLines } from "@/remotion/primitives/connector-lines"; <ConnectorLines anchors={[ { id: "source", x: 0.12, y: 0.5 }, { id: "parse", x: 0.44, y: 0.18 }, { id: "output", x: 0.86, y: 0.5 }, ]} edges={[ { from: "source", to: "parse", shape: "curve", bow: 0.12, dot: true }, { from: "parse", to: "output", shape: "curve", bow: 0.12, dot: true }, ]} /> ``` This is the primitive under a diagram, not the diagram: position your own nodes at the same fractional anchors and the lines stay in register at any size. Each edge draws on its own pathLength={1}, so a long curve and a short hop take the same time. An edge naming a missing anchor is dropped rather than drawn to the origin. For a full scene with payloads travelling the edges, use data-flow-pipes. ## Props | Name | Type | Default | Description | | --- | --- | --- | --- | | `anchors` | `ConnectorAnchor[]` | `4 sample anchors` | Named points as fractions of the box, so the same table drives your layout. | | `edges` | `ConnectorEdge[]` | `4 sample edges` | from / to anchor ids, plus shape, bow, colour and an optional arrival dot. | | `width` | `number` | `420` | Box width in pixels. | | `height` | `number` | `240` | Box height in pixels. | | `stroke` | `string` | `"#E8B86D"` | Default edge colour. | | `strokeWidth` | `number` | `2` | Edge weight. | | `dashed` | `boolean` | `false` | Dashes every edge: useful when the lines are a relationship rather than a flow. Dashed edges draw on through a mask, with the dashes marching as they go, so they animate exactly like solid ones. | | `delayInFrames` | `number` | `0` | Frames to wait before the first edge draws. | | `durationInFrames` | `number` | `26` | Frames one edge takes to draw. | | `staggerInFrames` | `number` | `10` | Frames between edges. | | `exitAtInFrames` | `number` | - | Frame the lines start leaving. Omit to leave them on screen. | | `exitInFrames` | `number` | `16` | Frames the exit takes. | ## Related - [Data Flow Pipes](https://remotionui.com/docs/components/data-flow-pipes.md) - [Org Chart Build](https://remotionui.com/docs/components/org-chart-build.md) - [Dashed Path Travel](https://remotionui.com/docs/components/dashed-path-travel.md) ## Machine-readable references - Props and usage as JSON: https://remotionui.com/ai/components/connector-lines.json - Component index: https://remotionui.com/ai/components.json --- # Cursor Path > Cursor travelling a route, with drawn trail and click ripples. Source: https://remotionui.com/docs/components/cursor-path ## Installation ```bash npx remotion-ui@latest add cursor-path ``` Moves a pointer along a route built from `points`, or along an SVG path passed to `d`. Travel is measured by arc length, so the cursor holds one speed across a long hop and a short one, and `smoothing` rounds the corners into a hand-like curve. The trail draws in behind the cursor by default; `trail="guide"` shows the whole route up front instead. `clickAt` ripples at the waypoints you name: the timing is derived from where each waypoint sits along the path, so clicks stay in sync when the duration changes. ## Usage ```tsx import { CursorPath } from "@/remotion/primitives/cursor-path"; <CursorPath points={[{ x: 80, y: 120 }, { x: 320, y: 80 }]} clickAt={[1]} /> ``` Advanced. Installs @remotion/paths. ## Props | Name | Type | Default | Description | | --- | --- | --- | --- | | `points` | `{ x: number; y: number }[]` | - | Route waypoints in the parent's coordinates. | | `d` | `string` | - | Authored SVG path to follow instead of points. | | `durationInFrames` | `number` | `90` | Travel duration. | | `delayInFrames` | `number` | `0` | Frames before the cursor sets off. | | `color` | `string` | `"#e8b86d"` | Trail and ripple color. | | `size` | `number` | `34` | Cursor size in px. | | `smoothing` | `number` | `0.6` | 0 hops in straight lines; higher rounds corners. | | `trail` | `"draw" \| "guide" \| "none"` | `"draw"` | Reveal the route behind the cursor, show it up front, or hide it. | | `clickAt` | `number[]` | - | Waypoint indices that ripple as the cursor arrives. | ## Related - [Simulated Cursor](https://remotionui.com/docs/components/simulated-cursor.md) - [Callout Spotlight](https://remotionui.com/docs/components/callout-spotlight.md) - [Zoom Pan Frame](https://remotionui.com/docs/components/zoom-pan-frame.md) ## Machine-readable references - Props and usage as JSON: https://remotionui.com/ai/components/cursor-path.json - Component index: https://remotionui.com/ai/components.json --- # Dashed Path Travel > Anything travelling any route, laying a dashed trail behind it. Source: https://remotionui.com/docs/components/dashed-path-travel ## Installation ```bash npx remotion-ui@latest add dashed-path-travel ``` Give it a `d` string or a list of waypoints and it builds the route, sends something along it, and marks the road behind. The traveller is `children`: anything renderable, centred on the point, and turned to face along the route with `orient`. The trail is a fixed dash pattern revealed by a mask that grows with the head, not a dashed stroke that grows. Growing the pattern slides every dash along the route as the line extends, which reads as a line being stretched; a fixed pattern under a growing mask reads as a road being marked out. Position and angle come from arc-length sampling, so the traveller moves at a constant speed around corners instead of hurrying through the straight sections the way a per-segment lerp does. `trackColor` draws the part of the route not yet travelled. Leave it on when the destination matters and the viewer should see where this is going; omit it when the reveal is the point. For a cursor specifically, with its own hardware shape and click beats, use `cursor-path`. ## Usage ```tsx import { DashedPathTravel } from "@/remotion/primitives/dashed-path-travel"; <DashedPathTravel waypoints={[ { x: 20, y: 150 }, { x: 90, y: 60 }, { x: 280, y: 40 }, ]} orient durationInFrames={86} exitAtInFrames={92} /> ``` The trail is a fixed dash pattern revealed by a mask that grows with the head, not a dashed stroke that grows: growing the pattern slides every dash along the route, which reads as a stretching line rather than a road being marked. Position and angle come from arc-length sampling, so the traveller keeps a constant speed around corners. For a cursor with its own hardware shape and click beats, use cursor-path. ## Props | Name | Type | Default | Description | | --- | --- | --- | --- | | `d` | `string` | - | The route as a path string. Give this or waypoints. | | `waypoints` | `TravelPoint[]` | `4 sample points` | Points the route passes through, in path units. | | `smoothing` | `number` | `0.4` | Corner rounding when building from waypoints. 0 gives straight hops. | | `children` | `ReactNode` | - | What travels the path. Centred on the point; falls back to a dot. | | `dotRadius` | `number` | `7` | Radius of the default dot, used when no children are given. | | `orient` | `boolean` | `false` | Turns the traveller to the path's tangent. | | `width` | `number` | `320` | Box width in pixels. | | `height` | `number` | `200` | Box height in pixels. | | `viewBox` | `string` | - | Omit to frame the route automatically from its bounding box. | | `trailColor` | `string` | `"#E8B86D"` | The dashed route behind the traveller. | | `trackColor` | `string` | `"rgba(255,255,255,0.12)"` | The route not yet travelled. Omit to hide where this is going. | | `strokeWidth` | `number` | `2.5` | Weight of both the track and the trail. | | `dash` | `number` | `9` | Dash and gap length, in path units. | | `delayInFrames` | `number` | `0` | Frames to wait before setting off. | | `durationInFrames` | `number` | `70` | Frames the trip takes. | | `exitAtInFrames` | `number` | - | Frame the whole thing starts leaving. Omit to leave it on screen. | | `exitInFrames` | `number` | `16` | Frames the exit takes. | ## Related - [Cursor Path](https://remotionui.com/docs/components/cursor-path.md) - [Path Draw](https://remotionui.com/docs/components/path-draw.md) - [Connector Lines](https://remotionui.com/docs/components/connector-lines.md) ## Machine-readable references - Props and usage as JSON: https://remotionui.com/ai/components/dashed-path-travel.json - Component index: https://remotionui.com/ai/components.json --- # Logo Reveal > Logo mark draw-on with wordmark and tagline beats. Source: https://remotionui.com/docs/components/logo-reveal ## Installation ```bash npx remotion-ui@latest add logo-reveal ``` Four beats: a bloom settles, the mark draws on with `path-draw`, the wordmark springs up, and the tagline follows. Pass an array to `pathD` for a multi-stroke mark: the strokes draw in order. The mark sizes itself from the frame's short edge and grows when no copy is supplied, so the scene fills both a 16:9 outro and a 9:16 clip without tuning. ## Usage ```tsx import { LogoReveal } from "@/remotion/scenes/logo-reveal"; <LogoReveal pathD="M 100 20 L 180 180 L 20 180 Z" wordmark="Acme" tagline="Ship faster" /> ``` ## Props | Name | Type | Default | Description | | --- | --- | --- | --- | | `pathD` (required) | `string \| string[]` | - | Logo path, or paths drawn in sequence. | | `viewBox` | `string` | - | Omit to frame the mark automatically. | | `size` | `number` | - | Mark size in px. Defaults to a share of the short edge. | | `wordmark` | `string` | - | Brand name rising after the mark completes. | | `tagline` | `string` | - | Supporting line, entering last. | | `stroke` | `string` | `"#e8b86d"` | Mark stroke color. | | `strokeWidth` | `number` | - | Defaults to a share of the mark size. | | `fill` | `string` | - | Fill flooded into the mark after the draw. | | `backgroundColor` | `string` | `"#080810"` | Scene background. | ## Related - [Path Draw](https://remotionui.com/docs/components/path-draw.md) - [Title Card](https://remotionui.com/docs/components/title-card.md) ## Machine-readable references - Props and usage as JSON: https://remotionui.com/ai/components/logo-reveal.json - Component index: https://remotionui.com/ai/components.json --- # Path Draw > SVG stroke reveal with auto-fit framing and multi-path stagger. Source: https://remotionui.com/docs/components/path-draw ## Installation ```bash npx remotion-ui@latest add path-draw ``` Reveals a stroke with `@remotion/paths` `evolvePath()`, and rides a bright head along the tip while it draws. Pass an array to `d` to draw several paths in sequence: each starts `staggerInFrames` after the last. Omit `viewBox` and the artwork is framed from its own bounding box, so a path exported anywhere on its canvas still lands centred and filling the frame. Set `fill` to flood colour in once the outline closes. ## Usage ```tsx import { PathDraw } from "@/remotion/primitives/path-draw"; <PathDraw d={["M 20 180 L 100 20 L 180 180", "M 60 120 L 140 120"]} durationInFrames={60} /> ``` Advanced. Installs @remotion/paths. ## Props | Name | Type | Default | Description | | --- | --- | --- | --- | | `d` (required) | `string \| string[]` | - | One path, or several drawn in order. | | `durationInFrames` | `number` | `60` | Draw length for each path. | | `delayInFrames` | `number` | `0` | Frames before the first path starts. | | `staggerInFrames` | `number` | `8` | Offset between paths when d is an array. | | `stroke` | `string` | `"#e8b86d"` | Stroke color. | | `strokeWidth` | `number` | `4` | Stroke width in path units. | | `width` | `number` | `200` | Rendered SVG width in px. | | `height` | `number` | `200` | Rendered SVG height in px. | | `viewBox` | `string` | - | Omit to frame the artwork from its bounding box. | | `fill` | `string` | - | Fill flooded in once the stroke closes. | | `head` | `boolean` | `true` | Dot riding the tip while it draws. | | `glow` | `boolean` | `true` | Soft bloom around the stroke. | ## Related - [Logo Reveal](https://remotionui.com/docs/components/logo-reveal.md) - [Cursor Path](https://remotionui.com/docs/components/cursor-path.md) ## Machine-readable references - Props and usage as JSON: https://remotionui.com/ai/components/path-draw.json - Component index: https://remotionui.com/ai/components.json --- # Shape Morph > One shape becoming another, and another, on a single progress ramp. Source: https://remotionui.com/docs/components/shape-morph ## Installation ```bash npx remotion-ui@latest add shape-morph ``` Give it a chain of shapes and it travels through them on one ramp. Names come from the `MORPH_SHAPES` presets, and anything else is treated as a raw `d` string, so a logo can sit in the chain beside a circle. The chain is prepared once and evaluated per frame. Preparation is the expensive half (parsing, winding alignment, box fitting), and it depends on nothing but the `d` strings, so doing it inside the render would re-parse every path thirty times a second for strings that never change. That is what `prepareMorph` in `lib/path-morph.ts` exists for, and it is shared with `blob-morph` and the displacement transitions. Steps inside the chain are linear on purpose. Easing each hop individually puts a stall at every shape, which reads as a slideshow; the easing belongs on the ramp that drives the whole chain, which is where it is. `rotation` turns the shape across the chain. A little is worth having: without it, a symmetrical pair like square-to-diamond can look like a still image at the midpoint. `loop` closes the ring back to the first shape so a looping driver has no seam. Shapes morph cleanly when they reduce to a similar number of curves: the presets are all authored as four-curve closed paths for exactly that reason. A detailed logo morphing into a circle will always fold somewhere. ## Usage ```tsx import { ShapeMorph } from "@/remotion/primitives/shape-morph"; <ShapeMorph shapes={["circle", "squircle", "triangle", "diamond"]} size={300} durationInFrames={96} exitAtInFrames={92} /> ``` The chain is prepared once and evaluated per frame: preparation (parsing, winding alignment, box fitting) depends only on the d strings, so doing it in the render would re-parse every path 30 times a second. Steps inside the chain are linear on purpose: easing each hop puts a stall at every shape, which reads as a slideshow. Shapes morph cleanly when they reduce to a similar curve count; the presets are all four-curve closed paths. ## Props | Name | Type | Default | Description | | --- | --- | --- | --- | | `shapes` | `(MorphShapeName \| string)[]` | `["circle", "squircle", "triangle", "diamond"]` | Shapes to travel through. Preset names, or raw d strings authored on a 0–100 box. | | `delayInFrames` | `number` | `0` | Frames to wait before the morph starts. | | `durationInFrames` | `number` | `90` | Frames the whole chain takes, end to end. | | `loop` | `boolean` | `false` | Returns to the first shape so a looping driver has no seam. | | `size` | `number` | `220` | Rendered size in pixels. | | `fill` | `string` | `"#E8B86D"` | Shape fill. Pass undefined for an outline only. | | `stroke` | `string` | - | Outline colour. Omit for a filled shape with no outline. | | `strokeWidth` | `number` | `3` | Outline weight, when stroke is set. | | `rotation` | `number` | `18` | Degrees turned across the chain. Stops a symmetrical pair looking static. | | `exitAtInFrames` | `number` | - | Frame the shape starts leaving. Omit to leave it on screen. | | `exitInFrames` | `number` | `16` | Frames the exit takes. | ## Related - [Blob Morph](https://remotionui.com/docs/components/blob-morph.md) - [Path Draw](https://remotionui.com/docs/components/path-draw.md) - [SVG Mask Reveal](https://remotionui.com/docs/components/svg-mask-reveal.md) ## Machine-readable references - Props and usage as JSON: https://remotionui.com/ai/components/shape-morph.json - Component index: https://remotionui.com/ai/components.json --- # Simulated Cursor > Frame-timed cursor with press, ripples, hit targets and labels. Source: https://remotionui.com/docs/components/simulated-cursor ## Installation ```bash npx remotion-ui@latest add simulated-cursor ``` Drives a pointer across percentage-based waypoints with an arrival frame each. Every hop runs its own spring, so the cursor decelerates into a target the way a hand does rather than gliding at a fixed rate. Give a waypoint a `target` to ring the hit area, and a `label` to chip the control being used. Frames listed in `clickFrames` press the pointer down and fire a ripple. ## Usage ```tsx import { SimulatedCursor } from "@/remotion/primitives/simulated-cursor"; <SimulatedCursor points={[ { x: 20, y: 60, frame: 0 }, { x: 70, y: 40, frame: 30, target: 96, label: "Render" }, ]} clickFrames={[32]} /> ``` Each hop runs its own spring, so the cursor decelerates into a target instead of gliding at a fixed rate. ## Props | Name | Type | Default | Description | | --- | --- | --- | --- | | `points` | `Array<{ x: number; y: number; frame: number; label?: string; target?: number }>` | - | Percent-based waypoints with arrival frames. `label` chips the point, `target` rings the hit area in px. | | `clickFrames` | `number[]` | `[48]` | Frames that press the pointer and fire a ripple. | | `color` | `string` | `"#f4f4f5"` | Pointer fill. | | `accent` | `string` | `"#e8b86d"` | Ripple and target ring color. | | `size` | `number` | `26` | Cursor size in px. | ## Related - [Cursor Path](https://remotionui.com/docs/components/cursor-path.md) - [Tutorial Clip](https://remotionui.com/docs/components/tutorial-clip.md) ## Machine-readable references - Props and usage as JSON: https://remotionui.com/ai/components/simulated-cursor.json - Component index: https://remotionui.com/ai/components.json --- # SVG Mask Reveal > An arbitrary SVG shape used as a reveal mask over anything. Source: https://remotionui.com/docs/components/svg-mask-reveal ## Installation ```bash npx remotion-ui@latest add svg-mask-reveal ``` The shape grows from `origin` until it covers the frame, revealing whatever you pass as children: media, a scene, a gradient, another component. The scale it has to reach is computed from the distance to the furthest corner, not from the frame's width. A shape opening from a corner has much further to travel than one opening from the middle, and a fixed multiplier either leaves a gap on one side or overshoots so far that the last half of the animation is nothing happening. It uses an SVG `<mask>` rather than a CSS `clip-path`, so any `d` string authored anywhere drops straight in and the same shape can carry soft edges. Names from `MORPH_SHAPES` work directly; custom paths should be authored on a 0–100 box, since that is the box the scale maths assumes. `invert` runs the shape backwards over the content, which is how you close a scene with the same figure you opened it with. `bouncy` springs the growth instead of easing it, and `rotation` turns the shape as it opens, worth a few degrees on an angular mask so the edge does not arrive parallel to the frame. ## Usage ```tsx import { SvgMaskReveal } from "@/remotion/primitives/svg-mask-reveal"; <SvgMaskReveal shape="squircle" origin={{ x: 0.32, y: 0.36 }} durationInFrames={90} rotation={40} > <YourContent /> </SvgMaskReveal> ``` The scale is computed from the distance to the furthest corner, not from the frame width: a shape opening from a corner has much further to travel, and a fixed multiplier either leaves a gap or spends half the animation doing nothing. It uses an SVG <mask> rather than a CSS clip-path, so any authored path drops in and the shape can carry soft edges. Custom paths must be authored on a 0–100 box, which is what the scale maths assumes. ## Props | Name | Type | Default | Description | | --- | --- | --- | --- | | `children` | `ReactNode` | - | What the mask reveals: media, a scene, a gradient, another component. | | `shape` | `MorphShapeName \| string` | `"circle"` | Mask shape: a preset name, or any d string authored on a 0–100 box. | | `origin` | `{ x: number; y: number }` | `{ x: 0.5, y: 0.5 }` | Where the shape opens from, as a fraction of the frame. | | `delayInFrames` | `number` | `0` | Frames to wait before the reveal starts. | | `durationInFrames` | `number` | `40` | Frames the reveal takes. | | `rotation` | `number` | `0` | Degrees the shape turns as it opens. | | `bouncy` | `boolean` | `false` | Springs the growth instead of easing it. | | `invert` | `boolean` | `false` | Shrinks the shape back over the content, to close a scene with the figure that opened it. | | `backgroundColor` | `string` | - | Painted behind the masked content. Omit for transparency. | ## Related - [Shape Morph](https://remotionui.com/docs/components/shape-morph.md) - [Blob Morph](https://remotionui.com/docs/components/blob-morph.md) - [Directional Wipe](https://remotionui.com/docs/components/directional-wipe.md) ## Machine-readable references - Props and usage as JSON: https://remotionui.com/ai/components/svg-mask-reveal.json - Component index: https://remotionui.com/ai/components.json --- # Maps & devices > Map flights, routes, markers, and device mockups for product shots. Source: https://remotionui.com/docs/components/maps-and-devices Map components render real map tiles with camera moves, routes, and markers. Device components frame your screenshots or video in phones, laptops, and browsers. ## Components - [Device Mockup Zoom](https://remotionui.com/docs/components/device-mockup-zoom.md): Cinematic laptop, phone, or browser mockup with staged UI and slow camera pullback. - [Globe Arc](https://remotionui.com/docs/components/globe-arc.md): Great-circle arcs drawing between cities on a slowly spinning globe. - [Map Canvas](https://remotionui.com/docs/components/map-canvas.md): Deterministic MapLibre map mount. - [Map Flight](https://remotionui.com/docs/components/map-flight.md): Animated map flyover with route reveal and markers. - [Map Heat Overlay](https://remotionui.com/docs/components/map-heat-overlay.md): A density overlay fading in over the basemap, with the hot cores arriving last. - [Map Markers](https://remotionui.com/docs/components/map-markers.md): GeoJSON circle and label markers on a map. - [Map Route](https://remotionui.com/docs/components/map-route.md): Animated GeoJSON route line on a map. - [Multi-Device Lineup](https://remotionui.com/docs/components/multi-device-lineup.md): Phone, tablet and laptop showing one responsive design, arriving in order. --- # Device Mockup Zoom > Cinematic laptop, phone, or browser mockup with staged UI and slow camera pullback. Source: https://remotionui.com/docs/components/device-mockup-zoom ## Installation ```bash npx remotion-ui@latest add device-mockup-zoom ``` Device mockup scene with a physical laptop shell by default, plus phone and browser variants. Pass `src` or `children` to replace the default staged app screen; add `title` and `subtitle` only when the shot needs a caption. ## Usage ```tsx import { DeviceMockupZoom } from "@/remotion/scenes/device-mockup-zoom"; <DeviceMockupZoom src={staticFile("app.png")} device="laptop" /> ``` ## Props | Name | Type | Default | Description | | --- | --- | --- | --- | | `src` | `string` | - | Optional screen content image. When omitted, the scene renders a polished product dashboard mockup. | | `title` | `string` | - | Optional headline. When omitted, the device remains the sole focal point. | | `subtitle` | `string` | - | Optional supporting line under the headline. | | `eyebrow` | `string` | - | Optional accent label above the headline. | | `device` | `"phone" \| "browser" \| "laptop"` | `"laptop"` | Mockup shell. Laptop includes a physical base, browser renders chrome only, phone renders a handheld frame. | | `children` | `React.ReactNode` | - | Custom screen content rendered inside the device. | ## Related - [Media Frame](https://remotionui.com/docs/components/media-frame.md) - [Zoom Pan Frame](https://remotionui.com/docs/components/zoom-pan-frame.md) ## Machine-readable references - Props and usage as JSON: https://remotionui.com/ai/components/device-mockup-zoom.json - Component index: https://remotionui.com/ai/components.json --- # Globe Arc > Great-circle arcs drawing between cities on a slowly spinning globe. Source: https://remotionui.com/docs/components/globe-arc ## Installation ```bash npx remotion-ui@latest add globe-arc ``` The globe is projected arithmetically (orthographic, the way a sphere looks from far away) rather than drawn from map tiles. There is no network dependency and no `delayRender`: every frame is a pure function of its own number, which is what a render farm wants and what a spinning globe made of tiles cannot give you. Arcs are great circles, sampled and clipped to the front hemisphere. The clipping is the part that matters: without a visibility test, points on the far side project onto the near side and routes fold back across the disc, which is the single thing that makes a hand-rolled globe look wrong. A route that leaves the front hemisphere breaks its path and picks up again where it returns. Each route draws in turn, with a head dot riding the line while it grows. The origin's label exists from the first frame and the destination's only once the arc has landed, so a label never precedes its route. `spinPerSecond` and `tilt` set the camera. Keep the spin slow: 10 to 20 degrees a second reads as a globe; faster reads as a loading spinner. For real geography with coastlines and place names, use `map-flight`, which flies a MapLibre camera along the route instead. ## Usage ```tsx import { GlobeArc } from "@/remotion/primitives/globe-arc"; <GlobeArc size={380} routes={[ { from: { lng: -74, lat: 40.7, label: "NYC" }, to: { lng: -0.1, lat: 51.5, label: "London" } }, ]} /> ``` Projected arithmetically rather than drawn from tiles, so there is no network dependency and no delayRender: every frame is a pure function of its number. Arcs are great circles clipped to the front hemisphere: without the visibility test, far-side points project onto the near side and routes fold across the disc, which is what makes a hand-rolled globe look wrong. For real coastlines and place names, use map-flight. ## Props | Name | Type | Default | Description | | --- | --- | --- | --- | | `routes` | `GlobeArcRoute[]` | `4 sample routes` | from / to coordinates with optional labels, colour and its own delay. | | `size` | `number` | `420` | Rendered size in pixels. | | `spinPerSecond` | `number` | `14` | Degrees of longitude turned per second. Above ~20 it reads as a loading spinner. | | `startLongitude` | `number` | `-40` | Longitude facing the viewer at frame 0. | | `tilt` | `number` | `18` | Camera latitude. Positive tilts the north pole toward you. | | `delayInFrames` | `number` | `6` | Frames to wait before the first arc draws. | | `durationInFrames` | `number` | `34` | Frames one arc takes to draw. | | `staggerInFrames` | `number` | `16` | Frames between arcs, when a route sets no delay of its own. | | `sphereColor` | `string` | `"#0E1524"` | Fill of the globe itself. | | `graticuleColor` | `string` | `"rgba(125,211,232,0.22)"` | Meridians, parallels and the limb. | | `arcColor` | `string` | `"#E8B86D"` | Default route colour. | | `cityColor` | `string` | `"#7DD3E8"` | City dots and labels. | | `exitAtInFrames` | `number` | - | Frame the globe starts leaving. Omit to leave it on screen. | | `exitInFrames` | `number` | `16` | Frames the exit takes. | ## Related - [Map Flight](https://remotionui.com/docs/components/map-flight.md) - [Map Route](https://remotionui.com/docs/components/map-route.md) - [Connector Lines](https://remotionui.com/docs/components/connector-lines.md) ## Machine-readable references - Props and usage as JSON: https://remotionui.com/ai/components/globe-arc.json - Component index: https://remotionui.com/ai/components.json --- # Map Canvas > Deterministic MapLibre map mount. Source: https://remotionui.com/docs/components/map-canvas ## Installation ```bash npx remotion-ui@latest add map-canvas ``` Low-level MapLibre mount with `delayRender` until the map is idle. Use as the foundation for custom map animations. ## Usage ```tsx import { MapCanvas } from "@/remotion/primitives/map-canvas"; <MapCanvas center={[8.54, 47.38]} zoom={7} onMapReady={setMap} /> ``` Advanced. Installs maplibre-gl. Render with --gl=angle --concurrency=1. ## Props | Name | Type | Default | Description | | --- | --- | --- | --- | | `center` (required) | `[number, number]` | - | Map center [lng, lat]. | | `zoom` | `number` | `7` | Initial zoom level. | | `onMapReady` | `(map: Map) => void` | - | Called when map is idle. | ## Related - [Map Route](https://remotionui.com/docs/components/map-route.md) - [Map Flight](https://remotionui.com/docs/components/map-flight.md) ## Machine-readable references - Props and usage as JSON: https://remotionui.com/ai/components/map-canvas.json - Component index: https://remotionui.com/ai/components.json --- # Map Flight > Animated map flyover with route reveal and markers. Source: https://remotionui.com/docs/components/map-flight ## Installation ```bash npx remotion-ui@latest add map-flight ``` The docs preview is a stylized stand-in. The installed scene uses MapLibre + Turf with real tiles and camera flyover. ## Usage ```tsx import { MapFlight } from "@/remotion/scenes/map-flight"; <MapFlight from={[8.54, 47.38]} to={[-74, 40.71]} fromLabel="Zurich" toLabel="New York" /> ``` Render with npx remotion render --gl=angle --concurrency=1. ## Props | Name | Type | Default | Description | | --- | --- | --- | --- | | `from` | `[number, number]` | - | Start coordinates [lng, lat]. | | `to` | `[number, number]` | - | End coordinates [lng, lat]. | | `fromLabel` | `string` | - | Start marker label. | | `toLabel` | `string` | - | End marker label. | ## Related - [Map Canvas](https://remotionui.com/docs/components/map-canvas.md) - [Map Route](https://remotionui.com/docs/components/map-route.md) - [Map Markers](https://remotionui.com/docs/components/map-markers.md) ## Machine-readable references - Props and usage as JSON: https://remotionui.com/ai/components/map-flight.json - Component index: https://remotionui.com/ai/components.json --- # Map Heat Overlay > A density overlay fading in over the basemap, with the hot cores arriving last. Source: https://remotionui.com/docs/components/map-heat-overlay ## Installation ```bash npx remotion-ui@latest add map-heat-overlay ``` Pass it the map from `MapCanvas`'s `onMapReady` and a point collection, and it adds a heatmap layer that fades up. Intensity climbs with the fade rather than sitting at its final value, so the hot cores arrive last and the density reads as accumulating instead of being there from the first frame at low alpha. Like every MapLibre primitive here, the paint holds the frame open with its own `delayRender`. Layers are added a commit after the map reports ready, and without the hold the overlay drops out of whichever frame the browser captures first, reliably the first sample of a still run, which then shows a bare basemap and looks like a broken component. Two settings decide whether this reads as data or as a smear. `radius` is in screen pixels, so it ramps with zoom. Otherwise the same overlay means different things at different camera heights. And it wants to stay small: roughly 12–24 for a few hundred points. Too large and every point merges into one saturated blob with no density left to read. The first colour stop must be transparent. A heatmap ramp is painted across the whole layer, so an opaque density-zero colour floods the entire viewport rather than showing the hot spots. `beforeLayerId` slides the overlay under a basemap layer, which is how you keep place labels legible through the heat. ## Usage ```tsx import { MapCanvas } from "@/remotion/primitives/map-canvas"; import { MapHeatOverlay } from "@/remotion/primitives/map-heat-overlay"; const [map, setMap] = useState<Map | null>(null); <AbsoluteFill> <MapCanvas center={[2.2, 49.6]} zoom={4} onMapReady={setMap} /> <MapHeatOverlay map={map} points={points} radius={18} /> </AbsoluteFill> ``` The paint holds the frame open with its own delayRender: layers are added a commit after the map reports ready, and without the hold the overlay drops out of the first captured frame and the still shows a bare basemap. Intensity climbs with the fade so hot cores arrive last. The first colour stop must be transparent: a heatmap ramp paints across the whole layer, so an opaque density-zero colour floods the viewport. ## Props | Name | Type | Default | Description | | --- | --- | --- | --- | | `map` | `Map \| null` | - | The map to paint on, from MapCanvas's onMapReady. | | `points` | `FeatureCollection<Point>` | - | Points to weigh. | | `weightProperty` | `string` | `"weight"` | Feature property holding each point's weight. | | `radius` | `number` | `18` | Kernel radius in screen pixels at radiusZoom. Roughly 12–24 for a few hundred points. | | `radiusZoom` | `number` | `3` | The zoom the radius is authored at; it ramps from there. | | `intensity` | `number` | `0.85` | Peak opacity once the overlay has faded up. | | `colors` | `string[]` | `5-stop cool-to-hot ramp` | Density ramp, low first. The first stop must be transparent. | | `beforeLayerId` | `string` | - | Layer to sit under, so place labels stay legible through the heat. | | `sourceId` | `string` | `"heat-points"` | Source and layer id prefix, for more than one overlay on a map. | | `revealProgress` | `number` | - | Drive the fade yourself, 0–1. Omit for the built-in frame ramp. | ## Related - [Map Canvas](https://remotionui.com/docs/components/map-canvas.md) - [Map Markers](https://remotionui.com/docs/components/map-markers.md) - [Heatmap Grid](https://remotionui.com/docs/components/heatmap-grid.md) ## Machine-readable references - Props and usage as JSON: https://remotionui.com/ai/components/map-heat-overlay.json - Component index: https://remotionui.com/ai/components.json --- # Map Markers > GeoJSON circle and label markers on a map. Source: https://remotionui.com/docs/components/map-markers ## Installation ```bash npx remotion-ui@latest add map-markers ``` Adds circle and symbol label layers for GeoJSON point features on a MapLibre map. ## Usage ```tsx import { MapMarkers } from "@/remotion/primitives/map-markers"; <MapMarkers map={map} markers={markerCollection} /> ``` ## Props | Name | Type | Default | Description | | --- | --- | --- | --- | | `map` (required) | `Map \| null` | - | MapLibre map instance. | | `markers` (required) | `FeatureCollection<Point>` | - | GeoJSON points with name property. | ## Related - [Map Flight](https://remotionui.com/docs/components/map-flight.md) ## Machine-readable references - Props and usage as JSON: https://remotionui.com/ai/components/map-markers.json - Component index: https://remotionui.com/ai/components.json --- # Map Route > Animated GeoJSON route line on a map. Source: https://remotionui.com/docs/components/map-route ## Installation ```bash npx remotion-ui@latest add map-route ``` Animates a GeoJSON line reveal on an existing MapLibre instance. Pair with `map-canvas` or `map-flight`. ## Usage ```tsx import { MapRoute } from "@/remotion/primitives/map-route"; <MapRoute map={map} route={targetRoute} progress={0.5} /> ``` ## Props | Name | Type | Default | Description | | --- | --- | --- | --- | | `map` (required) | `Map \| null` | - | MapLibre map instance. | | `route` (required) | `Feature<LineString>` | - | GeoJSON line to animate. | | `progress` | `number` | - | Route reveal progress 0–1. | ## Related - [Map Flight](https://remotionui.com/docs/components/map-flight.md) - [map-utils](https://remotionui.com/docs/components/map-utils.md) ## Machine-readable references - Props and usage as JSON: https://remotionui.com/ai/components/map-route.json - Component index: https://remotionui.com/ai/components.json --- # Multi-Device Lineup > Phone, tablet and laptop showing one responsive design, arriving in order. Source: https://remotionui.com/docs/components/multi-device-lineup ## Installation ```bash npx remotion-ui@latest add multi-device-lineup ``` Three devices land in order, smallest first. The laptop is the widest object and the thing a viewer ends up reading, so it arrives onto a lineup that already exists rather than being the thing everything else lands beside. Each screen is a real element at that device's own pixel size, not one screenshot scaled three ways. Pass the same `children` and whatever you render lays itself out per width, which is the only reason to show three devices at all. Give a device its own `content` when you want to show a different view on one of them. Hardware ratios are the real ones, and each device carries the detail that identifies it: the phone's speaker cutout, the tablet's camera dot, the laptop's base and hinge drawn as their own strip. A laptop rendered as a slab with rounded corners is the giveaway that a mockup was never looked at. `scale` sizes the whole lineup. It is the prop to reach for first when the lineup is wider than your frame: the devices divide a fixed width between them, so scaling the group is what keeps the phone from walking off the left edge. For a single device with a camera move into the screen, use `device-mockup-zoom`. ## Usage ```tsx import { MultiDeviceLineup } from "@/remotion/primitives/multi-device-lineup"; <MultiDeviceLineup scale={0.72} phone={{ label: "Phone" }} tablet={{ label: "Tablet" }} laptop={{ label: "Laptop" }} > <YourResponsiveScreen /> </MultiDeviceLineup> ``` Each screen is a real element at that device's own pixel size, not one screenshot scaled three ways: pass the same children and a responsive layout lays itself out per width, which is the only reason to show three devices. Devices land smallest first so the laptop arrives onto a lineup that already exists. Hardware ratios are the real ones, and the laptop's base and hinge are drawn as their own strip. For one device with a camera move into the screen, use device-mockup-zoom. ## Props | Name | Type | Default | Description | | --- | --- | --- | --- | | `children` | `ReactNode` | - | Rendered inside every device that has no content of its own: one responsive design at three widths. | | `phone` | `LineupScreen` | - | Optional content and caption for the phone. | | `tablet` | `LineupScreen` | - | Optional content and caption for the tablet. | | `laptop` | `LineupScreen` | - | Optional content and caption for the laptop. | | `scale` | `number` | `1` | Overall size of the lineup. The first prop to reach for when it is wider than the frame. | | `delayInFrames` | `number` | `4` | Frame the first device arrives. | | `staggerInFrames` | `number` | `9` | Frames between devices. | | `exitAtInFrames` | `number` | - | Frame the lineup starts leaving. Omit to leave it on screen. | | `exitInFrames` | `number` | `16` | Frames the exit takes. | | `bezelColor` | `string` | `"#15171D"` | Device body. | | `screenColor` | `string` | `"#0B0C11"` | Screen behind your content. | | `labelColor` | `string` | `"#7A828F"` | Captions under the devices. | ## Related - [Device Mockup Zoom](https://remotionui.com/docs/components/device-mockup-zoom.md) - [Tab Switch Panel](https://remotionui.com/docs/components/tab-switch-panel.md) - [Notification Stack](https://remotionui.com/docs/components/notification-stack.md) ## Machine-readable references - Props and usage as JSON: https://remotionui.com/ai/components/multi-device-lineup.json - Component index: https://remotionui.com/ai/components.json --- # 3D > Lit WebGL scenes built on @remotion/three, rendered deterministically frame by frame. Source: https://remotionui.com/docs/components/3d 3D components are real React Three Fiber scenes: modelled geometry, image-based lighting and contact shadows, with every move driven by the frame number so a render is identical on every run. Render them with `--gl=angle`. ## Components - [Device Mockup 3D](https://remotionui.com/docs/components/device-mockup-3d.md): Laptop product shot in real 3D. The lid opens, then the camera turns and pushes in over a lit floor. - [Product Turntable 3d](https://remotionui.com/docs/components/product-turntable-3d.md): A product on a studio turntable: the model turns a full revolution under a soft key and rim while the camera holds, with a contact shadow anchoring it to the floor. Install with npx remotion-ui@latest add product-turntable-3d. - [Text Extrude 3d](https://remotionui.com/docs/components/text-extrude-3d.md): Extruded 3D headline with a lit bevel: the letters rise and settle as the camera pulls back across them. Install with npx remotion-ui@latest add text-extrude-3d. - [Card Stack 3d](https://remotionui.com/docs/components/card-stack-3d.md): A stack of physical cards fanning out in depth, each with real thickness and an edge highlight, turning to face the camera. Install with npx remotion-ui@latest add card-stack-3d. - [Globe Points 3d](https://remotionui.com/docs/components/globe-points-3d.md): Lit sphere with instanced city markers and arcs rising between them, turning slowly under a rim light. Install with npx remotion-ui@latest add globe-points-3d. --- # Device Mockup 3D > Laptop product shot in real 3D. The lid opens, then the camera turns and pushes in over a lit floor. Source: https://remotionui.com/docs/components/device-mockup-3d ## Installation ```bash npx remotion-ui@latest add device-mockup-3d ``` A modelled laptop (hinged lid, black glass bezel with a camera dot, keyboard and trackpad) lit by a studio environment built on the spot. It settles onto a lit floor as the lid opens, then turns and pushes in. A slow drift runs under the whole shot, so the last frame is still moving rather than parked. The glass over the screen only adds reflection, so your screenshot is never dimmed: the streaks come from fixed studio lights and slide across as the laptop turns. The shadow falls on a lit pool rather than straight onto the backdrop, where a dark shadow would disappear. Pass `src` with a bright screenshot: a dark UI still reads, but a mostly black image turns the screen into a slab. The screen takes the image's own ratio unless you set `screenAspect`. The shot paces itself to the composition length; 4–6 seconds suits it. Render with `--gl=angle`. Motion comes from the frame only and the screen image loads behind `delayRender`, so the same frame renders to identical pixels every time. For a CSS mockup with a staged UI and no WebGL, use `device-mockup-zoom`. ## Usage ```tsx import { staticFile } from "remotion"; import { DeviceMockup3D } from "@/remotion/scenes/device-mockup-3d"; // Render with --gl=angle <DeviceMockup3D src={staticFile("app.png")} /> ``` A lit WebGL scene on @remotion/three; render with --gl=angle. The shot paces itself to the composition length: the laptop settles as the lid opens, then turns and pushes in, with a slow drift under both so the last frame never parks. Deterministic by construction: motion comes only from useCurrentFrame(), the screen image loads behind delayRender, and the environment is built from Lightformers instead of a CDN HDRI. For a CSS mockup with staged UI and no WebGL, use device-mockup-zoom. ## Props | Name | Type | Default | Description | | --- | --- | --- | --- | | `src` | `string` | `hosted demo screenshot` | Screenshot on the screen. A bright UI reads best; a mostly black image reads as a slab. | | `screenAspect` | `number` | - | Screen width / height. Omit to use the image's own ratio. | | `backgroundColor` | `string` | `"#0a0c11"` | Outer backdrop. | | `glowColor` | `string` | `"#1c212c"` | Soft glow behind the device. | | `floorColor` | `string` | `"#434a57"` | Lit floor pool the contact shadow falls on. Keep it lighter than the backdrop. | | `bodyColor` | `string` | `"#9ba1ab"` | Aluminium body. | | `rimColor` | `string` | `"#7aa2ff"` | Cool rim light from the left. | | `accentColor` | `string` | `"#ffb27a"` | Warm accent light from the right. | | `glare` | `number` | `1` | Strength of the glass reflection over the screen, 0–1. | ## Related - [Device Mockup Zoom](https://remotionui.com/docs/components/device-mockup-zoom.md) - [Multi-Device Lineup](https://remotionui.com/docs/components/multi-device-lineup.md) ## Machine-readable references - Props and usage as JSON: https://remotionui.com/ai/components/device-mockup-3d.json - Component index: https://remotionui.com/ai/components.json --- # Product Turntable 3d > A product on a studio turntable: the model turns a full revolution under a soft key and rim while the camera holds, with a contact shadow anchoring it to the floor. Install with npx remotion-ui@latest add product-turntable-3d. Source: https://remotionui.com/docs/components/product-turntable-3d ## Installation ```bash npx remotion-ui@latest add product-turntable-3d ``` A product on a studio turntable: the model turns a full revolution under a soft key and rim while the camera holds, with a contact shadow anchoring it to the floor. Takes a GLTF via prop and falls back to a built-in primitive, so it is the generic product shot device-mockup-3d is not. ## Usage ```tsx import { ProductTurntable3d } from "@/remotion/scenes/product-turntable-3d"; <ProductTurntable3d /> ``` ## Usage ```tsx import { ProductTurntable3d } from "@/remotion/scenes/product-turntable-3d"; <ProductTurntable3d /> ``` ## Props | Name | Type | Default | Description | | --- | --- | --- | --- | | `delayInFrames` | `number` | `0` | Frames to wait before this starts. | | `durationInFrames` | `number` | `30` | Length of the entrance. | ## Machine-readable references - Props and usage as JSON: https://remotionui.com/ai/components/product-turntable-3d.json - Component index: https://remotionui.com/ai/components.json --- # Text Extrude 3d > Extruded 3D headline with a lit bevel: the letters rise and settle as the camera pulls back across them. Install with npx remotion-ui@latest add text-extrude-3d. Source: https://remotionui.com/docs/components/text-extrude-3d ## Installation ```bash npx remotion-ui@latest add text-extrude-3d ``` Extruded 3D headline with a lit bevel: the letters rise and settle as the camera pulls back across them. Distinct from stroke-to-fill-text and the other atoms, which are flat SVG or DOM type with no real depth or lighting. ## Install the typeface The scene extrudes real glyphs, so it needs a three.js typeface JSON. `add text-extrude-3d` copies the component but **not** the font — download [geist-bold.typeface.json](https://remotionui.com/fonts/geist-bold.typeface.json) (Geist, SIL OFL 1.1) into your `public/fonts/`, or convert your own face with [facetype.js](https://gero3.github.io/facetype.js/) and point `fontUrl` at it. ## Usage ```tsx import { TextExtrude3d } from "@/remotion/scenes/text-extrude-3d"; <TextExtrude3d /> // Your own face: <TextExtrude3d text="LAUNCH" fontUrl={staticFile("fonts/my-brand.typeface.json")} /> ``` ## Usage ```tsx import { TextExtrude3d } from "@/remotion/scenes/text-extrude-3d"; <TextExtrude3d /> ``` ## Props | Name | Type | Default | Description | | --- | --- | --- | --- | | `delayInFrames` | `number` | `0` | Frames to wait before this starts. | | `durationInFrames` | `number` | `30` | Length of the entrance. | ## Machine-readable references - Props and usage as JSON: https://remotionui.com/ai/components/text-extrude-3d.json - Component index: https://remotionui.com/ai/components.json --- # Card Stack 3d > A stack of physical cards fanning out in depth, each with real thickness and an edge highlight, turning to face the camera. Install with npx remotion-ui@latest add card-stack-3d. Source: https://remotionui.com/docs/components/card-stack-3d ## Installation ```bash npx remotion-ui@latest add card-stack-3d ``` A stack of physical cards fanning out in depth, each with real thickness and an edge highlight, turning to face the camera. The 3D counterpart to flat card reveals: the depth is geometry, not a CSS perspective trick. ## Usage ```tsx import { CardStack3d } from "@/remotion/scenes/card-stack-3d"; <CardStack3d /> ``` ## Usage ```tsx import { CardStack3d } from "@/remotion/scenes/card-stack-3d"; <CardStack3d /> ``` ## Props | Name | Type | Default | Description | | --- | --- | --- | --- | | `delayInFrames` | `number` | `0` | Frames to wait before this starts. | | `durationInFrames` | `number` | `30` | Length of the entrance. | ## Machine-readable references - Props and usage as JSON: https://remotionui.com/ai/components/card-stack-3d.json - Component index: https://remotionui.com/ai/components.json --- # Globe Points 3d > Lit sphere with instanced city markers and arcs rising between them, turning slowly under a rim light. Install with npx remotion-ui@latest add globe-points-3d. Source: https://remotionui.com/docs/components/globe-points-3d ## Installation ```bash npx remotion-ui@latest add globe-points-3d ``` Lit sphere with instanced city markers and arcs rising between them, turning slowly under a rim light. The real-3D counterpart to the flat globe-arc projection, with genuine occlusion as markers pass behind the horizon. ## Install the map data The dot matrix is cut from real coastlines, so it needs a GeoJSON land file. `add globe-points-3d` copies the component but **not** the data — download [land-110m.json](https://remotionui.com/geo/land-110m.json) (Natural Earth 1:110m, public domain, 75 KB) into your `public/geo/`, or point `landUrl` at any GeoJSON FeatureCollection, Feature or `MultiPolygon` of land in lng/lat degrees. Without it the render stops with an actionable error rather than quietly drawing a bare blue ball. ## Usage ```tsx import { GlobePoints3d } from "@/remotion/scenes/globe-points-3d"; <GlobePoints3d /> // Your own polygons: <GlobePoints3d landUrl={staticFile("geo/my-land.json")} /> ``` ## Usage ```tsx import { GlobePoints3d } from "@/remotion/scenes/globe-points-3d"; <GlobePoints3d /> ``` ## Props | Name | Type | Default | Description | | --- | --- | --- | --- | | `delayInFrames` | `number` | `0` | Frames to wait before this starts. | | `durationInFrames` | `number` | `30` | Length of the entrance. | ## Machine-readable references - Props and usage as JSON: https://remotionui.com/ai/components/globe-points-3d.json - Component index: https://remotionui.com/ai/components.json --- # Shaders > Full-frame GPU fields, evaluated per pixel and driven by the frame number. Source: https://remotionui.com/docs/components/shaders Shader components paint the whole frame on the GPU: the value of every pixel is computed from the frame number, so there is no entrance to run out and no loop point to land on. They suit backgrounds and ambient layers under type. Each one is deterministic by construction. The underlying shader library animates itself off a wall clock, which would make a render sample a different moment on every run; these wrappers stop that clock and set the time from `useCurrentFrame()` instead. Render them with `--gl=angle`. A live preview costs one WebGL context, so pages mount them on hover rather than all at once. ## Components - [Dither Field Background](https://remotionui.com/docs/components/dither-field-bg.md): A two-colour ordered-dither field, quantised to a pixel grid. - [Warp Bands Background](https://remotionui.com/docs/components/warp-bands-bg.md): Colour bands folded through noise and a swirl, smoke, ink, or marble. - [Grain Gradient Background](https://remotionui.com/docs/components/grain-gradient-bg.md): A multi-colour gradient with grain worked through it. - [Light Tunnel Background](https://remotionui.com/docs/components/light-tunnel-bg.md): Flight down a twisting barrel of light, with a defocused vanishing point. - [Text Reveal Shader](https://remotionui.com/docs/components/text-reveal-shader.md): Words condensing out of light into liquid chrome. --- # Dither Field Background > A two-colour ordered-dither field, quantised to a pixel grid. Source: https://remotionui.com/docs/components/dither-field-bg ## Installation ```bash npx remotion-ui@latest add dither-field-bg ``` A smooth pattern pushed through a dither matrix, so it resolves into two colours on a pixel grid rather than a gradient. It reads as print halftone or an early bitmap display, and it is the one background here that holds an edge: the grid gives type something to sit against. `shape` picks the pattern underneath and `pattern` picks the threshold matrix: the Bayer sizes are ordered and regular, `random` is white noise and reads as film grain. The shapes split in two. `simplex`, `warp`, `dots` and `wave` tile and fill the frame at any scale, use these for a background. `ripple`, `swirl` and `sphere` are bounded shapes with an edge, so below `scale={1}` they sit as an object in an empty field rather than covering it. `pixelSize` is measured in real pixels and deliberately ignores `scale`, so zooming moves the pattern underneath a grid that stays put. Raise it for a coarser, more obviously digital field; at `1` the dither almost disappears. Render with `--gl=angle`. Motion comes from the frame only, so the same frame renders to identical pixels every time. ## Usage ```tsx import { DitherFieldBg } from "@/remotion/primitives/dither-field-bg"; // Render with --gl=angle <DitherFieldBg shape="warp" pattern="4x4" /> ``` The dither grid is measured in real pixels and ignores scale, so zooming moves the pattern underneath a grid that stays put. Deterministic by construction: the shader library's own requestAnimationFrame clock is switched off and the time is set from useCurrentFrame(). Render with --gl=angle. ## Props | Name | Type | Default | Description | | --- | --- | --- | --- | | `backgroundColor` | `string` | `"#070605"` | The unlit half of the two-tone field. | | `inkColor` | `string` | `"#e4ac59"` | The lit half. The field only ever holds these two colors. | | `shape` | `"simplex" \| "warp" \| "dots" \| "wave" \| "ripple" \| "swirl" \| "sphere"` | `"warp"` | Pattern the dither is sampled from before the grid quantises it. simplex, warp, dots and wave fill the frame; ripple, swirl and sphere are bounded shapes. | | `pattern` | `"random" \| "2x2" \| "4x4" \| "8x8"` | `"4x4"` | Threshold matrix. Bayer sizes are ordered; random reads as film grain. | | `pixelSize` | `number` | `2` | Size of one dither cell in pixels, 0.5–20. Larger reads more retro. | | `scale` | `number` | `1` | Zoom on the underlying pattern, 0.01–4. Below 1 a bounded shape stops covering the frame. | | `speed` | `number` | `1` | Multiplies how far the field travels per second. | ## Related - [Grain Gradient Background](https://remotionui.com/docs/components/grain-gradient-bg.md) - [Warp Bands Background](https://remotionui.com/docs/components/warp-bands-bg.md) - [Animated Noise Grain](https://remotionui.com/docs/components/animated-noise-grain.md) ## Machine-readable references - Props and usage as JSON: https://remotionui.com/ai/components/dither-field-bg.json - Component index: https://remotionui.com/ai/components.json --- # Warp Bands Background > Colour bands folded through noise and a swirl, smoke, ink, or marble. Source: https://remotionui.com/docs/components/warp-bands-bg ## Installation ```bash npx remotion-ui@latest add warp-bands-bg ``` Up to ten colours laid over a base pattern, then folded by noise and a swirl. What it looks like is mostly `softness`: at `0` the bands stay legible ribbons, at `1` they melt into one continuous field of smoke or ink. `swirl` and `swirlIterations` control the folding. More passes fold the bands back through themselves and push it toward marble. `distortion` roughens the edges without folding them. Keep a dark colour in the list. The bands blend in order, and an all-bright set loses the separation that makes the motion readable under type. Render with `--gl=angle`. The field has no entrance and no loop point; it is the same motion at every point in the composition. ## Usage ```tsx import { WarpBandsBg } from "@/remotion/primitives/warp-bands-bg"; // Render with --gl=angle <WarpBandsBg softness={1} swirl={0.8} /> ``` No entrance and no loop point: the same motion at every point in the composition, so any window shows it. Deterministic by construction: the library's wall clock is switched off and the time is set from useCurrentFrame(). Render with --gl=angle. ## Props | Name | Type | Default | Description | | --- | --- | --- | --- | | `colors` | `string[]` | `["#0b0a08", "#e4ac59", "#0b0a08", "#c2557a"]` | Up to 10 colors, blended in order. Keep a dark one to hold the bands apart. | | `pattern` | `"checks" \| "stripes" \| "edge"` | `"checks"` | Base pattern the bands are laid over before distortion. | | `proportion` | `number` | `0.45` | Where one color gives way to the next, 0–1. | | `softness` | `number` | `1` | Edge hardness, 0 = hard band, 1 = full gradient. Changes its character most. | | `distortion` | `number` | `0.25` | Noise distortion across the bands, 0–1. | | `swirl` | `number` | `0.8` | Swirl strength, 0–1. This is what makes the bands read as marble. | | `swirlIterations` | `number` | `10` | Layered swirl passes, 0–20. More passes, more folding. | | `patternScale` | `number` | `0.1` | Zoom on the base pattern, 0–1. | | `scale` | `number` | `1` | Overall zoom, 0.01–4. | | `rotation` | `number` | `0` | Rotation of the whole field in degrees. | | `speed` | `number` | `1` | Multiplies how far the field travels per second. | ## Related - [Grain Gradient Background](https://remotionui.com/docs/components/grain-gradient-bg.md) - [Dither Field Background](https://remotionui.com/docs/components/dither-field-bg.md) - [Mesh Gradient Background](https://remotionui.com/docs/components/mesh-gradient-bg.md) ## Machine-readable references - Props and usage as JSON: https://remotionui.com/ai/components/warp-bands-bg.json - Component index: https://remotionui.com/ai/components.json --- # Grain Gradient Background > A multi-colour gradient with grain worked through it. Source: https://remotionui.com/docs/components/grain-gradient-bg ## Installation ```bash npx remotion-ui@latest add grain-gradient-bg ``` A gradient in one of seven shapes (`wave`, `blob`, `ripple`, `dots`, `truchet`, `corners`, `sphere`), with grain mixed through the colour rather than layered over it. The grain is the point. A shallow ramp crossing a wide frame has only about fifty usable 8-bit levels and plateaus into visible bands wherever it is composited; noise breaks those plateaus up. Set `noise` to `0` and the banding comes back. Like the dither grid, it is measured in real pixels and ignores `scale`. Distinct from `mesh-gradient-bg`, which is three drifting blobs composited on the GPU, and from `animated-noise-grain`, which is a grain overlay with no gradient of its own. Render with `--gl=angle`. ## Usage ```tsx import { GrainGradientBg } from "@/remotion/primitives/grain-gradient-bg"; // Render with --gl=angle <GrainGradientBg shape="wave" noise={0.35} /> ``` The grain is the point: a shallow ramp across a wide frame has only ~48 usable 8-bit levels and plateaus into visible bands, and noise is what breaks them up; set noise to 0 and the banding returns. Distinct from mesh-gradient-bg (three drifting blobs) and animated-noise-grain (a grain overlay with no gradient). Render with --gl=angle. ## Props | Name | Type | Default | Description | | --- | --- | --- | --- | | `backgroundColor` | `string` | `"#050505"` | Stage the shape sits on. | | `colors` | `string[]` | `["#e4ac59", "#e07a5f", "#f0c98a"]` | Up to 7 colors, blended across the shape. | | `shape` | `"wave" \| "dots" \| "truchet" \| "corners" \| "ripple" \| "blob" \| "sphere"` | `"wave"` | The form the gradient takes. Each is a different field, not a preset. | | `softness` | `number` | `0.6` | Edge hardness between colors, 0 = posterised, 1 = smooth. | | `intensity` | `number` | `0.45` | Distortion between the color bands, 0–1. | | `noise` | `number` | `0.35` | Grain overlay, 0–1. Measured in real pixels, so it ignores scale. | | `scale` | `number` | `1` | Overall zoom, 0.01–4. | | `speed` | `number` | `1` | Multiplies how far the field travels per second. | ## Related - [Mesh Gradient Background](https://remotionui.com/docs/components/mesh-gradient-bg.md) - [Dither Field Background](https://remotionui.com/docs/components/dither-field-bg.md) - [Warp Bands Background](https://remotionui.com/docs/components/warp-bands-bg.md) ## Machine-readable references - Props and usage as JSON: https://remotionui.com/ai/components/grain-gradient-bg.json - Component index: https://remotionui.com/ai/components.json --- # Light Tunnel Background > Flight down a twisting barrel of light, with a defocused vanishing point. Source: https://remotionui.com/docs/components/light-tunnel-bg ## Installation ```bash npx remotion-ui@latest add light-tunnel-bg ``` A flat field remapped onto the inside of a cylinder. Depth comes from the reciprocal radius, so the wall rushes past as a pixel approaches the middle of the frame, and the angle comes from `atan` plus a twist coupled to that depth. This is the one background in the lane with a vanishing point. The others move across a flat plane, this one travels toward something. `ribbons` is rounded to an integer and that is not a convenience. The twist is added before the angle wraps, so a fractional repeat count leaves a hard seam running down the line where `atan` changes sign. Integer counts wrap cleanly and the barrel has no visible join. `ringDensity` places rings evenly in `log(r)` rather than in `r`. Spaced evenly in `r` they bunch into a solid bright mass at the centre and disappear at the rim; spaced logarithmically they hold roughly the same apparent width all the way in, which is what keeps the folds readable instead of smearing. `defocus` is the other half of that. `1/r` is singular at the exact centre of the frame, and the usual fix, clamping the radius, is also the usual tell: it leaves a flat disc with a hard rim parked in the vanishing point. Here a nine-tap Gaussian disk whose radius grows as `r` falls resolves the singularity the way a lens does, by losing focus. Set it to `0` to see what the clamp would have looked like. Hue is keyed to the ribbon index rather than to the clock, so a ribbon keeps its colour for the whole flight. Driving hue from depth instead makes the entire barrel cycle through the palette as you travel, which reads as a screensaver. Render with `--gl=angle`. Motion comes from the frame only, so the same frame renders to identical pixels every time. ## Usage ```tsx import { LightTunnelBg } from "@/remotion/primitives/light-tunnel-bg"; // Render with --gl=angle <LightTunnelBg ribbons={14} twist={0.16} /> ``` Depth comes from the reciprocal radius and the angle from atan plus a depth-coupled twist, so this is the one background in the lane with a vanishing point. Two details carry it: rings are spaced evenly in log(r) rather than r, which keeps the folds the same apparent width all the way in instead of bunching at the centre; and the singularity at r=0 is resolved by a nine-tap Gaussian defocus that grows as the wall recedes, rather than by clamping the radius, which leaves a flat disc with a hard rim in the vanishing point. Hue is keyed to the ribbon index rather than the clock, so a ribbon keeps its colour instead of the barrel cycling. Render with --gl=angle. ## Props | Name | Type | Default | Description | | --- | --- | --- | --- | | `backgroundColor` | `string` | `"#050505"` | Plate behind the tunnel, and the colour the far centre falls off to. | | `colors` | `[string, string, string]` | `["#e4ac59", "#e07a5f", "#c2557a"]` | Three ribbon tints, distributed around the barrel by ribbon index. | | `ribbons` | `number` | `12` | How many ribbons run down the barrel. Rounded to an integer: a fractional count leaves a seam where the angle wraps. | | `twist` | `number` | `0.22` | How hard the barrel twists with depth. 0 gives straight ribbons. | | `ringDensity` | `number` | `3.2` | Rings per unit of log-depth. Higher packs the folds tighter. | | `defocus` | `number` | `0.035` | Radius of the centre defocus, in frame heights. 0 leaves the vanishing point sharp. | | `intensity` | `number` | `1` | Overall brightness. | | `speed` | `number` | `1` | Flight speed down the barrel. 0 freezes the tunnel. | ## Related - [Mesh Gradient Background](https://remotionui.com/docs/components/mesh-gradient-bg.md) - [Warp Bands Background](https://remotionui.com/docs/components/warp-bands-bg.md) - [Light Rays](https://remotionui.com/docs/components/light-rays.md) ## Machine-readable references - Props and usage as JSON: https://remotionui.com/ai/components/light-tunnel-bg.json - Component index: https://remotionui.com/ai/components.json --- # Text Reveal Shader > Words condensing out of light into liquid chrome. Source: https://remotionui.com/docs/components/text-reveal-shader ## Installation ```bash npx remotion-ui@latest add text-reveal-shader ``` The copy is rasterised once to an alpha texture and handed to a fragment shader as its source, so the shader reads glyph coverage and generates everything else per pixel. That is what buys the refraction: a CSS or SVG mask can uncover letterforms but cannot bend them through a moving film, because it has no access to the pixels either side of the edge it is drawing. The reveal is a diagonal sweep whose threshold is perturbed by two crossed sines, one running in x and one in y at unrelated periods. One sine alone gives a wavy line that still reads as a machine wipe; crossing two breaks the repeat and the edge reads as a wet meniscus pulling across the letters. `wobble` sets how hard they bend it, and `0` gives a straight wipe. Two values carry the look, and they are where to spend time tuning: `bandWidth` is the width of a narrow exponential band pinned to the edge. Inside it the glyph is refracted, with the displacement taken from differences between channels of the iridescent field, so the offset follows whatever the film is doing locally rather than pushing in a fixed direction, and the three channels are sampled at decreasing strength to disperse the edge into colour. Widen it and the effect becomes a general blur; narrow it and it reads as a clean chromatic rim. `settle` is how long after the edge has passed the glyph interior takes to relax from the live iridescent field to flat silver. This is what makes the words read as condensing out of light rather than as light-coloured type being uncovered. Set it high and the letters never stop shimmering; set it near zero and they snap to chrome the instant the edge clears them. `delay` and `duration` are in frames. The face is worth pinning explicitly via `fontFamily`: the glyphs become a texture, so an unpinned system stack resolves differently on a dev machine and a render worker. Distinct from `masked-slide-reveal`, which slides a hard-edged mask over type, and from `light-sweep-text`, which passes a specular highlight across glyphs that are already fully visible. Render with `--gl=angle`. Motion comes from the frame only, so the same frame renders to identical pixels every time. ## Usage ```tsx import { TextRevealShader } from "@/remotion/primitives/text-reveal-shader"; // Render with --gl=angle <TextRevealShader text={"LIQUID\nCHROME"} bandWidth={0.022} settle={0.16} /> ``` The type is rasterised once to an alpha texture and handed to a fragment shader as its source, which is what buys the refraction: a CSS or SVG mask can uncover letterforms but cannot bend them through a moving film, having no access to the pixels either side of its edge. The reveal threshold is perturbed by two crossed sines at unrelated periods so the edge reads as a wet meniscus rather than a wipe. bandWidth and settle are where the taste lives. Distinct from masked-slide-reveal (hard-edged mask over type) and light-sweep-text (specular pass over already-visible glyphs). Render with --gl=angle. ## Props | Name | Type | Default | Description | | --- | --- | --- | --- | | `text` | `string` | `"LIQUID\nCHROME"` | Copy to reveal. Newlines start a new line; the block stays centred. | | `backgroundColor` | `string` | `"#050505"` | Plate behind the words. | | `colors` | `[string, string]` | `["#e4ac59", "#f0abc0"]` | The two ends of the iridescent film the words condense out of. | | `silverColor` | `string` | `"#ded8cf"` | Colour the glyph interior settles to once the edge has passed. | | `angle` | `number` | `34` | Direction of the sweep, in degrees. 0 sweeps left to right. | | `delay` | `number` | `0` | Frame the reveal starts on. | | `duration` | `number` | `78` | How many frames the sweep takes to cross the frame. | | `wobble` | `number` | `0.06` | How far the two crossed sines bend the edge. 0 gives a straight wipe. | | `bandWidth` | `number` | `0.022` | Width of the refracting band at the edge, in frame widths. Wider becomes a general blur; narrower reads as a clean chromatic rim. | | `refraction` | `number` | `0.055` | How far the band displaces the glyph. | | `settle` | `number` | `0.16` | How long after the edge the interior takes to settle to flat silver. | | `fontSize` | `number` | `170` | Type size in px, measured against the composition height. | | `fontWeight` | `number` | `800` | Weight passed to the canvas rasteriser. | | `fontFamily` | `string` | `"system-ui, -apple-system, Segoe UI, Roboto, sans-serif"` | Worth pinning explicitly: the glyphs become a texture, so an unpinned stack resolves differently on a dev box and a render worker. | | `letterSpacing` | `number` | `4` | Extra tracking in px. | | `lineHeight` | `number` | `1.02` | Line height as a multiple of the type size. | ## Related - [Masked Slide Reveal](https://remotionui.com/docs/components/masked-slide-reveal.md) - [Light Sweep Text](https://remotionui.com/docs/components/light-sweep-text.md) - [Grain Gradient Background](https://remotionui.com/docs/components/grain-gradient-bg.md) ## Machine-readable references - Props and usage as JSON: https://remotionui.com/ai/components/text-reveal-shader.json - Component index: https://remotionui.com/ai/components.json --- # AI composers > Scenes that recreate AI chat and coding tools, with messages that type out on cue. Source: https://remotionui.com/docs/components/ai-composers AI composer scenes recreate the look of chat and coding assistants. You pass the conversation and they type it out, which suits product demos and launch videos. ## Components - [ChatGPT](https://remotionui.com/docs/components/chat-gpt.md): ChatGPT composer scene for Remotion. - [Claude Chat](https://remotionui.com/docs/components/claude-chat.md): Claude chat composer scene for Remotion. - [Claude Code](https://remotionui.com/docs/components/claude-code.md): Claude Code terminal scene for Remotion. - [OpenCode](https://remotionui.com/docs/components/opencode.md): OpenCode TUI composer scene for Remotion. - [v0](https://remotionui.com/docs/components/v0.md): v0 builder composer scene for Remotion. --- # ChatGPT > ChatGPT composer scene for Remotion. Source: https://remotionui.com/docs/components/chat-gpt ## Installation ```bash npx remotion-ui@latest add chat-gpt ``` Animated ChatGPT composer with greeting, suggestion chips, and voice-to-send morph. ## Usage ```tsx import { ChatGpt } from "@/remotion/scenes/chat-gpt"; <ChatGpt prompt="Make a sunset over a calm ocean" /> ``` ## Props | Name | Type | Default | Description | | --- | --- | --- | --- | | `greeting` | `string` | `"What's on your mind today?"` | Headline above the composer. | | `placeholder` | `string` | `"Ask anything"` | Empty input placeholder. | | `prompt` | `string` | `"Make a sunset over the ocean"` | Prompt typed into the ChatGPT composer. | | `accentColor` | `string` | `"#2F6FED"` | Voice button color before it morphs to send. | | `theme` | `"light" \| "dark"` | `"light"` | Light or dark surface palette. | | `speed` | `number` | `1` | Animation speed multiplier. | ## Related - [Claude Chat](https://remotionui.com/docs/components/claude-chat.md) - [v0](https://remotionui.com/docs/components/v0.md) - [Chat to Preview](https://remotionui.com/docs/components/chat-to-preview.md) ## Machine-readable references - Props and usage as JSON: https://remotionui.com/ai/components/chat-gpt.json - Component index: https://remotionui.com/ai/components.json --- # Claude Chat > Claude chat composer scene for Remotion. Source: https://remotionui.com/docs/components/claude-chat ## Installation ```bash npx remotion-ui@latest add claude-chat ``` Animated Claude chat composer with typed prompt and waveform-to-send morph. ## Usage ```tsx import { ClaudeChat } from "@/remotion/scenes/claude-chat"; <ClaudeChat prompt="Draft a launch tweet for our new release" /> ``` ## Props | Name | Type | Default | Description | | --- | --- | --- | --- | | `placeholder` | `string` | `"Try: draft an email · summarize a doc · plan your week"` | Empty composer placeholder text. | | `prompt` | `string` | `"Draft a launch tweet"` | Prompt typed into the composer. | | `modelName` | `string` | `"Opus 4.8"` | Model label in the toolbar. | | `modelTier` | `string` | `"Max"` | Tier label beside the model. | | `accentColor` | `string` | `"#D97757"` | Terracotta send button color. | | `theme` | `"light" \| "dark"` | `"light"` | Light or dark surface palette. | | `speed` | `number` | `1` | Animation speed multiplier. | ## Related - [ChatGPT](https://remotionui.com/docs/components/chat-gpt.md) - [v0](https://remotionui.com/docs/components/v0.md) - [Chat to Preview](https://remotionui.com/docs/components/chat-to-preview.md) ## Machine-readable references - Props and usage as JSON: https://remotionui.com/ai/components/claude-chat.json - Component index: https://remotionui.com/ai/components.json --- # Claude Code > Claude Code terminal scene for Remotion. Source: https://remotionui.com/docs/components/claude-code ## Installation ```bash npx remotion-ui@latest add claude-code ``` Animated Claude Code welcome terminal with what's-new panel and CLI prompt typing. ## Usage ```tsx import { ClaudeCode } from "@/remotion/scenes/claude-code"; <ClaudeCode prompt='edit src/theme.ts to add a dark mode toggle' /> ``` ## Props | Name | Type | Default | Description | | --- | --- | --- | --- | | `title` | `string` | `"Claude Code v2.0.0"` | Legend label on the dashed welcome box. | | `userName` | `string` | `"Meaghan"` | Welcome message name. | | `model` | `string` | `"Opus 4.8 • Max 20x"` | Active model label. | | `cwd` | `string` | `"/users/meaghan/code/apps"` | Working directory shown in the welcome panel. | | `placeholder` | `string` | `'Try "edit <filepath> to ..."'` | CLI prompt placeholder before typing. | | `prompt` | `string` | `"edit src/theme.ts to add a dark mode toggle"` | Command typed at the CLI prompt. | | `accentColor` | `string` | `"#D97757"` | Dashed border and highlight color. | | `theme` | `"light" \| "dark"` | `"dark"` | Light or dark terminal palette. | | `speed` | `number` | `1` | Animation speed multiplier. | ## Related - [Terminal Simulator](https://remotionui.com/docs/components/terminal-simulator.md) - [Code Reveal](https://remotionui.com/docs/components/code-reveal.md) - [OpenCode](https://remotionui.com/docs/components/opencode.md) ## Machine-readable references - Props and usage as JSON: https://remotionui.com/ai/components/claude-code.json - Component index: https://remotionui.com/ai/components.json --- # OpenCode > OpenCode TUI composer scene for Remotion. Source: https://remotionui.com/docs/components/opencode ## Installation ```bash npx remotion-ui@latest add opencode ``` Animated OpenCode TUI with wordmark, accent input bar, and agent status row. ## Usage ```tsx import { Opencode } from "@/remotion/scenes/opencode"; <Opencode query='"What is the tech stack of this project?"' /> ``` ## Props | Name | Type | Default | Description | | --- | --- | --- | --- | | `placeholder` | `string` | `"Ask anything... "` | Muted prefix before the typed query. | | `query` | `string` | `'"What is the tech stack of this project?"'` | Query typed after the placeholder. | | `agentName` | `string` | `"Build"` | Active agent label. | | `modelName` | `string` | `"Kimi K2.5"` | Model name in the status row. | | `provider` | `string` | `"Moonshot AI"` | Model provider label. | | `accentColor` | `string` | `"#2B7FFF"` | Left accent bar and agent color. | | `theme` | `"light" \| "dark"` | `"dark"` | Light or dark TUI palette. | | `speed` | `number` | `1` | Animation speed multiplier. | ## Related - [Claude Code](https://remotionui.com/docs/components/claude-code.md) - [Terminal Simulator](https://remotionui.com/docs/components/terminal-simulator.md) - [ChatGPT](https://remotionui.com/docs/components/chat-gpt.md) ## Machine-readable references - Props and usage as JSON: https://remotionui.com/ai/components/opencode.json - Component index: https://remotionui.com/ai/components.json --- # v0 > v0 builder composer scene for Remotion. Source: https://remotionui.com/docs/components/v0 ## Installation ```bash npx remotion-ui@latest add v0 ``` Animated v0 builder with model selectors and a mic-to-send morph. The prompt is typed, the send button presses, and the prompt rises into the thread with the reply dots pulsing under it: the beat is scheduled off the prompt length by `sendBeatAt`, so a longer prompt pushes the submit later instead of running past the end of the clip. The reference box is cropped to the greeting-plus-composer band rather than a full 1280x720 page, so the composer fills the frame at tile size. ## Usage ```tsx import { V0Composer } from "@/remotion/scenes/v0"; <V0Composer prompt="a landing page for my SaaS with pricing" /> ``` ## Props | Name | Type | Default | Description | | --- | --- | --- | --- | | `greeting` | `string` | `"What do you want to create?"` | Bold heading above the box. | | `placeholder` | `string` | `"Ask v0 to build…"` | Empty textarea placeholder. | | `prompt` | `string` | `"a landing page with pricing"` | Build prompt typed into the textarea. The send beat is scheduled off its length, so a long prompt pushes the submit later rather than overrunning the window. | | `modelName` | `string` | `"v0 Max"` | Model chip label in the toolbar. | | `projectName` | `string` | `"Project"` | Project selector label. | | `theme` | `"light" \| "dark"` | `"dark"` | Light or dark surface palette. | | `speed` | `number` | `1` | Animation speed multiplier. | ## Related - [Claude Chat](https://remotionui.com/docs/components/claude-chat.md) - [ChatGPT](https://remotionui.com/docs/components/chat-gpt.md) - [Chat to Preview](https://remotionui.com/docs/components/chat-to-preview.md) ## Machine-readable references - Props and usage as JSON: https://remotionui.com/ai/components/v0.json - Component index: https://remotionui.com/ai/components.json --- # Code & terminal > Code reveals, diffs, file trees, and terminal sessions. Source: https://remotionui.com/docs/components/code-and-terminal These scenes show code and command lines: highlighted reveals, animated diffs, commit graphs, and terminals that print output line by line. ## Components - [Code Accordion](https://remotionui.com/docs/components/code-accordion.md): Stepped walkthrough where each section opens, writes its code, and is checked off. - [Code Diff Wipe](https://remotionui.com/docs/components/code-diff-wipe.md): A patch landing line by line, removals collapse, additions open and write themselves in. - [Code Reveal](https://remotionui.com/docs/components/code-reveal.md): Editor window that writes a syntax-highlighted file, then focuses the lines that matter. - [Commit Graph](https://remotionui.com/docs/components/commit-graph.md): A branch graph that draws itself, every edge grows from its parent, and each commit pops the moment its line arrives. - [File Tree Reveal](https://remotionui.com/docs/components/file-tree-reveal.md): A project tree opening itself node by node, folders turning as their contents arrive. - [Terminal Simulator](https://remotionui.com/docs/components/terminal-simulator.md): A terminal window that types a command, streams build steps, and hands the prompt back. --- # Code Accordion > Stepped walkthrough where each section opens, writes its code, and is checked off. Source: https://remotionui.com/docs/components/code-accordion ## Installation ```bash npx remotion-ui@latest add code-accordion ``` Steps play in order: a section opens, writes its code, holds, then closes with a check as the next one takes over. Pass `activeIndex` to pin a single step open instead of walking the list. ## Usage ```tsx import { CodeAccordion } from "@/remotion/scenes/code-accordion"; <CodeAccordion sections={sections} /> ``` ## Props | Name | Type | Default | Description | | --- | --- | --- | --- | | `sections` | `AccordionSection[]` | - | Steps played in order; each has a title, code, and optional meta. | | `activeIndex` | `number` | - | Pins one step open instead of walking the list. | | `title` | `string` | `"Add it to your project"` | Label above the steps. | | `holdSeconds` | `number` | `0.75` | Seconds an opened step is held before it closes. | | `accentColor` | `string` | `"#E8B86D"` | Chevron, fill and glow color. | | `theme` | `"dark" \| "light"` | `"dark"` | Panel palette. | | `speed` | `number` | `1` | Animation speed multiplier. | ## Related - [Code Reveal](https://remotionui.com/docs/components/code-reveal.md) - [Code Diff Wipe](https://remotionui.com/docs/components/code-diff-wipe.md) ## Machine-readable references - Props and usage as JSON: https://remotionui.com/ai/components/code-accordion.json - Component index: https://remotionui.com/ai/components.json --- # Code Diff Wipe > A patch landing line by line, removals collapse, additions open and write themselves in. Source: https://remotionui.com/docs/components/code-diff-wipe ## Installation ```bash npx remotion-ui@latest add code-diff-wipe ``` Pass the file before and after the change. The scene diffs the two, then plays an apply front down the listing: removed lines redden, strike through and collapse as it passes; added lines open beneath it and write in. The header tallies the change as it goes. ## Usage ```tsx import { CodeDiffWipe } from "@/remotion/scenes/code-diff-wipe"; <CodeDiffWipe before={before} after={after} title="render.ts" /> ``` ## Props | Name | Type | Default | Description | | --- | --- | --- | --- | | `before` | `string` | - | Source before the patch. | | `after` | `string` | - | Source after the patch; the scene diffs the two. | | `title` | `string` | `"render.ts"` | Filename on the window header. | | `wipeSeconds` | `number` | `1.7` | Seconds the apply front takes to travel the file. | | `accentColor` | `string` | `"#E8B86D"` | Apply front and glow color. | | `theme` | `"dark" \| "light"` | `"dark"` | Editor palette. | | `speed` | `number` | `1` | Animation speed multiplier. | ## Related - [Code Reveal](https://remotionui.com/docs/components/code-reveal.md) - [Code Accordion](https://remotionui.com/docs/components/code-accordion.md) ## Machine-readable references - Props and usage as JSON: https://remotionui.com/ai/components/code-diff-wipe.json - Component index: https://remotionui.com/ai/components.json --- # Code Reveal > Editor window that writes a syntax-highlighted file, then focuses the lines that matter. Source: https://remotionui.com/docs/components/code-reveal ## Installation ```bash npx remotion-ui@latest add code-reveal ``` An editor writes the file in front of the viewer: characters land under a live caret, syntax colours as it goes, and once the listing is complete, the highlighted lines take focus while the rest recedes. ## Usage ```tsx import { CodeReveal } from "@/remotion/scenes/code-reveal"; <CodeReveal title="pipeline.ts" code={source} highlightedLines={[4, 5]} /> ``` ## Props | Name | Type | Default | Description | | --- | --- | --- | --- | | `code` | `string` | - | Source shown in the editor; surrounding blank lines are trimmed. | | `highlightedLines` | `number[]` | - | 1-based lines focused once the listing finishes writing. | | `title` | `string` | `"explainer.tsx"` | Filename on the editor tab. | | `language` | `string` | `"tsx"` | Language badge on the right of the header. | | `startLine` | `number` | `1` | First line number in the gutter, for excerpts. | | `showLineNumbers` | `boolean` | `true` | Shows the gutter. | | `accentColor` | `string` | `"#E8B86D"` | Caret, focus band and glow color. | | `theme` | `"dark" \| "light"` | `"dark"` | Editor palette. | | `speed` | `number` | `1` | Animation speed multiplier. | ## Related - [Tutorial Clip](https://remotionui.com/docs/components/tutorial-clip.md) - [Terminal Simulator](https://remotionui.com/docs/components/terminal-simulator.md) - [Code Diff Wipe](https://remotionui.com/docs/components/code-diff-wipe.md) ## Machine-readable references - Props and usage as JSON: https://remotionui.com/ai/components/code-reveal.json - Component index: https://remotionui.com/ai/components.json --- # Commit Graph > A branch graph that draws itself, every edge grows from its parent, and each commit pops the moment its line arrives. Source: https://remotionui.com/docs/components/commit-graph ## Installation ```bash npx remotion-ui@latest add commit-graph ``` Commits land one at a time in a window styled like `git log --graph`. Each edge grows from the commit it descends from, the dot pops as the line reaches it, and the message beside it fades up a beat later, so the eye follows the rail rather than jumping ahead to the text. `parent` defaults to the previous entry, which is all a straight run needs. Point it further back to fork a branch, put the fork's commits on `lane: 1`, and set `mergeFrom` on the commit that brings it home; that commit draws two edges, one per parent, in each parent's own lane colour. Edges declare `pathLength={1}`, so the dash offset that reveals a segment is the same number as the commit's progress whether the segment is a one-row vertical hop or a long merge curve. A fork and a straight run therefore draw at the same apparent speed instead of the curve appearing to rush. Fork and merge curves leave their parent vertically and arrive vertically, which is what makes them read as lane changes rather than diagonal shortcuts. `stepSeconds` sets the pace for both the edge and the commit that follows it, so a longer history is a matter of lowering it rather than restaging the beats. ## Usage ```tsx import { CommitGraph } from "@/remotion/scenes/commit-graph"; <CommitGraph commits={[ { message: "Seed the registry manifest", hash: "9c41f0a" }, { message: "Add render queue worker", hash: "3ab77e2" }, { message: "Branch: retry backoff", hash: "d0e91c4", lane: 1, parent: 1 }, { message: "Cap retries at five", hash: "51b2fa8", lane: 1 }, { message: "Ship caption presets", hash: "7f30dd1", lane: 0, parent: 1 }, { message: "Merge retry backoff", hash: "b8c4e05", parent: 4, mergeFrom: 3, ref: "main" }, ]} holdSeconds={3.4} /> ``` `parent` defaults to the previous commit, so a straight run needs nothing; point it further back to fork and set `mergeFrom` to bring the fork home. Edges use pathLength={1}, so a long merge curve and a short vertical hop draw at the same apparent speed, and a commit dot only pops once the line feeding it has arrived. ## Props | Name | Type | Default | Description | | --- | --- | --- | --- | | `commits` | `GraphCommit[]` | `6 sample commits` | Message, hash, lane, parent index, optional mergeFrom lane and branch ref chip. | | `windowTitle` | `string` | `"git log --graph --oneline"` | Text in the title bar. Omit to drop the chrome header. | | `startAtSeconds` | `number` | `0.34` | Second the first commit lands. | | `stepSeconds` | `number` | `0.36` | Seconds between commits. Each edge draws over this same gap. | | `holdSeconds` | `number` | - | Seconds the finished graph holds before it retreats. Omit to leave it up. | | `accentColor` | `string` | `"#E8B86D"` | Trunk colour, and the branch ref chip. | | `laneColors` | `string[]` | `4 lane colours` | Colours for branch lanes 1 and up. Lane 0 always takes accentColor. | | `backgroundColor` | `string` | - | Page behind the window. Defaults to the theme page colour. | | `theme` | `"dark" \| "light"` | `"dark"` | Surface palette. | | `speed` | `number` | `1` | Animation speed multiplier. | ## Related - [Code Diff Wipe](https://remotionui.com/docs/components/code-diff-wipe.md) - [File Tree Reveal](https://remotionui.com/docs/components/file-tree-reveal.md) - [Terminal Simulator](https://remotionui.com/docs/components/terminal-simulator.md) ## Machine-readable references - Props and usage as JSON: https://remotionui.com/ai/components/commit-graph.json - Component index: https://remotionui.com/ai/components.json --- # File Tree Reveal > A project tree opening itself node by node, folders turning as their contents arrive. Source: https://remotionui.com/docs/components/file-tree-reveal ## Installation ```bash npx remotion-ui@latest add file-tree-reveal ``` Rows arrive in depth-first display order, so a folder is always on screen before anything inside it. The tree expands rather than assembling out of order. Each row takes up its own height as it appears, which pushes the rows beneath it down instead of fading them onto a fixed grid, and each folder's chevron turns on the same frames its first child arrives. Nodes are folders when they have a `children` array, files when they do not. An empty array is a folder with nothing in it, which is why there is no `kind` field to keep in sync. `selectedPath` is the slash-joined path from the root (`src/scenes/lower-third.tsx`, not just the file name), so a tree with the same name under two folders selects the one you meant. Omit it to leave nothing selected. File names take their colour from the extension, using the same token palette the code components use, so a tree standing next to `code-reveal` or `code-diff-wipe` agrees with it. This component shows structure; those two show the contents of a file. ## Usage ```tsx import { FileTreeReveal } from "@/remotion/scenes/file-tree-reveal"; <FileTreeReveal title="northstar-studio" nodes={[ { name: "src", children: [{ name: "index.ts" }] }, { name: "package.json" }, ]} selectedPath="src/index.ts" holdSeconds={4} /> ``` Rows reveal in depth-first display order, so a folder is always on screen before its contents, and each row takes its own height as it arrives: the rows beneath are pushed down rather than cross-faded onto a fixed grid. File names take their colour from the extension using the code token palette. Shows structure; code-reveal and code-diff-wipe show the contents of a file. ## Props | Name | Type | Default | Description | | --- | --- | --- | --- | | `nodes` | `FileNode[]` | `sample project tree` | Recursive tree. A node with a children array is a folder; without one it is a file. | | `title` | `string` | `"northstar-studio"` | Title bar over the tree. Omit to drop the header. | | `selectedPath` | `string` | `"src/scenes/lower-third.tsx"` | Slash-joined path of the file that lights up at the end. Omit to select nothing. | | `rowStagger` | `number` | `0.18` | Seconds between one row appearing and the next. | | `holdSeconds` | `number` | - | Seconds the finished tree holds before the panel retreats. Omit to leave it up. | | `accentColor` | `string` | `"#E8B86D"` | Selected row's bar, tint and label. | | `backgroundColor` | `string` | - | Page behind the panel. Defaults to the theme page colour. | | `theme` | `"dark" \| "light"` | `"dark"` | Surface palette. | | `speed` | `number` | `1` | Animation speed multiplier. | ## Related - [Code Reveal](https://remotionui.com/docs/components/code-reveal.md) - [Code Diff Wipe](https://remotionui.com/docs/components/code-diff-wipe.md) - [Terminal Simulator](https://remotionui.com/docs/components/terminal-simulator.md) ## Machine-readable references - Props and usage as JSON: https://remotionui.com/ai/components/file-tree-reveal.json - Component index: https://remotionui.com/ai/components.json --- # Terminal Simulator > A terminal window that types a command, streams build steps, and hands the prompt back. Source: https://remotionui.com/docs/components/terminal-simulator ## Installation ```bash npx remotion-ui@latest add terminal-simulator ``` The scene plays a full shell beat: the command types itself at the prompt, each step prints with a spinner, the spinner strokes into a check as the step resolves alongside its timing, and the prompt returns with a blinking caret, the signal a real terminal gives you when the work is done. Steps resolve in order. Give a step a longer `work` (in seconds) when it should visibly hold, and a `tone` of `warn` or `error` when it should not land clean. ## Usage ```tsx import { TerminalSimulator } from "@/remotion/scenes/terminal-simulator"; <TerminalSimulator command="pnpm build" summary="done in 4.2s" /> ``` ## Props | Name | Type | Default | Description | | --- | --- | --- | --- | | `command` | `string` | `"pnpm registry:build"` | Command typed at the prompt before anything runs. | | `steps` | `TerminalStep[]` | - | Steps printed in order; each spins, then resolves to a glyph and timing. | | `summary` | `string` | `"6 blocks · 1.9 MB · done in 4.2s"` | Dim line printed after the last step. | | `prompt` | `string` | `"~/remotion-ui"` | Prompt prefix, usually a working directory. | | `title` | `string` | `"Build output"` | Terminal window title. | | `shell` | `string` | `"zsh"` | Shell label on the right of the header. | | `accentColor` | `string` | `"#E8B86D"` | Prompt, spinner and glow color. | | `theme` | `"dark" \| "light"` | `"dark"` | Terminal palette. | | `speed` | `number` | `1` | Animation speed multiplier. | | `zoom` | `number` | `1` | Multiplies the fitted stage scale; raise it when the log has to stay legible at tile size. | ## Related - [Code Reveal](https://remotionui.com/docs/components/code-reveal.md) - [Claude Code](https://remotionui.com/docs/components/claude-code.md) - [OpenCode](https://remotionui.com/docs/components/opencode.md) ## Machine-readable references - Props and usage as JSON: https://remotionui.com/ai/components/terminal-simulator.json - Component index: https://remotionui.com/ai/components.json --- # Creator > Social-video layouts: hooks, polls, reactions, countdowns, and talking-head frames. Source: https://remotionui.com/docs/components/creator Creator scenes are built for short vertical and square video: hook cards, polls, reaction bursts, and layouts for a talking head with overlays. ## Components - [Comment Callout](https://remotionui.com/docs/components/comment-callout.md): A viewer comment answered on screen, marked up, hearted, and replied to. - [Countdown Timer](https://remotionui.com/docs/components/countdown-timer.md): A clock that runs down rather than a number that changes. - [Hook Card](https://remotionui.com/docs/components/hook-card.md): Short-form opener where the hook lands line by line and the promise gets underlined. - [Poll Overlay](https://remotionui.com/docs/components/poll-overlay.md): An audience poll whose bars travel out to their real shares. - [Reaction Burst](https://remotionui.com/docs/components/reaction-burst.md): A continuous side-channel of hearts and likes climbing the frame. - [Talking Head Layout](https://remotionui.com/docs/components/talking-head-layout.md): Speaker frame that opens, names the speaker, and plays the spoken lines. --- # Comment Callout > A viewer comment answered on screen, marked up, hearted, and replied to. Source: https://remotionui.com/docs/components/comment-callout ## Installation ```bash npx remotion-ui@latest add comment-callout ``` The comment lands from the feed, the marker sweeps the phrase named by `highlight`, the creator hearts it, and the composer opens and types out `reply` before it sends. Leave `reply` empty to end the scene on the comment itself, and drop `highlight` to skip the markup beat. ## Usage ```tsx import { CommentCallout } from "@/remotion/scenes/comment-callout"; <CommentCallout author="Mina Lee" handle="@minamakes" body="Can you turn this into a quick video breakdown?" highlight="a quick video breakdown" reply="Dropping it Thursday, here's the short version." /> ``` ## Props | Name | Type | Default | Description | | --- | --- | --- | --- | | `body` | `string` | - | The viewer comment being answered. | | `author` | `string` | - | Display name of the commenter. | | `handle` | `string` | - | Social handle, also shown on the reply line. | | `initials` | `string` | - | Avatar initials. Defaults to the first two letters of author. | | `timestamp` | `string` | - | Relative time shown after the handle, e.g. "2h". | | `highlight` | `string` | - | Substring of body the marker sweeps across. Matched case-insensitively; omit to skip the beat. | | `reply` | `string` | - | Answer typed into the composer and sent. Pass an empty string to end on the comment. | | `replyLabel` | `string` | - | Label on the reply action. Defaults to "Reply". | | `likes` | `number` | - | Like count before the creator hearts the comment. Default 128. | | `accentColor` | `string` | - | Avatar, marker, heart, and send colour. | | `backgroundColor` | `string` | - | Overrides the page background behind the card. | | `theme` | `"dark" \| "light"` | - | Card palette. Default "dark". | | `speed` | `number` | - | Animation speed multiplier for fitting a fixed-length Sequence. Default 1. | ## Related - [Creator Reel](https://remotionui.com/docs/components/creator-reel.md) - [Quote Card](https://remotionui.com/docs/components/quote-card.md) - [Caption Bumper](https://remotionui.com/docs/components/caption-bumper.md) ## Machine-readable references - Props and usage as JSON: https://remotionui.com/ai/components/comment-callout.json - Component index: https://remotionui.com/ai/components.json --- # Countdown Timer > A clock that runs down rather than a number that changes. Source: https://remotionui.com/docs/components/countdown-timer ## Installation ```bash npx remotion-ui@latest add countdown-timer ``` The ring drains continuously while the digit swaps on each whole second, so the clock reads as running between ticks instead of sitting still. The last few seconds take `urgentColor`, and zero lands with a single pop rather than ticking on into negative time. The digit is what a viewer would read off a wall clock: with 4.2 seconds left it shows `5`. Set `zeroLabel` to swap in a word at the end (LIVE, GO, ON AIR), otherwise it rests on `0`. `variant="numeric"` drops the ring and keeps the number, for corners of the frame where a 300-unit circle will not fit. ## Usage ```tsx import { CountdownTimer } from "@/remotion/scenes/countdown-timer"; <CountdownTimer from={5} label="Starting in" zeroLabel="Live" /> ``` The ring drains continuously while the digit swaps on each whole second, so the clock reads as running rather than as a number that happens to change. It stops at zero instead of ticking into negative time. ## Props | Name | Type | Default | Description | | --- | --- | --- | --- | | `from` | `number` | `5` | Seconds on the clock when the scene opens. | | `variant` | `"ring" \| "numeric"` | `"ring"` | Ring sweep with the number inside, or the number alone. | | `label` | `string` | - | Caption above the clock (STARTING IN, DOORS OPEN). | | `zeroLabel` | `string` | - | Shown once the clock reaches zero. Omit to hold on 0. | | `startDelaySeconds` | `number` | `0.35` | Seconds before the clock starts running. | | `accentColor` | `string` | `"#E8B86D"` | Ring colour above the urgent threshold. | | `urgentColor` | `string` | `"#F97362"` | Accent applied over the last urgentUnder seconds. | | `urgentUnder` | `number` | `3` | Seconds remaining at which the urgent accent takes over. | | `theme` | `"dark" \| "light"` | `"dark"` | Surface palette. | | `speed` | `number` | `1` | Animation speed multiplier. | ## Related - [Metric Ticker](https://remotionui.com/docs/components/metric-ticker.md) - [Sports Scorebug](https://remotionui.com/docs/components/sports-scorebug.md) - [End Card](https://remotionui.com/docs/components/end-card.md) ## Machine-readable references - Props and usage as JSON: https://remotionui.com/ai/components/countdown-timer.json - Component index: https://remotionui.com/ai/components.json --- # Hook Card > Short-form opener where the hook lands line by line and the promise gets underlined. Source: https://remotionui.com/docs/components/hook-card ## Installation ```bash npx remotion-ui@latest add hook-card ``` The label counts in, then the hook rises line by line out of its own mask at the pace it is spoken, and an underline draws under the words named by `emphasis`, which may span a line break. Write your own line breaks into `headline` with `\n`, or leave it to be balanced automatically. ## Usage ```tsx import { HookCard } from "@/remotion/scenes/hook-card"; <HookCard kicker="Creator insight" headline="Make the first second count" emphasis="first second" subtitle="Hook viewers before they scroll" /> ``` ## Props | Name | Type | Default | Description | | --- | --- | --- | --- | | `headline` (required) | `string` | - | The hook. Newlines are honoured as written; otherwise it is balanced across lines. | | `kicker` | `string` | - | Small live label that counts in above the hook. | | `subtitle` | `string` | - | Supporting line that settles once the hook has landed. | | `emphasis` | `string` | - | Substring of headline that takes the accent colour and the underline. Matched case-insensitively, and may span a line break. | | `align` | `"left" \| "center"` | - | Hook alignment. Default "left". | | `accentColor` | `string` | `"#E8B86D"` | Label, underline, and bloom colour. | | `backgroundColor` | `string` | - | Overrides the page background. | | `theme` | `"dark" \| "light"` | - | Page palette. Default "dark". | | `speed` | `number` | - | Animation speed multiplier for fitting a fixed-length Sequence. Default 1. | ## Related - [Creator Reel](https://remotionui.com/docs/components/creator-reel.md) - [Title Card](https://remotionui.com/docs/components/title-card.md) - [Auto-Fit Title](https://remotionui.com/docs/components/auto-fit-title.md) ## Machine-readable references - Props and usage as JSON: https://remotionui.com/ai/components/hook-card.json - Component index: https://remotionui.com/ai/components.json --- # Poll Overlay > An audience poll whose bars travel out to their real shares. Source: https://remotionui.com/docs/components/poll-overlay ## Installation ```bash npx remotion-ui@latest add poll-overlay ``` The card opens, the options arrive one after another, the bars travel out to their shares while the percentages count up under them, and the leading answer takes the accent once everything has settled. Pass raw `votes` rather than percentages: shares are computed against the other options, so the numbers on screen always agree with the tallies you gave it. A poll with no votes in yet falls back to even shares instead of dividing by zero. There is no correct answer here; the winner is whichever option the votes gave it. For a right-and-wrong reveal use `quiz-question`. Set `holdSeconds` to have the card retreat, or leave it off to hold the result for the rest of the cut. ## Usage ```tsx import { PollOverlay } from "@/remotion/scenes/poll-overlay"; <PollOverlay badge="Poll" question="Which should we build next?" options={[ { label: "Timeline editor", votes: 412 }, { label: "Batch renders", votes: 268 }, { label: "Team presets", votes: 143 }, ]} totalLabel="823 votes · closes in 2m" holdSeconds={4} /> ``` Transparent overlay scene designed to sit over footage. Unlike quiz-question there is no correct answer: the winner is whichever option the votes gave it. ## Props | Name | Type | Default | Description | | --- | --- | --- | --- | | `question` (required) | `string` | - | The question the card asks. | | `options` (required) | `PollOption[]` | - | Each option's label and raw vote tally. Shares are computed from the tallies. | | `badge` | `string` | - | Small tag above the question (POLL, AUDIENCE, EP 12). | | `align` | `"left" \| "right" \| "center"` | `"left"` | Edge the card sits against. | | `holdSeconds` | `number` | - | Seconds the result holds before the card retreats. Omit to leave it up. | | `totalLabel` | `string` | - | Total-vote line under the options. Omit to hide it. | | `accentColor` | `string` | `"#E8B86D"` | Colour the leading option takes. | | `theme` | `"dark" \| "light"` | `"dark"` | Surface palette. | | `speed` | `number` | `1` | Animation speed multiplier. | ## Related - [Quiz Question](https://remotionui.com/docs/components/quiz-question.md) - [Reaction Burst](https://remotionui.com/docs/components/reaction-burst.md) - [Comparison Bars](https://remotionui.com/docs/components/comparison-bars.md) ## Machine-readable references - Props and usage as JSON: https://remotionui.com/ai/components/poll-overlay.json - Component index: https://remotionui.com/ai/components.json --- # Reaction Burst > A continuous side-channel of hearts and likes climbing the frame. Source: https://remotionui.com/docs/components/reaction-burst ## Installation ```bash npx remotion-ui@latest add reaction-burst ``` Reactions spawn on a steady cadence, climb, sway, and thin out near the top of their arc: the live-stream side channel rather than a celebration. This is the narrow one. `confetti-burst` is a single impulse fired on one beat; here the stream keeps running for as long as the scene does. `stopAfterSeconds` closes the tap while letting everything already in flight finish its arc. Every reaction's jitter (sway phase, lane offset, scale, tilt) is a pure function of `seed` and its spawn index, through Remotion's `random()` helper. Remotion renders frames out of order and in parallel, so `Math.random()` would give the same glyph a different arc on every frame. Two streams in one composition need different `seed`s, or they trace identical arcs. `reactions` takes strings, drawn in Noto Color Emoji so a render worker without a system emoji font does not produce tofu, or elements if you would rather ship your own marks. ## Usage ```tsx import { ReactionBurst } from "@/remotion/scenes/reaction-burst"; <ReactionBurst align="right" ratePerSecond={7} /> ``` Deliberately narrower than confetti-burst, which is a single impulse fired on one beat; here the reactions keep coming for as long as the scene runs. Jitter runs through Remotion's seeded random(), a pure function of seed and spawn index, so frames render identically in any order. ## Props | Name | Type | Default | Description | | --- | --- | --- | --- | | `reactions` | `React.ReactNode[]` | `["❤️", "👍", "🔥", "😂", "✨"]` | Glyphs cycled through as reactions spawn. Strings render in Noto Color Emoji; pass elements to use your own marks. | | `ratePerSecond` | `number` | `6` | Reactions spawned per second. | | `align` | `"left" \| "right"` | `"right"` | Edge the stream rises along. | | `lifeSeconds` | `number` | `2.6` | Seconds a single reaction takes to travel its arc. | | `drift` | `number` | `46` | Horizontal sway in units, peak to peak. | | `size` | `number` | `56` | Glyph size in units at full scale. | | `rise` | `number` | `0.72` | Fraction of the frame height a reaction climbs. | | `stopAfterSeconds` | `number` | - | Seconds after which no new reactions spawn. Ones in flight finish their arc. | | `seed` | `string \| number` | `"reaction-burst"` | Seeds the per-reaction jitter. Two streams in one composition need different seeds. | | `speed` | `number` | `1` | Animation speed multiplier. | ## Related - [Confetti Burst](https://remotionui.com/docs/components/confetti-burst.md) - [Poll Overlay](https://remotionui.com/docs/components/poll-overlay.md) - [chat-bubble](https://remotionui.com/docs/components/chat-bubble.md) ## Machine-readable references - Props and usage as JSON: https://remotionui.com/ai/components/reaction-burst.json - Component index: https://remotionui.com/ai/components.json --- # Talking Head Layout > Speaker frame that opens, names the speaker, and plays the spoken lines. Source: https://remotionui.com/docs/components/talking-head-layout ## Installation ```bash npx remotion-ui@latest add talking-head-layout ``` The frame opens on the speaker, the name plate slides out from behind its edge, the `captions` play through the reserved zone with the waveform moving under them, then the plate retreats and leaves the frame clean for burnt-in captions or platform UI. Omit `captions` and the zone collapses so the frame takes the height instead. Pass `holdSeconds` when the layout stands on its own and the whole frame leaves once the last line has been read; omit it inside a `TransitionSeries`, where the transition covers the tail. ## Usage ```tsx import { TalkingHeadLayout } from "@/remotion/scenes/talking-head-layout"; <TalkingHeadLayout mediaSrc={staticFile("speaker.mp4")} audioSrc={staticFile("voice.wav")} eyebrow="On camera" title="Maya Okonkwo" subtitle="Founder, Northlight Studio" captions={["Keep the speaker readable.", "Reserve the lower frame."]} /> ``` Advanced. Installs @remotion/media and waveform-line for optional audio visuals. ## Props | Name | Type | Default | Description | | --- | --- | --- | --- | | `mediaSrc` | `string` | - | Speaker image or video. Falls back to a framed placeholder. | | `audioSrc` | `string` | - | Voice track the waveform is drawn from. Omit to hide the waveform. | | `eyebrow` | `string` | - | Small label above the name on the plate, e.g. a role. | | `title` | `string` | - | Name plate headline. | | `subtitle` | `string` | - | Second plate line. | | `captions` | `string[]` | - | Spoken lines. They play one at a time, word by word, in the zone reserved under the frame. Omit and the zone collapses. | | `fit` | `"cover" \| "contain"` | `"cover"` | Media object-fit behavior. | | `accentColor` | `string` | `"#2DD4BF"` | Plate label, waveform, and ambient light color. | | `backgroundColor` | `string` | - | Overrides the page background behind the frame. | | `theme` | `"dark" \| "light"` | `"dark"` | Palette the page and plate are drawn from. | | `holdSeconds` | `number` | - | Seconds after which the whole layout leaves. Omit to hold: correct inside a TransitionSeries, where the transition covers the tail. | | `speed` | `number` | `1` | Animation speed multiplier for shorter Sequences. | ## Related - [Creator Reel](https://remotionui.com/docs/components/creator-reel.md) - [Caption Scene](https://remotionui.com/docs/components/caption-scene.md) - [Media Frame](https://remotionui.com/docs/components/media-frame.md) ## Machine-readable references - Props and usage as JSON: https://remotionui.com/ai/components/talking-head-layout.json - Component index: https://remotionui.com/ai/components.json --- # UI flows > Simulated product interactions: forms, drag and drop, tabs, and notifications. Source: https://remotionui.com/docs/components/ui-flows UI flow scenes simulate someone using an interface: filling a form, dragging cards, switching tabs, and receiving notifications. Use them to demo a product without screen recording. ## Components - [Chat to Preview](https://remotionui.com/docs/components/chat-to-preview.md): The prompt-to-render loop: ask typed and sent, answer streamed, preview assembled. - [Drag-and-Drop Flow](https://remotionui.com/docs/components/drag-drop-flow.md): Cursor drags a file out of a media library into a drop zone that arms, catches it, and uploads it. - [FAQ Accordion](https://remotionui.com/docs/components/faq-accordion.md): Question rows that open one at a time, each answer's panel growing as the row above it gives the height back. - [Form Fill Sequence](https://remotionui.com/docs/components/form-fill-sequence.md): A sign-up form filling itself out field by field, each one validating before the next takes focus. - [Kanban Move](https://remotionui.com/docs/components/kanban-move.md): A board where work moves, cards lift off one column, arc across the gutter, and drop into the next while the list they left closes up. - [Notification Stack](https://remotionui.com/docs/components/notification-stack.md): Toasts arriving, stacking, and clearing themselves in a screen corner. - [Search Results Populate](https://remotionui.com/docs/components/search-results-populate.md): A query typing itself, results streaming back, and the list re-ranking to put the best match on top. - [Tab Switch Panel](https://remotionui.com/docs/components/tab-switch-panel.md): An app window whose tabs switch on their own, the pill gliding while panels slide through. --- # Chat to Preview > The prompt-to-render loop: ask typed and sent, answer streamed, preview assembled. Source: https://remotionui.com/docs/components/chat-to-preview ## Installation ```bash npx remotion-ui@latest add chat-to-preview ``` The ask types itself into the composer under a caret and flies up into the thread on send; the assistant thinks, then streams its answer word by word; and the preview surface assembles alongside it: status moving Idle → Rendering → Ready, wireframe blocks landing in order, then resolving into the rendered scene under a single sheen. `messages` drives the whole clock: user turns type and send, assistant turns stream, and the timing is derived from the text rather than from fixed frames. ## Usage ```tsx import { ChatToPreview } from "@/remotion/scenes/chat-to-preview"; <ChatToPreview messages={messages} previewTitle="Ship the scene" /> ``` ## Props | Name | Type | Default | Description | | --- | --- | --- | --- | | `messages` | `ChatMessage[]` | - | The exchange, in order. User turns type and send; assistant turns stream. Drives the whole clock. | | `previewTitle` | `string` | `"Ship the scene"` | Title the finished preview renders. | | `previewCaption` | `string` | - | Supporting line under the preview title. | | `previewLabel` | `string` | `"Preview"` | Name of the preview surface in its header, or its tab title in browser mode. | | `previewUrl` | `string` | - | Address the preview is loading. Renders the surface as a browser (tab strip, URL bar and a load bar) and starts the page loading when the address is sent. | | `placeholder` | `string` | - | Composer placeholder before anything is typed. | | `accentColor` | `string` | `"#E8B86D"` | Assistant bubble, status, and render tint. | | `backgroundColor` | `string` | - | Overrides the page background. | | `theme` | `"dark" \| "light"` | `"dark"` | Surface palette. | | `speed` | `number` | `1` | Animation speed multiplier. | ## Related - [Talking Head Layout](https://remotionui.com/docs/components/talking-head-layout.md) - [Media Frame](https://remotionui.com/docs/components/media-frame.md) ## Machine-readable references - Props and usage as JSON: https://remotionui.com/ai/components/chat-to-preview.json - Component index: https://remotionui.com/ai/components.json --- # Drag-and-Drop Flow > Cursor drags a file out of a media library into a drop zone that arms, catches it, and uploads it. Source: https://remotionui.com/docs/components/drag-drop-flow ## Installation ```bash npx remotion-ui@latest add drag-drop-flow ``` The whole drag beat, not a card sliding into a box. The cursor travels into the media library, presses the file, and carries it across; the row it left holds its place as a dashed ghost; the drop zone arms while the file is held over it; and the release turns into a transfer that fills and completes. Pass `siblings` to change the rest of the library, `fileName`/`fileSize` for the file itself, and `speed` to fit the beat into a fixed sequence. ## Usage ```tsx import { DragDropFlow } from "@/remotion/scenes/drag-drop-flow"; <DragDropFlow fileName="hero-loop.tsx" /> ``` ## Props | Name | Type | Default | Description | | --- | --- | --- | --- | | `fileName` | `string` | `"hero-take.mp4"` | File the cursor picks up. | | `fileSize` | `string` | `"48.2 MB"` | Size shown once the upload completes. | | `siblings` | `string[]` | - | Other rows in the source list. | | `sourceLabel` | `string` | `"Media library"` | Heading on the source panel. | | `label` | `string` | `"Drop your clip"` | Idle prompt in the drop zone. | | `hint` | `string` | - | Second line under the prompt. | | `activeLabel` | `string` | `"Release to upload"` | Prompt while the file is held over the zone. | | `doneLabel` | `string` | `"Uploaded"` | Label once the upload finishes. | | `accentColor` | `string` | `"#E8B86D"` | Zone, cursor ring, and progress colour. | | `backgroundColor` | `string` | - | Overrides the page background. | | `theme` | `"dark" \| "light"` | `"dark"` | Surface palette. | | `speed` | `number` | `1` | Animation speed multiplier. | ## Related - [Cursor Path](https://remotionui.com/docs/components/cursor-path.md) - [Simulated Cursor](https://remotionui.com/docs/components/simulated-cursor.md) - [Tutorial Clip](https://remotionui.com/docs/components/tutorial-clip.md) ## Machine-readable references - Props and usage as JSON: https://remotionui.com/ai/components/drag-drop-flow.json - Component index: https://remotionui.com/ai/components.json --- # FAQ Accordion > Question rows that open one at a time, each answer's panel growing as the row above it gives the height back. Source: https://remotionui.com/docs/components/faq-accordion ## Installation ```bash npx remotion-ui@latest add faq-accordion ``` Rows open in the order you give in `openOrder`, and each one closes the previous. The two curves overlap deliberately: the closing panel gives back its height over the same frames the opening one takes it, so the list keeps a steady overall height and nothing below it jumps. The chevron turns a full half so it ends pointing at the panel it just opened, and the answer copy fades in behind the growing edge rather than with it, which is what makes the panel read as opening instead of as text stretching. Panel heights are estimated from each answer's own length against the measured content width. A headless render has no settled layout to interrogate mid-animation. A height read from `scrollHeight` collapses to zero on exactly the frames that matter, so the estimate rounds up, costing a few pixels of slack and buying a height that is identical on every machine. Keep answers to two or three lines; long copy inflates that rounding. Pass a shorter `openOrder` than `items` to leave the tail closed, which is often what you want: a list where every row opens spends its whole run in motion and never lets a viewer read one answer. For code panels reach for `code-accordion`, and for an ordered process rather than a Q&A use `timeline-steps`. ## Usage ```tsx import { FaqAccordion } from "@/remotion/scenes/faq-accordion"; <FaqAccordion title="Questions people ask" items={[ { question: "Do I own the components?", answer: "Yes. The CLI copies the source into your repo." }, { question: "Can I render on my own machine?", answer: "Renders run wherever Remotion runs." }, ]} openOrder={[0, 1]} holdSeconds={3.4} /> ``` Panel heights are estimated from the answer's length against the measured content width, because a headless render has no layout to interrogate mid-animation, and a height read from scrollHeight collapses to zero on exactly the frames that matter. Keep answers to two or three lines; long copy inflates the estimate's rounding slack. For code panels use code-accordion, for an ordered process use timeline-steps. ## Props | Name | Type | Default | Description | | --- | --- | --- | --- | | `items` | `FaqItem[]` | `4 sample questions` | Question and answer for each row. | | `title` | `string` | `"Questions people ask"` | Heading above the list. Omit to drop it. | | `openOrder` | `number[]` | `[0, 1, 2]` | Row indices opened in turn; each closes the previous. Shorter than items leaves the tail closed. | | `startAtSeconds` | `number` | `0.55` | Second the first row opens. | | `openEverySeconds` | `number` | `1` | Seconds between one row opening and the next. | | `transitionSeconds` | `number` | `0.55` | How long a row takes to open or close. Opens and closes overlap, so the list never jumps height. | | `holdSeconds` | `number` | - | Seconds the list holds before it retreats. Omit to leave it up. | | `accentColor` | `string` | `"#E8B86D"` | Open row's chevron and its background wash. | | `backgroundColor` | `string` | - | Page behind the list. Defaults to the theme page colour. | | `theme` | `"dark" \| "light"` | `"dark"` | Surface palette. | | `speed` | `number` | `1` | Animation speed multiplier. | ## Related - [Code Accordion](https://remotionui.com/docs/components/code-accordion.md) - [Timeline Steps](https://remotionui.com/docs/components/timeline-steps.md) - [Feature List](https://remotionui.com/docs/components/feature-list.md) ## Machine-readable references - Props and usage as JSON: https://remotionui.com/ai/components/faq-accordion.json - Component index: https://remotionui.com/ai/components.json --- # Form Fill Sequence > A sign-up form filling itself out field by field, each one validating before the next takes focus. Source: https://remotionui.com/docs/components/form-fill-sequence ## Installation ```bash npx remotion-ui@latest add form-fill-sequence ``` The caret drops into the first field, types its value, and the field ticks green before focus moves on. The submit button stays disabled until the last field has validated, so the ending reads as a consequence of the form rather than a separate flourish. Field timings are not fixed constants: each one is derived from its own value length and `charsPerSecond`, so a long email visibly takes longer to enter than a short name and the whole sequence lengthens when you pass more fields. Budget roughly `value.length / charsPerSecond + 0.26s` per field when you are fitting this into a cut. `accentColor` is the focus ring and the armed button; `validColor` is the tick and the settled border. They are separate props on purpose: collapsing them into one colour makes "this field has focus" and "this field passed" indistinguishable at a glance. Typing here is the subject. When the typing is only setup for a result list, reach for `search-results-populate` instead. ## Usage ```tsx import { FormFillSequence } from "@/remotion/scenes/form-fill-sequence"; <FormFillSequence title="Create your workspace" fields={[ { label: "Full name", value: "Ada Lovelace", placeholder: "Your name" }, { label: "Work email", value: "ada@northstar.dev" }, ]} submitLabel="Create workspace" successLabel="Workspace created" holdSeconds={4} /> ``` Field beats are derived from each value's length, so the sequence lengthens with the content rather than running on fixed constants. The submit button stays disabled until the last field ticks. Typing is the subject here; when it is only setup for a result list, use search-results-populate. ## Props | Name | Type | Default | Description | | --- | --- | --- | --- | | `fields` | `FormField[]` | `3 sample fields` | Label, typed value and placeholder for each field, filled in order. | | `title` | `string` | `"Create your workspace"` | Heading on the card. Omit to show the fields alone. | | `subtitle` | `string` | `"Takes about a minute."` | Supporting line under the heading. | | `submitLabel` | `string` | `"Create workspace"` | Button text while the form is still filling. | | `successLabel` | `string` | `"Workspace created"` | Button text once every field has validated. | | `charsPerSecond` | `number` | `34` | Typing rate. Each field's duration is its value length divided by this. | | `holdSeconds` | `number` | - | Seconds the filled form holds before the card retreats. Omit to leave it up. | | `accentColor` | `string` | `"#E8B86D"` | Focus ring and armed submit button. | | `validColor` | `string` | `"#7FD1A0"` | Tick and settled border. Kept off accentColor so focus and validation stay two states. | | `backgroundColor` | `string` | - | Page behind the card. Defaults to the theme page colour. | | `theme` | `"dark" \| "light"` | `"dark"` | Surface palette. | | `speed` | `number` | `1` | Animation speed multiplier. | ## Related - [Search Results Populate](https://remotionui.com/docs/components/search-results-populate.md) - [Drag-and-Drop Flow](https://remotionui.com/docs/components/drag-drop-flow.md) - [Tab Switch Panel](https://remotionui.com/docs/components/tab-switch-panel.md) ## Machine-readable references - Props and usage as JSON: https://remotionui.com/ai/components/form-fill-sequence.json - Component index: https://remotionui.com/ai/components.json --- # Kanban Move > A board where work moves, cards lift off one column, arc across the gutter, and drop into the next while the list they left closes up. Source: https://remotionui.com/docs/components/kanban-move ## Installation ```bash npx remotion-ui@latest add kanban-move ``` Cards deal into their columns, then the ones you have given a move lift off, arc across the gutter under a shadow that grows with the lift, and drop into the bottom of the destination list. The column being aimed at lights while a card is in flight and settles again once it lands, so the eye is told where the card is going before it gets there. Give a card a move with `moveTo` and `moveAtSeconds`; leave both off and it holds. A board where everything moves reads as noise rather than as work getting done: two or three moves across a scene is usually the right number. Slots are arithmetic rather than layout. A moving card lands at the bottom of its destination *as that column stands at the moment it arrives*, and every card above a departure closes the gap over exactly the frames the departing card is travelling. Nothing here measures the DOM, so the board behaves identically in a headless render and in the Studio, and no card ever snaps to a new row. Column counts follow the cards, not the clock: a card in flight is counted by whichever column it is closest to, so the numbers tick over at the midpoint of the arc. For a single file dropped into one target, `drag-drop-flow` is the smaller scene. ## Usage ```tsx import { KanbanMove } from "@/remotion/scenes/kanban-move"; <KanbanMove columns={["Backlog", "In progress", "Shipped"]} cards={[ { title: "Caption presets", meta: "RUI-218 · Ana", column: 0 }, { title: "Render queue retries", meta: "RUI-204 · Piotr", column: 0, moveTo: 1, moveAtSeconds: 0.95, }, { title: "Theme tokens", meta: "RUI-177 · Kit", column: 1 }, ]} holdSeconds={3.4} /> ``` Give a card `moveTo` and `moveAtSeconds` to send it across; leave both off for cards that hold. Slots are arithmetic: a card lands at the bottom of its destination as that column stands at the moment it arrives, and the cards it left behind close the gap over exactly the frames it is travelling. For a single file dropping into one target, use drag-drop-flow. ## Props | Name | Type | Default | Description | | --- | --- | --- | --- | | `columns` | `string[]` | `["Backlog", "In progress", "Shipped"]` | Column headings, left to right. Cards address columns by index. | | `cards` | `KanbanCard[]` | `6 sample cards` | Title, meta line, starting column, rail tint, and the one move the card makes. | | `moveSeconds` | `number` | `0.62` | How long a card takes to arc from column to column. | | `dealStaggerSeconds` | `number` | `0.08` | Seconds between each card's arrival during the opening deal. | | `holdSeconds` | `number` | - | Seconds the settled board holds before it retreats. Omit to leave it up. | | `accentColor` | `string` | `"#E8B86D"` | Destination column glow, and the fallback card rail. | | `backgroundColor` | `string` | - | Page behind the board. Defaults to the theme page colour. | | `theme` | `"dark" \| "light"` | `"dark"` | Surface palette. | | `speed` | `number` | `1` | Animation speed multiplier. | ## Related - [Drag-and-Drop Flow](https://remotionui.com/docs/components/drag-drop-flow.md) - [Tab Switch Panel](https://remotionui.com/docs/components/tab-switch-panel.md) - [Notification Stack](https://remotionui.com/docs/components/notification-stack.md) ## Machine-readable references - Props and usage as JSON: https://remotionui.com/ai/components/kanban-move.json - Component index: https://remotionui.com/ai/components.json --- # Notification Stack > Toasts arriving, stacking, and clearing themselves in a screen corner. Source: https://remotionui.com/docs/components/notification-stack ## Installation ```bash npx remotion-ui@latest add notification-stack ``` Each toast carries its own life. Arrivals and dismissals overlap, so the stack fills while notifications outpace their own timers and drains again once they stop. It is never a fixed list that fades in together. The collapse is what sells it: when a toast leaves, the ones below travel up into the gap instead of jumping. Every slot offset is the sum of the live heights above it, and a dismissing toast's contribution falls smoothly to zero rather than switching off. There is no `holdSeconds` here, because there is nothing to hold: set `lifeSeconds` for the default dwell and override a single toast with `holdFor`. Bottom-anchored stacks grow upward, so the newest toast is always the one nearest the corner regardless of `align`. `showProgress` draws the draining line along each toast's bottom edge. Leave it on for scenes where the stack sits still for a while: it is the only thing moving between one arrival and the next. For a single pointed annotation rather than system chatter, use `comment-callout` or `callout-spotlight`. ## Usage ```tsx import { NotificationStack } from "@/remotion/scenes/notification-stack"; <NotificationStack align="top-right" toasts={[ { title: "Render finished", body: "launch-teaser.mp4", tone: "success", meta: "now" }, { title: "Storage at 86%", tone: "warn", meta: "2m" }, ]} lifeSeconds={2.3} /> ``` Transparent overlay scene designed to sit over an app or capture. Each toast carries its own life, so there is no holdSeconds: the stack fills and drains on its own. Slot offsets are the sum of the live heights above, which is what makes the rows below travel up into a dismissal instead of jumping. ## Props | Name | Type | Default | Description | | --- | --- | --- | --- | | `toasts` | `Toast[]` | `4 sample toasts` | Title, optional body and meta, tone, and optional per-toast arrival and dwell. | | `align` | `"top-right" \| "top-left" \| "bottom-right" \| "bottom-left"` | `"top-right"` | Corner the stack anchors to. Bottom anchors grow upward. | | `startAtSeconds` | `number` | `0.3` | Second the first toast arrives. | | `staggerSeconds` | `number` | `0.62` | Seconds between arrivals, for toasts without their own atSeconds. | | `lifeSeconds` | `number` | `2.3` | Default seconds a toast stays up before dismissing itself. | | `showProgress` | `boolean` | `true` | Draining line along each toast's bottom edge. | | `accentColor` | `string` | `"#E8B86D"` | Colour used by the warn tone. | | `theme` | `"dark" \| "light"` | `"dark"` | Surface palette. | | `speed` | `number` | `1` | Animation speed multiplier. | ## Related - [Comment Callout](https://remotionui.com/docs/components/comment-callout.md) - [Callout Spotlight](https://remotionui.com/docs/components/callout-spotlight.md) - [chat-bubble](https://remotionui.com/docs/components/chat-bubble.md) ## Machine-readable references - Props and usage as JSON: https://remotionui.com/ai/components/notification-stack.json - Component index: https://remotionui.com/ai/components.json --- # Search Results Populate > A query typing itself, results streaming back, and the list re-ranking to put the best match on top. Source: https://remotionui.com/docs/components/search-results-populate ## Installation ```bash npx remotion-ui@latest add search-results-populate ``` The query types itself, an indeterminate bar runs while the index works, results stream in one by one, and then the list re-ranks so the best match rises to the top. The order of `results` is arrival order (the order the index handed them back), and `score` decides where each one ends up. Give the highest score to something other than the first entry and you get the beat this component exists for: a fourth arrival climbing past three rows to first place. Pass them already sorted and the re-rank is a no-op. Rows are never re-sorted in the DOM. Each one interpolates from its arrival slot to its ranked slot, so React does not remount a row mid-flight and the travel stays continuous even when two rows swap. Typing is setup here, not the subject. When the fields themselves are the story (focus, validation, a submit button arming), use `form-fill-sequence`. ## Usage ```tsx import { SearchResultsPopulate } from "@/remotion/scenes/search-results-populate"; <SearchResultsPopulate query="transition between scenes" results={[ { title: "Slide transition", detail: "docs/transitions/slide", score: 0.64 }, { title: "Cross-fade two compositions", detail: "docs/transitions/fade", score: 0.98 }, ]} holdSeconds={4} /> ``` The re-rank is the payoff: give the highest score to something other than the first entry and a late arrival climbs past the rows above it. Rows interpolate from arrival slot to ranked slot rather than being re-sorted, so React never remounts one mid-flight. ## Props | Name | Type | Default | Description | | --- | --- | --- | --- | | `query` | `string` | `"transition between scenes"` | Text typed into the field. | | `results` | `SearchResult[]` | `5 sample results` | Title, detail line and 0–1 score. Array order is arrival order; score decides the final rank. | | `placeholder` | `string` | `"Search the docs"` | Greyed prompt shown before the first character lands. | | `countLabel` | `string` | `"{n} results"` | Line above the list. {n} is replaced with the result count. | | `topLabel` | `string` | `"Best match"` | Tag pinned to the top-ranked result once the list settles. | | `charsPerSecond` | `number` | `30` | Typing rate for the query. | | `searchSeconds` | `number` | `0.34` | Seconds the indeterminate bar runs between the query and the first row. | | `holdSeconds` | `number` | - | Seconds the ranked list holds before the card retreats. Omit to leave it up. | | `accentColor` | `string` | `"#E8B86D"` | Active field border, top-result tag and score. | | `backgroundColor` | `string` | - | Page behind the card. Defaults to the theme page colour. | | `theme` | `"dark" \| "light"` | `"dark"` | Surface palette. | | `speed` | `number` | `1` | Animation speed multiplier. | ## Related - [Form Fill Sequence](https://remotionui.com/docs/components/form-fill-sequence.md) - [Comparison Table](https://remotionui.com/docs/components/comparison-table.md) - [File Tree Reveal](https://remotionui.com/docs/components/file-tree-reveal.md) ## Machine-readable references - Props and usage as JSON: https://remotionui.com/ai/components/search-results-populate.json - Component index: https://remotionui.com/ai/components.json --- # Tab Switch Panel > An app window whose tabs switch on their own, the pill gliding while panels slide through. Source: https://remotionui.com/docs/components/tab-switch-panel ## Installation ```bash npx remotion-ui@latest add tab-switch-panel ``` The pill travels along the tab bar while the outgoing panel slides off and the incoming one arrives behind it. Rows trail the headline by a little more each step down, so a panel reads as one object with depth rather than as a stack of independent fades. Tabs share the bar width evenly. That is what lets the pill's travel be pure arithmetic: no text measurement, so the indicator can never drift out of register with the label beneath it. The trade is that one long label squeezes every other tab, so keep labels to a word or two. The scene walks forward from `startIndex` to the last tab and stops; it does not wrap. Total run time is `firstSwitchAtSeconds + switchEverySeconds × (tabs.length - 1 - startIndex) + transitionSeconds`, which is the number to check before setting `holdSeconds`: a hold shorter than that cuts the window away mid-switch. Panels cross-fade faster than they travel, on purpose: the outgoing panel is gone before the incoming one is half way, so the two never sit on top of each other as unreadable double text. ## Usage ```tsx import { TabSwitchPanel } from "@/remotion/scenes/tab-switch-panel"; <TabSwitchPanel windowTitle="Northstar Studio" tabs={[ { label: "Overview", title: "1,284 renders", rows: [{ label: "Queued", value: "12" }] }, { label: "Billing", title: "Studio plan", rows: [{ label: "Seats", value: "9 of 12" }] }, ]} switchEverySeconds={0.9} holdSeconds={4} /> ``` Tabs share the bar width evenly so the pill's travel is arithmetic rather than measured text, so it can never drift out of register with its label. The scene walks forward to the last tab and stops; it does not wrap, so holdSeconds must clear firstSwitchAtSeconds + switchEverySeconds × (tabs.length - 1) + transitionSeconds. ## Props | Name | Type | Default | Description | | --- | --- | --- | --- | | `tabs` | `PanelTab[]` | `4 sample tabs` | Tab label plus the panel's title, summary and label/value rows. | | `windowTitle` | `string` | `"Northstar Studio"` | Title bar text. Omit to drop the chrome header. | | `startIndex` | `number` | `0` | Tab shown when the scene opens. | | `firstSwitchAtSeconds` | `number` | `0.95` | Second the first switch fires. | | `switchEverySeconds` | `number` | `0.9` | Seconds between switches after the first. | | `transitionSeconds` | `number` | `0.5` | How long one tab-to-tab move takes. | | `holdSeconds` | `number` | - | Seconds the last panel holds before the window retreats. Omit to leave it up. | | `accentColor` | `string` | `"#E8B86D"` | Indicator pill and active label. | | `backgroundColor` | `string` | - | Page behind the window. Defaults to the theme page colour. | | `theme` | `"dark" \| "light"` | `"dark"` | Surface palette. | | `speed` | `number` | `1` | Animation speed multiplier. | ## Related - [Device Mockup Zoom](https://remotionui.com/docs/components/device-mockup-zoom.md) - [Chat to Preview](https://remotionui.com/docs/components/chat-to-preview.md) - [FAQ Accordion](https://remotionui.com/docs/components/faq-accordion.md) ## Machine-readable references - Props and usage as JSON: https://remotionui.com/ai/components/tab-switch-panel.json - Component index: https://remotionui.com/ai/components.json --- # Layouts & cards > Composed scenes for titles, stats, quotes, pricing, timelines, and split layouts. Source: https://remotionui.com/docs/components/layouts-and-cards Layouts and cards are complete scenes for common beats in a video: title and end cards, lower thirds, stats, quotes, pricing, and timelines. Pass your content as props. ## Components - [Auto-Fit Title](https://remotionui.com/docs/components/auto-fit-title.md): A headline sized to the frame it is given, then assembled word by word. - [B-Roll Stack](https://remotionui.com/docs/components/b-roll-stack.md): A deck of supporting shots dealt one at a time behind the narration. - [Calendar Month Fill](https://remotionui.com/docs/components/calendar-month-fill.md): A month grid sweeping up on a diagonal, then events dropping onto their days one at a time. - [Callout Spotlight](https://remotionui.com/docs/components/callout-spotlight.md): A spotlight that is aimed. Mask, ping, connector, then the callout. - [Caption Bumper](https://remotionui.com/docs/components/caption-bumper.md): A between-beats card that punches its line in word by word. - [Changelog Entry](https://remotionui.com/docs/components/changelog-entry.md): A release note reading itself out. Version, a rule drawing under it, then each change behind its own coloured tag. - [Comparison Table](https://remotionui.com/docs/components/comparison-table.md): A feature matrix that fills in the way you read it. Row by row, label first, each column's verdict a fraction behind the last. - [Data Flow Pipes](https://remotionui.com/docs/components/data-flow-pipes.md): A pipeline running end to end, with payloads hopping stage to stage. - [End Card](https://remotionui.com/docs/components/end-card.md): The outro, built in the order a viewer acts on it. - [Feature List](https://remotionui.com/docs/components/feature-list.md): A list being ticked off, row by row. - [Logo Wall](https://remotionui.com/docs/components/logo-wall.md): A client wall that comes up to colour. Tiles land grey, then warm to their brand colours on a diagonal sweep. - [Lower Third](https://remotionui.com/docs/components/lower-third.md): A name plate that wipes on, holds, and retreats the way it came. - [Media Frame](https://remotionui.com/docs/components/media-frame.md): One piece of media presented. The frame opens on it under a slow push. - [Media Sequence](https://remotionui.com/docs/components/media-sequence.md): An edited run of shots with a chapter strip showing where you are. - [News Ticker Bar](https://remotionui.com/docs/components/news-ticker-bar.md): A broadcast lower bar with a standing flag and a headline crawl. - [Org Chart Build](https://remotionui.com/docs/components/org-chart-build.md): A hierarchy assembling top-down. Connectors draw down from the parents already standing, and nodes land on the ends of the lines. - [Pricing Card](https://remotionui.com/docs/components/pricing-card.md): A tier card that earns its price. The number rolls up, the features tick in beneath it, and the call to action arrives last. - [Quiz Question](https://remotionui.com/docs/components/quiz-question.md): A question that resolves. Options arrive, one is picked, then the right answer lights while the rest step back. - [Quote Card](https://remotionui.com/docs/components/quote-card.md): A pull quote read aloud. Mark, lines, marker sweep, attribution. - [Roadmap Lanes](https://remotionui.com/docs/components/roadmap-lanes.md): Swimlanes of shipped, building and planned work, each lane filling in turn and in-flight items growing to their real progress. - [Split Screen](https://remotionui.com/docs/components/split-screen.md): A before/after that is actually made, not just placed side by side. - [Sports Scorebug](https://remotionui.com/docs/components/sports-scorebug.md): Broadcast score furniture with a live clock and scores that land. - [Stat Card](https://remotionui.com/docs/components/stat-card.md): A number landing. Ring, counter, label, and the change behind it. - [Team Grid](https://remotionui.com/docs/components/team-grid.md): A team arriving person by person. The avatar springs up first, the name and role follow it into place. - [Timeline Steps](https://remotionui.com/docs/components/timeline-steps.md): A process walked step by step, each one worked and checked off. - [Title Card](https://remotionui.com/docs/components/title-card.md): An opening card where the headline stands up line by line. - [Weather Card](https://remotionui.com/docs/components/weather-card.md): Conditions with iconography that never stops. Rays turn, clouds drift, drops and flakes fall on their own loops. - [Zoom Pan Frame](https://remotionui.com/docs/components/zoom-pan-frame.md): A camera move on a still, driven by focal points rather than pixel offsets. --- # Auto-Fit Title > A headline sized to the frame it is given, then assembled word by word. Source: https://remotionui.com/docs/components/auto-fit-title ## Installation ```bash npx remotion-ui@latest add auto-fit-title ``` The fit is measured before anything animates, then the words land one after another out of their own masks: a two-word title and a twelve-word title both fill the safe area and both land the same way. `maxFontSize` and `minFontSize` bound the fit; the subtitle scales with the result so the pair keeps its ratio at any length. ## Usage ```tsx import { AutoFitTitle } from "@/remotion/scenes/auto-fit-title"; <AutoFitTitle title="Headlines that always fit" subtitle="Any resolution" /> ``` ## Props | Name | Type | Default | Description | | --- | --- | --- | --- | | `title` (required) | `string` | - | Headline, fitted to the safe area whatever its length. | | `subtitle` | `string` | - | Subtitle; scales with the fitted headline. | | `logoSrc` | `string` | - | Brand mark above the headline. | | `logoSize` | `number` | - | Logo size in composition pixels. | | `maxFontSize` | `number` | `128` | Ceiling for the fitted size, at a 1080-wide stage. | | `minFontSize` | `number` | `34` | Floor for the fitted size. | | `accentColor` | `string` | `"#E8B86D"` | Background glow colour. | | `theme` | `"dark" \| "light"` | `"dark"` | Surface palette. | | `speed` | `number` | `1` | Animation speed multiplier. | | `holdSeconds` | `number` | - | Seconds before the card fades and lifts away. Omit to hold. Inside a TransitionSeries, set it so the exit finishes before the cut begins. | ## Related - [Title Card](https://remotionui.com/docs/components/title-card.md) - [Social Clip](https://remotionui.com/docs/components/social-clip.md) ## Machine-readable references - Props and usage as JSON: https://remotionui.com/ai/components/auto-fit-title.json - Component index: https://remotionui.com/ai/components.json --- # B-Roll Stack > A deck of supporting shots dealt one at a time behind the narration. Source: https://remotionui.com/docs/components/b-roll-stack ## Installation ```bash npx remotion-ui@latest add b-roll-stack ``` Each shot rides to the front of the deck in turn with its own label, the one it replaces slides back into the stack, and the deck keeps cycling for as long as the scene runs, so a long narration beat never sits on a frozen fan of cards. `holdSeconds` sets how long a shot owns the front; the headline, kicker and caption sit beside the deck (above it in portrait) with a running count. ## Usage ```tsx import { BRollStack } from "@/remotion/scenes/b-roll-stack"; <BRollStack kicker="Cutaway" title="Layer proof shots behind the narration" items={[{ src: staticFile("shot.png"), title: "Proof", fit: "cover" }]} /> ``` ## Props | Name | Type | Default | Description | | --- | --- | --- | --- | | `items` | `BRollItem[]` | - | Image or video cards to layer. Omit for styled placeholders. | | `kicker` | `string` | `"Supporting visuals"` | Short label above the headline. | | `title` | `string` | - | Scene headline. | | `caption` | `string` | - | Supporting copy below the headline. | | `holdSeconds` | `number` | `1.35` | Seconds a shot holds at the front before the deck advances. | | `aspect` | `number` | `16 / 9` | Aspect the cards are cut to. | | `accentColor` | `string` | `"#E8B86D"` | Kicker, card rim, and label colour. | | `theme` | `"dark" \| "light"` | `"dark"` | Surface palette. | | `speed` | `number` | `1` | Animation speed multiplier. | ## Related - [Media Frame](https://remotionui.com/docs/components/media-frame.md) - [Media Sequence](https://remotionui.com/docs/components/media-sequence.md) ## Machine-readable references - Props and usage as JSON: https://remotionui.com/ai/components/b-roll-stack.json - Component index: https://remotionui.com/ai/components.json --- # Calendar Month Fill > A month grid sweeping up on a diagonal, then events dropping onto their days one at a time. Source: https://remotionui.com/docs/components/calendar-month-fill ## Installation ```bash npx remotion-ui@latest add calendar-month-fill ``` The empty grid fades up on a diagonal sweep and then the events land, each chip dropping onto its day rather than fading in place, so a filling month reads as things being scheduled instead of as a page loading. The month is laid out from `daysInMonth` and `startWeekday` rather than from a date, and there is no date library involved. A scene needs a month that *looks* right, not one that is correct for a particular year, and this keeps the component free of both a dependency and a timezone bug waiting to happen. Set `startWeekday` to the column the 1st falls in, counting from Monday. `todayDay` rings one date in the accent colour. Pass `-1` when the month is a plan rather than a present-tense calendar. Events are keyed by day number, one chip per day: the cell has room for the day number and a single chip at 1080p. If two things happen on one day, say so in the label rather than stacking chips. ## Usage ```tsx import { CalendarMonthFill } from "@/remotion/scenes/calendar-month-fill"; <CalendarMonthFill month="August" year="2026" daysInMonth={31} startWeekday={5} todayDay={15} events={[ { day: 4, label: "Kickoff", color: "#7DD3E8" }, { day: 15, label: "Render day", color: "#9BD4A0" }, ]} holdSeconds={3.4} /> ``` The month comes from daysInMonth and startWeekday rather than from a date: a scene needs a month that looks right, not one correct for a particular year, and this keeps the component free of a date library and a timezone bug. Chips drop onto their day rather than fading in place, so a filling month reads as things being scheduled. One chip per day is the ceiling at 1080p. ## Props | Name | Type | Default | Description | | --- | --- | --- | --- | | `month` | `string` | `"August"` | Month name in the header. | | `year` | `string` | `"2026"` | Year beside the month. | | `daysInMonth` | `number` | `31` | How many day cells the month has. | | `startWeekday` | `number` | `5` | Column the 1st falls in, counting from Monday as 0. | | `todayDay` | `number` | `15` | Day given the accent ring. Pass -1 when the month is a plan. | | `events` | `CalendarEvent[]` | `7 sample events` | Day number, label and chip colour. One chip per day. | | `weekdayLabels` | `string[]` | `Mon–Sun` | Column headings; their count sets the grid width. | | `gridAtSeconds` | `number` | `0.3` | Second the empty grid starts sweeping up. | | `eventsAtSeconds` | `number` | `0.95` | Second the first event drops. | | `staggerSeconds` | `number` | `0.2` | Seconds between events. | | `holdSeconds` | `number` | - | Seconds the filled month holds before it retreats. Omit to leave it up. | | `accentColor` | `string` | `"#E8B86D"` | Today's ring, and the fallback chip colour. | | `backgroundColor` | `string` | - | Page behind the card. Defaults to the theme page colour. | | `theme` | `"dark" \| "light"` | `"dark"` | Surface palette. | | `speed` | `number` | `1` | Animation speed multiplier. | ## Related - [Gantt Timeline](https://remotionui.com/docs/components/gantt-timeline.md) - [Roadmap Lanes](https://remotionui.com/docs/components/roadmap-lanes.md) - [Weather Card](https://remotionui.com/docs/components/weather-card.md) ## Machine-readable references - Props and usage as JSON: https://remotionui.com/ai/components/calendar-month-fill.json - Component index: https://remotionui.com/ai/components.json --- # Callout Spotlight > A spotlight that is aimed. Mask, ping, connector, then the callout. Source: https://remotionui.com/docs/components/callout-spotlight ## Installation ```bash npx remotion-ui@latest add callout-spotlight ``` The frame dims and the mask closes in from the whole picture onto `target`, a ring pings the region once it lands, and only then does a connector draw out to the callout card: the eye is taken to the thing before it is told about it. `target` is in source pixels; give `sourceWidth`/`sourceHeight` when it was measured against a different size and it is scaled and clamped into the safe area. The card flips above the target when there is no room below. ## Usage ```tsx import { CalloutSpotlight } from "@/remotion/scenes/callout-spotlight"; <CalloutSpotlight kicker="Tutorial" title="Click export" target={{ x: 320, y: 180, width: 420, height: 180 }} /> ``` ## Props | Name | Type | Default | Description | | --- | --- | --- | --- | | `title` (required) | `string` | - | Callout headline. | | `kicker` | `string` | - | Small label above the headline. | | `subtitle` | `string` | - | Supporting line below the headline. | | `target` (required) | `SpotlightTarget` | - | Region to spotlight, in source pixels; clamped to the safe area. The card flips above it when bottom clearance is low. | | `backgroundSrc` | `string` | - | Screenshot or capture under the spotlight. | | `sourceWidth` | `number` | - | Size the target was measured against. Defaults to the composition. | | `sourceHeight` | `number` | - | As above, vertically. | | `dim` | `number` | `0.72` | How far the rest of the frame is knocked back, 0–1. | | `accentColor` | `string` | `"#E8B86D"` | Outline, ping, and connector colour. | | `theme` | `"dark" \| "light"` | `"dark"` | Surface palette. | | `speed` | `number` | `1` | Animation speed multiplier. | ## Related - [Zoom Pan Frame](https://remotionui.com/docs/components/zoom-pan-frame.md) - [Tutorial Clip](https://remotionui.com/docs/components/tutorial-clip.md) ## Machine-readable references - Props and usage as JSON: https://remotionui.com/ai/components/callout-spotlight.json - Component index: https://remotionui.com/ai/components.json --- # Caption Bumper > A between-beats card that punches its line in word by word. Source: https://remotionui.com/docs/components/caption-bumper ## Installation ```bash npx remotion-ui@latest add caption-bumper ``` The ground wipes in behind the line, the words land one after another out of their own masks, a rule draws under them, and the whole card wipes out again once `holdSeconds` is up. The type size is fitted to the safe area, so a three-word bumper and a twelve-word one both fill the frame. ## Usage ```tsx import { CaptionBumper } from "@/remotion/scenes/caption-bumper"; <CaptionBumper text="This is the key moment." /> ``` ## Props | Name | Type | Default | Description | | --- | --- | --- | --- | | `text` (required) | `string` | - | The line the bumper exists to land. | | `eyebrow` | `string` | - | Small label above it (segment, chapter, timestamp). | | `maxFontSize` | `number` | `84` | Largest type size at a 1280-wide stage. | | `holdSeconds` | `number` | - | Seconds before the card wipes out. Omit to hold to the end. | | `accentColor` | `string` | `"#F472B6"` | Ground, eyebrow, and rule colour. | | `theme` | `"dark" \| "light"` | `"dark"` | Surface palette. | | `speed` | `number` | `1` | Animation speed multiplier. | ## Related - [Karaoke Captions](https://remotionui.com/docs/components/karaoke-captions.md) - [Data Story](https://remotionui.com/docs/components/data-story.md) ## Machine-readable references - Props and usage as JSON: https://remotionui.com/ai/components/caption-bumper.json - Component index: https://remotionui.com/ai/components.json --- # Changelog Entry > A release note reading itself out. Version, a rule drawing under it, then each change behind its own coloured tag. Source: https://remotionui.com/docs/components/changelog-entry ## Installation ```bash npx remotion-ui@latest add changelog-entry ``` The version lands first at display size, a rule draws out from the left beneath it, and the changes follow one at a time. Each row's tag arrives a fraction before its sentence, because the kind of change is what a viewer scans for: by the time they read the sentence they already know whether it is an addition or a fix. Tags are fixed width rather than sized to their label. That is what lets every sentence share a left edge; a column of ragged text beside ragged tags is the fastest way to make a changelog look unmaintained. Kinds are `added`, `fixed`, `changed` and `removed`, each with its own colour (green, blue, amber, red), and `kindColors` overrides any of them without you having to supply the rest. The rule draws rather than fades. It reads as the header being underlined, which is a beat in the scene; a fading line reads as a transition and pulls attention away from the version it belongs to. Five or six rows is the ceiling before the card outgrows a 1080p frame. Split a larger release across two entries rather than shrinking the type. ## Usage ```tsx import { ChangelogEntry } from "@/remotion/scenes/changelog-entry"; <ChangelogEntry version="v2.4.0" date="16 August" summary="Captions, webhooks, and a queue that stops sulking." changes={[ { kind: "added", text: "Caption presets for nine languages" }, { kind: "fixed", text: "Retry backoff no longer stalls the queue" }, { kind: "removed", text: "Legacy waveform atom" }, ]} holdSeconds={3.4} /> ``` Tags are fixed width so every sentence shares a left edge: ragged text beside ragged tags is what makes a changelog look unmaintained. The tag lands before its sentence because the kind of change is what a viewer scans for. Five or six rows is the ceiling before the card outgrows a 1080p frame; split a larger release into two entries. ## Props | Name | Type | Default | Description | | --- | --- | --- | --- | | `changes` | `ChangeRow[]` | `5 sample changes` | A kind (added, fixed, changed or removed) and the sentence beside it. | | `version` | `string` | `"v2.4.0"` | Version string, set at display size. | | `date` | `string` | `"16 August"` | Date beside the version. | | `summary` | `string` | `"Captions, webhooks, and a queue that stops sulking."` | Headline under the version. Omit for releases without one. | | `kindColors` | `Partial<Record<ChangeKind, string>>` | `green / blue / amber / red` | Override any tag colour without supplying the rest. | | `startAtSeconds` | `number` | `0.66` | Second the first change row arrives. | | `staggerSeconds` | `number` | `0.28` | Seconds between rows. Each sentence trails its own tag by 0.08s. | | `holdSeconds` | `number` | - | Seconds the finished entry holds before it retreats. Omit to leave it up. | | `accentColor` | `string` | `"#E8B86D"` | Fallback tag colour for kinds with no colour set. | | `backgroundColor` | `string` | - | Page behind the card. Defaults to the theme page colour. | | `theme` | `"dark" \| "light"` | `"dark"` | Surface palette. | | `speed` | `number` | `1` | Animation speed multiplier. | ## Related - [Commit Graph](https://remotionui.com/docs/components/commit-graph.md) - [Feature List](https://remotionui.com/docs/components/feature-list.md) - [Roadmap Lanes](https://remotionui.com/docs/components/roadmap-lanes.md) ## Machine-readable references - Props and usage as JSON: https://remotionui.com/ai/components/changelog-entry.json - Component index: https://remotionui.com/ai/components.json --- # Comparison Table > A feature matrix that fills in the way you read it. Row by row, label first, each column's verdict a fraction behind the last. Source: https://remotionui.com/docs/components/comparison-table ## Installation ```bash npx remotion-ui@latest add comparison-table ``` Rows wipe in one at a time. Inside a row the label lands first and the cells follow at 0.07s intervals, so the eye tracks left to right across the row instead of taking it as a block, the same order a viewer would read it in anyway. Cells take three forms. `true` draws a tick, `false` draws a cross, and a string prints as-is for the rows where the answer is a number or a word rather than a yes. Ticks and crosses draw their own strokes rather than fading in: at the size a matrix forces, a fading glyph spends most of its entrance as grey mush, whereas a drawing one is sharp from its first frame. `highlightColumn` lights the tier you want picked. It is one band sitting behind the grid, not a background on each cell, so the rows can never disagree about where its edges are, and `highlightLabel` pins the chip that explains it beside the title. Six rows and three columns is a comfortable ceiling at 1080p; past that, the row height starts fighting the type size. For a single ticked list rather than a matrix, use `feature-list`, and for one tier on its own use `pricing-card`. ## Usage ```tsx import { ComparisonTable } from "@/remotion/scenes/comparison-table"; <ComparisonTable title="What you get" columns={["Free", "Studio", "Scale"]} rows={[ { label: "Render minutes", cells: ["60", "2,000", "Unlimited"] }, { label: "4K exports", cells: [false, true, true] }, { label: "Priority queue", cells: [false, false, true] }, ]} highlightColumn={1} highlightLabel="Most picked" holdSeconds={3.4} /> ``` Ticks and crosses draw their own strokes rather than fading: a fading glyph spends most of its entrance as grey mush at matrix sizes. The highlighted column is one lit band behind the grid, so rows can never disagree about where its edges are. For a single ticked list rather than a matrix, use feature-list. ## Props | Name | Type | Default | Description | | --- | --- | --- | --- | | `columns` | `string[]` | `["Free", "Studio", "Scale"]` | Column headings. The feature-label column is unnamed and sits ahead of these. | | `rows` | `MatrixRow[]` | `6 sample rows` | A label plus one cell per column: true ticks, false crosses, a string prints as-is. | | `title` | `string` | `"What you get"` | Heading above the table. Omit to drop it. | | `highlightColumn` | `number` | `1` | Column kept lit throughout. Pass -1 for a table with no favourite. | | `highlightLabel` | `string` | `"Most picked"` | Chip pinned beside the title, above the highlighted column. | | `startAtSeconds` | `number` | `0.5` | Second the first row wipes in. | | `rowStaggerSeconds` | `number` | `0.26` | Seconds between rows. Cells inside a row trail their label by another 0.07s each. | | `holdSeconds` | `number` | - | Seconds the finished table holds before it retreats. Omit to leave it up. | | `accentColor` | `string` | `"#E8B86D"` | Highlight band, its header, and the ticks inside it. | | `backgroundColor` | `string` | - | Page behind the card. Defaults to the theme page colour. | | `theme` | `"dark" \| "light"` | `"dark"` | Surface palette. | | `speed` | `number` | `1` | Animation speed multiplier. | ## Related - [Feature List](https://remotionui.com/docs/components/feature-list.md) - [Pricing Card](https://remotionui.com/docs/components/pricing-card.md) - [Pricing Focus](https://remotionui.com/docs/components/pricing-focus.md) ## Machine-readable references - Props and usage as JSON: https://remotionui.com/ai/components/comparison-table.json - Component index: https://remotionui.com/ai/components.json --- # Data Flow Pipes > A pipeline running end to end, with payloads hopping stage to stage. Source: https://remotionui.com/docs/components/data-flow-pipes ## Installation ```bash npx remotion-ui@latest add data-flow-pipes ``` Stages come up in dependency order, the pipes draw between them, and a stream of payloads travels hop by hop (lighting each stage as it lands, ticking that stage's tally, and filling its progress line) until the last stage drains and checks off. `stages` takes two to five `{ label, detail }` entries, `packets` sets how many payloads are pushed through, and `unit` names what is being counted. ## Usage ```tsx import { DataFlowPipes } from "@/remotion/scenes/data-flow-pipes"; <DataFlowPipes stages={[{ label: "Ingest" }, { label: "Deliver" }]} /> ``` ## Props | Name | Type | Default | Description | | --- | --- | --- | --- | | `stages` | `PipeStage[]` | - | Stages in order, each { label, detail }. Two to five read best. | | `unit` | `string` | `"clips"` | Unit counted at each stage. | | `packets` | `number` | `9` | Payloads pushed through the pipeline. | | `accentColor` | `string` | `"#2DD4BF"` | Pipe, packet, and node colour. | | `backgroundColor` | `string` | - | Overrides the page background. | | `theme` | `"dark" \| "light"` | `"dark"` | Surface palette. | | `speed` | `number` | `1` | Animation speed multiplier. | ## Related - [Timeline Steps](https://remotionui.com/docs/components/timeline-steps.md) - [Metric Ticker](https://remotionui.com/docs/components/metric-ticker.md) ## Machine-readable references - Props and usage as JSON: https://remotionui.com/ai/components/data-flow-pipes.json - Component index: https://remotionui.com/ai/components.json --- # End Card > The outro, built in the order a viewer acts on it. Source: https://remotionui.com/docs/components/end-card ## Installation ```bash npx remotion-ui@latest add end-card ``` The title rises out of its mask, the button assembles and its label rises out of the button, the address types underneath a caret that clears when it completes, the channels list, and a single ring pulses off the button. `cta`, `url`, `handles`, `logoSrc`, `eyebrow` and `subtitle` are each optional: omit them and the card ends on what is left. ## Usage ```tsx import { EndCard } from "@/remotion/scenes/end-card"; <EndCard title="Thanks for watching" cta="Subscribe" url="youtube.com" /> ``` ## Props | Name | Type | Default | Description | | --- | --- | --- | --- | | `title` (required) | `string` | - | Closing headline. | | `subtitle` | `string` | - | Line under the title. | | `eyebrow` | `string` | - | Chip above the title. | | `cta` | `string` | - | Button label. Omit to end on the title alone. | | `url` | `string` | - | Address typed under the button. | | `handles` | `string[]` | - | Handles or channels listed along the foot. | | `logoSrc` | `string` | - | Brand mark image (staticFile or URL). | | `accentColor` | `string` | `"#E8B86D"` | Button, pulse, and eyebrow colour. | | `theme` | `"dark" \| "light"` | `"dark"` | Surface palette. | | `speed` | `number` | `1` | Animation speed multiplier. | ## Related - [Title Card](https://remotionui.com/docs/components/title-card.md) - [Intro](https://remotionui.com/docs/components/intro.md) ## Machine-readable references - Props and usage as JSON: https://remotionui.com/ai/components/end-card.json - Component index: https://remotionui.com/ai/components.json --- # Feature List > A list being ticked off, row by row. Source: https://remotionui.com/docs/components/feature-list ## Installation ```bash npx remotion-ui@latest add feature-list ``` Each row arrives in turn: its rule draws across, the row settles in behind it, and its check strokes in, so the scene ends on a list that has visibly been worked through rather than one that faded in. `items` takes plain strings or `{ label, detail }` objects when a row needs a second line. ## Usage ```tsx import { FeatureList } from "@/remotion/scenes/feature-list"; <FeatureList title="Why RemotionUI" items={["Own your components", "Live previews", "CLI workflow"]} /> ``` Self-contained scene. Uses layout and motion-tokens helpers only. ## Props | Name | Type | Default | Description | | --- | --- | --- | --- | | `items` (required) | `(string \| FeatureItem)[]` | - | Rows, as strings or { label, detail }. Up to five are shown. | | `title` | `string` | - | Section heading. | | `eyebrow` | `string` | - | Small label above the heading. | | `accentColor` | `string` | `"#E8B86D"` | Check and eyebrow colour. | | `theme` | `"dark" \| "light"` | `"dark"` | Surface palette. | | `speed` | `number` | `1` | Animation speed multiplier. | ## Related - [Stat Card](https://remotionui.com/docs/components/stat-card.md) - [Showcase](https://remotionui.com/docs/components/showcase.md) ## Machine-readable references - Props and usage as JSON: https://remotionui.com/ai/components/feature-list.json - Component index: https://remotionui.com/ai/components.json --- # Logo Wall > A client wall that comes up to colour. Tiles land grey, then warm to their brand colours on a diagonal sweep. Source: https://remotionui.com/docs/components/logo-wall ## Installation ```bash npx remotion-ui@latest add logo-wall ``` Tiles arrive quickly in reading order so the wall is whole within a second, and then the colour sweeps across it diagonally. Splitting the two is the whole trick: if the arrival is the slow part, the scene spends its first beats looking half-built, and the greyscale-to-colour idea never gets a stage to happen on. The sweep is driven by `row + column` rather than by index, so it crosses the wall as a wave at any grid width instead of running down it like a list. Grey is produced by one `saturate()` on the tile, not by a second set of grey colours. The wordmark and the mark both carry their brand colour the whole time and the filter takes it away, so the monochrome stage is a true desaturation of the finished tile: swap in your own colours and the grey stage follows for free. Brightness moves with saturation, because a desaturated tile at full brightness looks muddy rather than monochrome. Wordmarks are text, so there are no image assets to bundle or fail to load in a headless render. Pass `glyph` when a brand's mark is not just its first letter. ## Usage ```tsx import { LogoWall } from "@/remotion/scenes/logo-wall"; <LogoWall eyebrow="Trusted by" title="Teams shipping with RemotionUI" logos={[ { name: "Northstar", color: "#E8B86D" }, { name: "Halcyon", color: "#7DD3E8" }, { name: "Fernweh", color: "#9BD4A0" }, { name: "Orbital", color: "#C99BE8" }, ]} holdSeconds={3.4} /> ``` Arrival and colour are separate beats on purpose: tiles land fast so the wall is whole within a second, then the colour sweeps the diagonal across it. Grey is one saturate() on the tile rather than a second set of grey colours, so swapping in your own brand colours brings the monochrome stage with it. Wordmarks are text: no image assets to bundle or fail to load in a headless render. ## Props | Name | Type | Default | Description | | --- | --- | --- | --- | | `logos` | `WallLogo[]` | `8 sample brands` | Wordmark, brand colour, and the glyph in the mark beside it. | | `eyebrow` | `string` | `"Trusted by"` | Small line above the heading. Omit to drop it. | | `title` | `string` | `"Teams shipping with RemotionUI"` | Heading above the wall. Omit to drop it. | | `columns` | `number` | `4` | Tiles per row. | | `startAtSeconds` | `number` | `0.32` | Second the first tile arrives. | | `arriveStaggerSeconds` | `number` | `0.06` | Seconds between tiles arriving, in reading order. Deliberately fast. | | `staggerSeconds` | `number` | `0.24` | Seconds between diagonals of the colour sweep. | | `warmSeconds` | `number` | `0.6` | How long one tile takes to go from grey to brand colour. | | `holdSeconds` | `number` | - | Seconds the finished wall holds before it retreats. Omit to leave it up. | | `accentColor` | `string` | `"#E8B86D"` | Eyebrow, and the fallback for logos with no colour. | | `backgroundColor` | `string` | - | Page behind the wall. Defaults to the theme page colour. | | `theme` | `"dark" \| "light"` | `"dark"` | Surface palette. | | `speed` | `number` | `1` | Animation speed multiplier. | ## Related - [Team Grid](https://remotionui.com/docs/components/team-grid.md) - [Feature List](https://remotionui.com/docs/components/feature-list.md) - [Comparison Table](https://remotionui.com/docs/components/comparison-table.md) ## Machine-readable references - Props and usage as JSON: https://remotionui.com/ai/components/logo-wall.json - Component index: https://remotionui.com/ai/components.json --- # Lower Third > A name plate that wipes on, holds, and retreats the way it came. Source: https://remotionui.com/docs/components/lower-third ## Installation ```bash npx remotion-ui@latest add lower-third ``` The plate wipes out from the frame edge, the name rises out of its own mask, the role and badge settle, and with `holdSeconds` set it retreats the same way instead of being left standing for the rest of the cut. `align` picks the edge it comes from. Overlay it on footage with an `AbsoluteFill`; it renders nothing but the plate. ## Usage ```tsx import { LowerThird } from "@/remotion/scenes/lower-third"; <LowerThird title="Jane Doe" subtitle="Product Designer" accentColor="#f97316" align="left" /> ``` Transparent overlay scene designed to sit over footage. ## Props | Name | Type | Default | Description | | --- | --- | --- | --- | | `title` (required) | `string` | - | Primary line. | | `subtitle` | `string` | - | Secondary line. | | `badge` | `string` | - | Small tag on the plate (LIVE, EP 12, the segment). | | `align` | `"left" \| "right"` | `"left"` | Edge the plate wipes out from. | | `holdSeconds` | `number` | - | Seconds before the plate retreats. Omit to leave it on screen. | | `accentColor` | `string` | `"#E8B86D"` | Badge colour. | | `backgroundColor` | `string` | - | Overrides the plate background. | | `theme` | `"dark" \| "light"` | `"dark"` | Surface palette. | | `speed` | `number` | `1` | Animation speed multiplier. | ## Related - [Title Card](https://remotionui.com/docs/components/title-card.md) - [End Card](https://remotionui.com/docs/components/end-card.md) ## Machine-readable references - Props and usage as JSON: https://remotionui.com/ai/components/lower-third.json - Component index: https://remotionui.com/ai/components.json --- # Media Frame > One piece of media presented. The frame opens on it under a slow push. Source: https://remotionui.com/docs/components/media-frame ## Installation ```bash npx remotion-ui@latest add media-frame ``` The frame opens like a shutter on the media while a slow push runs underneath, then the title masks up out of its own line and the caption settles beneath. The frame is cut to `aspect` (16:9 by default) and centred, so `contain` media fills it instead of sitting in a letterbox, and the layout reserves only what is shown. With no title and no caption, the frame owns the whole safe area. ## Usage ```tsx import { MediaFrame } from "@/remotion/scenes/media-frame"; <MediaFrame src={staticFile("demo.png")} title="Product demo" /> ``` Advanced. Installs @remotion/media for video sources. ## Props | Name | Type | Default | Description | | --- | --- | --- | --- | | `src` (required) | `string` | - | Image or video source. | | `title` | `string` | - | Headline above the frame; masks up out of its own line. | | `caption` | `string` | - | Supporting line under the frame. | | `eyebrow` | `string` | - | Small label above the title. | | `fit` | `"cover" \| "contain"` | `"contain"` | Media object-fit behaviour. Use contain for UI screenshots. | | `aspect` | `number` | `16 / 9` | Aspect the frame is cut to, so contain media fills it. | | `radius` | `number` | - | Corner radius in composition pixels. | | `accentColor` | `string` | `"#E8B86D"` | Rim light and eyebrow colour. | | `theme` | `"dark" \| "light"` | `"dark"` | Surface palette. | | `speed` | `number` | `1` | Animation speed multiplier. | ## Related - [Media Sequence](https://remotionui.com/docs/components/media-sequence.md) - [Split Screen](https://remotionui.com/docs/components/split-screen.md) ## Machine-readable references - Props and usage as JSON: https://remotionui.com/ai/components/media-frame.json - Component index: https://remotionui.com/ai/components.json --- # Media Sequence > An edited run of shots with a chapter strip showing where you are. Source: https://remotionui.com/docs/components/media-sequence ## Installation ```bash npx remotion-ui@latest add media-sequence ``` Each item is pushed on by the next through a `TransitionSeries` of [Media Frame](https://remotionui.com/docs/components/media-frame.md), and a chapter strip along the foot fills through the item that is playing and stays filled behind it. Set `transition` to `fade` for a dissolve instead of a push, `showProgress` to drop the strip, and per-item `durationInFrames` to hold a shot longer. ## Usage ```tsx import { MediaSequence } from "@/remotion/scenes/media-sequence"; <MediaSequence items={[{ src: staticFile("one.png"), title: "Hook" }]} /> ``` ## Props | Name | Type | Default | Description | | --- | --- | --- | --- | | `items` (required) | `MediaItem[]` | - | Timed media items. | | `defaultDurationInFrames` | `number` | `78` | Length of an item that sets no duration of its own. | | `transitionDurationInFrames` | `number` | `14` | Overlap between neighbouring items. | | `transition` | `"slide" \| "fade"` | `"slide"` | Push the next item on, or dissolve to it. | | `showProgress` | `boolean` | `true` | Chapter strip along the foot. | | `aspect` | `number` | `16 / 9` | Aspect the frames are cut to. | | `accentColor` | `string` | `"#E8B86D"` | Strip fill and frame rim colour. | | `theme` | `"dark" \| "light"` | `"dark"` | Surface palette. | ## Related - [Media Frame](https://remotionui.com/docs/components/media-frame.md) - [Tutorial Clip](https://remotionui.com/docs/components/tutorial-clip.md) ## Machine-readable references - Props and usage as JSON: https://remotionui.com/ai/components/media-sequence.json - Component index: https://remotionui.com/ai/components.json --- # News Ticker Bar > A broadcast lower bar with a standing flag and a headline crawl. Source: https://remotionui.com/docs/components/news-ticker-bar ## Installation ```bash npx remotion-ui@latest add news-ticker-bar ``` The bar rises from the frame edge, the flag wipes out ahead of the crawl, and the headlines run continuously: two copies of the run chase each other so the loop never shows a seam. Headlines dissolve into the right edge instead of being sliced off against the dateline. `infinite-marquee` is the generic looping-text primitive. This is the dressed news bar built on the same idea, with the flag, strapline and timestamp furniture a broadcast frame needs. Drop `strapline` for a single-line bar. Crawl speed is `pixelsPerSecond` in layout units, so it stays consistent across frame sizes. ## Usage ```tsx import { NewsTickerBar } from "@/remotion/scenes/news-ticker-bar"; <NewsTickerBar flag="Breaking" headlines={["Registry crosses 165 components", "CLI adds batch install"]} strapline="Live from the newsroom" timestamp="21:04" /> ``` Transparent overlay scene designed to sit over footage. infinite-marquee is the generic looping-text primitive; this is the dressed news bar with the chrome a broadcast frame needs. ## Props | Name | Type | Default | Description | | --- | --- | --- | --- | | `headlines` (required) | `string[]` | - | Headlines cycled through the crawl, separated by a bullet. | | `flag` | `string` | `"Breaking"` | Standing flag on the left (BREAKING, MARKETS, LIVE). | | `strapline` | `string` | - | Second line under the crawl. Omit for a single-line bar. | | `timestamp` | `string` | - | Clock or dateline pinned to the right edge. Omit to hide it. | | `pixelsPerSecond` | `number` | `118` | Crawl speed in units per second. | | `accentColor` | `string` | `"#F97362"` | Flag fill and top rule colour. | | `theme` | `"dark" \| "light"` | `"dark"` | Surface palette. | | `holdSeconds` | `number` | - | Seconds the bar holds before it retreats. Omit to leave it up. | | `speed` | `number` | `1` | Animation speed multiplier. | ## Related - [Infinite Marquee](https://remotionui.com/docs/components/infinite-marquee.md) - [Lower Third](https://remotionui.com/docs/components/lower-third.md) - [Sports Scorebug](https://remotionui.com/docs/components/sports-scorebug.md) ## Machine-readable references - Props and usage as JSON: https://remotionui.com/ai/components/news-ticker-bar.json - Component index: https://remotionui.com/ai/components.json --- # Org Chart Build > A hierarchy assembling top-down. Connectors draw down from the parents already standing, and nodes land on the ends of the lines. Source: https://remotionui.com/docs/components/org-chart-build ## Installation ```bash npx remotion-ui@latest add org-chart-build ``` The root lands, its connectors draw downward, and the next level's nodes arrive on the ends of those lines, so the chart builds the way someone would draw it, rather than fading in as a finished diagram. Every connector leads its child by about a third of a second, which is long enough to read as cause and effect and short enough that the chart never feels like it is waiting. Positions come from a leaf walk rather than a grid. Leaves are spread evenly across the width and each parent centres over the span of its own children, so a lopsided tree (three reports on one side, one on the other) stays balanced without any node needing to know its siblings' widths. Connectors are elbows, not diagonals. Org charts are read as columns of authority; a straight line between two boxes reads as a relationship of a different kind entirely. Nodes are a flat array with `parent` indices, which keeps the data trivially serialisable: parents must appear before their children. Depth picks the node's colour from `levelColors`, so a fourth level reuses the last entry rather than running out. ## Usage ```tsx import { OrgChartBuild } from "@/remotion/scenes/org-chart-build"; <OrgChartBuild title="How the team is wired" nodes={[ { name: "Ada Okonjo", role: "Founder" }, { name: "Piotr Nowak", role: "Engineering", parent: 0 }, { name: "Dai Nakamura", role: "Design", parent: 0 }, { name: "Sam Rhodes", role: "Infrastructure", parent: 1 }, ]} holdSeconds={3.4} /> ``` Positions come from a leaf walk rather than a grid: leaves spread evenly and each parent centres over the span of its own children, so a lopsided tree stays balanced. Connectors are elbows, not diagonals: a straight line between two boxes reads as a different kind of relationship entirely. Three levels fits 1080p comfortably; a fourth wants a taller frame rather than a smaller node. ## Props | Name | Type | Default | Description | | --- | --- | --- | --- | | `nodes` | `OrgNode[]` | `a 7-person tree` | Name, role and a `parent` index. Omit parent for the root; parents must appear before their children. | | `title` | `string` | `"How the team is wired"` | Heading above the chart. Omit to drop it. | | `startAtSeconds` | `number` | `0.34` | Second the root lands. | | `levelStaggerSeconds` | `number` | `0.62` | Seconds between levels. Connectors lead their child by 0.34s inside that gap. | | `siblingStaggerSeconds` | `number` | `0.12` | Seconds between siblings, ordered left to right by position. | | `holdSeconds` | `number` | - | Seconds the finished chart holds before it retreats. Omit to leave it up. | | `accentColor` | `string` | `"#E8B86D"` | Role line on the root. | | `levelColors` | `string[]` | `3 depth colours` | One colour per depth. Deeper levels reuse the last entry. | | `backgroundColor` | `string` | - | Page behind the chart. Defaults to the theme page colour. | | `theme` | `"dark" \| "light"` | `"dark"` | Surface palette. | | `speed` | `number` | `1` | Animation speed multiplier. | ## Related - [Team Grid](https://remotionui.com/docs/components/team-grid.md) - [Commit Graph](https://remotionui.com/docs/components/commit-graph.md) - [Roadmap Lanes](https://remotionui.com/docs/components/roadmap-lanes.md) ## Machine-readable references - Props and usage as JSON: https://remotionui.com/ai/components/org-chart-build.json - Component index: https://remotionui.com/ai/components.json --- # Pricing Card > A tier card that earns its price. The number rolls up, the features tick in beneath it, and the call to action arrives last. Source: https://remotionui.com/docs/components/pricing-card ## Installation ```bash npx remotion-ui@latest add pricing-card ``` The price counts up under a soft blur that clears as it settles, the features tick in one at a time, and the button lands after the last of them, so the card finishes on the thing you want clicked rather than on a feature line. The roll is a plain interpolation on the value, not a spinning digit strip. A strip has to guess glyph widths to keep its columns aligned; a counted number stays in register with `tabular-nums` at any font size, and it reads as counting rather than as a slot machine. Pass `wasPrice` when there is a before-and-after to tell: it strikes through beside the new number once the roll is most of the way home. The call to action is scheduled off the last feature, not off a fixed second, so adding features pushes the button later instead of colliding with it. If you need the whole card inside a tighter cut, lower `featureStaggerSeconds` before you touch `rollSeconds`: the roll is the beat people watch. This is one card at block grain. For a full tier-comparison beat with a composition's pacing around it, use `pricing-focus`; for a side-by-side matrix, use `comparison-table`. ## Usage ```tsx import { PricingCard } from "@/remotion/scenes/pricing-card"; <PricingCard tier="Studio" badge="Most picked" price={32} period="/mo" note="Billed annually. Cancel whenever." features={["2,000 render minutes a month", "4K exports, no watermark", "9 team seats"]} ctaLabel="Start rendering" holdSeconds={3.4} /> ``` The price is a counted number under a blur that clears as it settles, not a spinning digit strip: a strip has to guess glyph widths, a counted number stays in register with tabular-nums at any size. The CTA is scheduled off the last feature, so adding features pushes the button later rather than colliding with it. This is one card at block grain; for a full tier comparison beat, use pricing-focus. ## Props | Name | Type | Default | Description | | --- | --- | --- | --- | | `tier` | `string` | `"Studio"` | Tier name across the top of the card. | | `price` | `number` | `32` | The number the price rolls up to. | | `currency` | `string` | `"$"` | Symbol set ahead of the number. | | `period` | `string` | `"/mo"` | Cadence after the price: "/mo", "per seat", anything short. | | `badge` | `string` | `"Most picked"` | Chip beside the tier name. Omit to drop it. | | `note` | `string` | `"Billed annually. Cancel whenever."` | Line under the price. | | `wasPrice` | `number` | - | Old price, struck through beside the new one. Omit when there is no before-and-after. | | `features` | `string[]` | `5 sample features` | Ticked lines under the price, revealed in order. | | `ctaLabel` | `string` | `"Start rendering"` | Button text. Omit to drop the button. | | `priceAtSeconds` | `number` | `0.42` | Second the price starts rolling. | | `rollSeconds` | `number` | `0.9` | How long the roll takes. | | `featuresAtSeconds` | `number` | `1.05` | Second the first feature ticks in. | | `featureStaggerSeconds` | `number` | `0.22` | Seconds between features. The CTA lands 0.16s after the last one. | | `holdSeconds` | `number` | - | Seconds the finished card holds before it retreats. Omit to leave it up. | | `accentColor` | `string` | `"#E8B86D"` | Badge, ticks, card border wash and the CTA fill. | | `backgroundColor` | `string` | - | Page behind the card. Defaults to the theme page colour. | | `theme` | `"dark" \| "light"` | `"dark"` | Surface palette. | | `speed` | `number` | `1` | Animation speed multiplier. | ## Related - [Pricing Focus](https://remotionui.com/docs/components/pricing-focus.md) - [Comparison Table](https://remotionui.com/docs/components/comparison-table.md) - [Feature List](https://remotionui.com/docs/components/feature-list.md) ## Machine-readable references - Props and usage as JSON: https://remotionui.com/ai/components/pricing-card.json - Component index: https://remotionui.com/ai/components.json --- # Quiz Question > A question that resolves. Options arrive, one is picked, then the right answer lights while the rest step back. Source: https://remotionui.com/docs/components/quiz-question ## Installation ```bash npx remotion-ui@latest add quiz-question ``` Options arrive one at a time, the scene picks one, and only then does the right answer light up. Keeping the pick and the reveal as separate beats is the whole design: the eye needs to have settled on a choice before it can register being told it was wrong, and quiz scenes that resolve in a single frame are unreadable at social speeds. Three states are drawn (picked, right, wrong), and correct always wins where they overlap, so `pickedIndex === correctIndex` gives you a scene where the pick is right. Pass `pickedIndex={-1}` for a reveal with no pick at all. On the reveal, every option that is neither picked nor correct steps back rather than changing colour. The resolution then reads as focus narrowing, which is what a viewer is actually doing, instead of as three new colours arriving at once. Four options is the readable maximum at 1080p, and shorter than about six words each. This is the shape with a right answer; for audience voting with no correct option, use `poll-overlay`. ## Usage ```tsx import { QuizQuestion } from "@/remotion/scenes/quiz-question"; <QuizQuestion question="What does the RemotionUI CLI actually do?" options={[ "It bundles a runtime you ship", "It copies the source into your repo", "It renders on our servers", ]} correctIndex={1} pickedIndex={2} holdSeconds={3.4} /> ``` The pick and the reveal are deliberately separate beats: the eye has to settle on a choice before it can register being told it was wrong. On the reveal everything neither picked nor correct steps back rather than changing colour, so the resolution reads as focus narrowing. For audience voting with no right answer, use poll-overlay. ## Props | Name | Type | Default | Description | | --- | --- | --- | --- | | `question` | `string` | `"What does the RemotionUI CLI actually do?"` | The question, set at display size. | | `options` | `string[]` | `4 sample answers` | Answer options in display order. Four is the readable maximum at 1080p. | | `correctIndex` | `number` | `1` | Index of the right answer. | | `pickedIndex` | `number` | `2` | Index picked before the reveal. Set it to correctIndex for a right pick, -1 for none. | | `eyebrow` | `string` | `"Question 3 of 8"` | Small line above the question. Omit to drop it. | | `optionsAtSeconds` | `number` | `0.55` | Second the first option arrives. | | `staggerSeconds` | `number` | `0.2` | Seconds between options. | | `pickAtSeconds` | `number` | `1.75` | Second the pick lands. | | `revealAtSeconds` | `number` | `2.35` | Second the right answer is revealed. | | `holdSeconds` | `number` | - | Seconds the resolved question holds before it retreats. Omit to leave it up. | | `accentColor` | `string` | `"#E8B86D"` | Eyebrow, and the picked-but-not-yet-resolved state. | | `correctColor` | `string` | `"#7FD1A0"` | The right answer on reveal. | | `wrongColor` | `string` | `"#E89B9B"` | A wrong pick on reveal. | | `backgroundColor` | `string` | - | Page behind the card. Defaults to the theme page colour. | | `theme` | `"dark" \| "light"` | `"dark"` | Surface palette. | | `speed` | `number` | `1` | Animation speed multiplier. | ## Related - [Poll Overlay](https://remotionui.com/docs/components/poll-overlay.md) - [Comparison Table](https://remotionui.com/docs/components/comparison-table.md) - [Reaction Burst](https://remotionui.com/docs/components/reaction-burst.md) ## Machine-readable references - Props and usage as JSON: https://remotionui.com/ai/components/quiz-question.json - Component index: https://remotionui.com/ai/components.json --- # Quote Card > A pull quote read aloud. Mark, lines, marker sweep, attribution. Source: https://remotionui.com/docs/components/quote-card ## Installation ```bash npx remotion-ui@latest add quote-card ``` The quote mark draws, the quote rises line by line out of its own masks, a marker sweeps the `emphasis` phrase word by word, and the attribution arrives last with its initials disc. `emphasis` is matched over the whole quote and sliced per line, so a phrase that spans a line break still reads as one stroke. ## Usage ```tsx import { QuoteCard } from "@/remotion/scenes/quote-card"; <QuoteCard quote="The best motion is code you can read and change" emphasis="motion" author="Team" /> ``` ## Props | Name | Type | Default | Description | | --- | --- | --- | --- | | `quote` (required) | `string` | - | Quote body. | | `emphasis` | `string` | - | Phrase swept with a marker; matched over the whole quote, so it may span a line break. | | `author` | `string` | - | Attribution name. | | `role` | `string` | - | Second attribution line (role, company, handle). | | `initials` | `string` | - | Initials in the attribution disc. Defaults to the author's. | | `charsPerLine` | `number` | `30` | Characters per line the quote balances to. | | `accentColor` | `string` | `"#F472B6"` | Mark, marker, and disc colour. | | `theme` | `"dark" \| "light"` | `"dark"` | Surface palette. | | `speed` | `number` | `1` | Animation speed multiplier. | ## Related - [text-emphasis](https://remotionui.com/docs/components/text-emphasis.md) - [Title Card](https://remotionui.com/docs/components/title-card.md) ## Machine-readable references - Props and usage as JSON: https://remotionui.com/ai/components/quote-card.json - Component index: https://remotionui.com/ai/components.json --- # Roadmap Lanes > Swimlanes of shipped, building and planned work, each lane filling in turn and in-flight items growing to their real progress. Source: https://remotionui.com/docs/components/roadmap-lanes ## Installation ```bash npx remotion-ui@latest add roadmap-lanes ``` Lanes fill one after another. Items in a `done` lane land already ticked, items in a `showProgress` lane land empty and then fill to their own `progress` value, and items in a `dashed` lane arrive outlined and unlit: three states that are readable in a still frame, not just in motion. The fill starts *after* the pill has landed, and takes longer than the arrival did. A bar that grows while its pill is still moving reads as one blurred event; letting the pill settle first turns the progress into a second beat the eye can follow, and the percentage counting up beside it has somewhere to land. Lane appearance is driven by flags rather than by lane name, so the three defaults (Shipped, Building, Planned) are a starting point, not a contract. A "Blocked" lane is `dashed` with a red `color`; a "Next up" lane is `showProgress` with low values. Three items per lane at three lanes is the comfortable maximum at 1080p; the item width is divided from the board, so a fourth item shortens every label rather than wrapping. ## Usage ```tsx import { RoadmapLanes } from "@/remotion/scenes/roadmap-lanes"; <RoadmapLanes title="What we are building" lanes={[ { title: "Shipped", color: "#9BD4A0", done: true, items: [{ label: "Render API" }] }, { title: "Building", color: "#E8B86D", showProgress: true, items: [{ label: "Timeline scrubber", progress: 0.72 }], }, { title: "Planned", color: "#7A828F", dashed: true, items: [{ label: "Stem export" }] }, ]} holdSeconds={3.4} /> ``` Lane appearance comes from flags, not from lane names: a blocked lane is `dashed` with a red colour, a next-up lane is `showProgress` with low values. The fill starts after the pill lands and takes longer than the arrival, so progress is a second beat rather than a blur inside the first. Three items per lane is the comfortable maximum at 1080p; item width divides the board rather than wrapping. ## Props | Name | Type | Default | Description | | --- | --- | --- | --- | | `lanes` | `RoadmapLane[]` | `Shipped / Building / Planned` | Title, colour, items, and the flags that set the lane's state: done, showProgress, dashed. | | `title` | `string` | `"What we are building"` | Heading above the lanes. Omit to drop it. | | `startAtSeconds` | `number` | `0.42` | Second the first lane's items arrive. | | `laneStaggerSeconds` | `number` | `0.42` | Seconds between lanes. | | `itemStaggerSeconds` | `number` | `0.14` | Seconds between items inside a lane. | | `fillSeconds` | `number` | `0.8` | How long a progress bar takes to reach its value, starting 0.3s after the pill lands. | | `holdSeconds` | `number` | - | Seconds the settled roadmap holds before it retreats. Omit to leave it up. | | `accentColor` | `string` | `"#E8B86D"` | Fallback colour for lanes with none of their own. | | `backgroundColor` | `string` | - | Page behind the lanes. Defaults to the theme page colour. | | `theme` | `"dark" \| "light"` | `"dark"` | Surface palette. | | `speed` | `number` | `1` | Animation speed multiplier. | ## Related - [Kanban Move](https://remotionui.com/docs/components/kanban-move.md) - [Timeline Steps](https://remotionui.com/docs/components/timeline-steps.md) - [Changelog Entry](https://remotionui.com/docs/components/changelog-entry.md) ## Machine-readable references - Props and usage as JSON: https://remotionui.com/ai/components/roadmap-lanes.json - Component index: https://remotionui.com/ai/components.json --- # Split Screen > A before/after that is actually made, not just placed side by side. Source: https://remotionui.com/docs/components/split-screen ## Installation ```bash npx remotion-ui@latest add split-screen ``` The two panels arrive from opposite edges and meet at the divider, their labels land, and with `wipeAtSeconds` set the divider travels back to the left edge, wiping the left panel away and leaving the right one whole: the move a comparison is for. The left label leaves with the panel it names. The right panel sits underneath, so the wipe uncovers it rather than sliding it. `split` sets where the divider rests beforehand, and `holdSeconds` takes the whole comparison off screen. Omit it inside a `TransitionSeries`, where the transition covers the tail. Pass video sources and the panels play; the scene sets `pauseWhenBuffering` on them, so add `premountFor` on the wrapping `<Sequence>` to have both streams buffered before the comparison starts: ```tsx <Sequence durationInFrames={120} premountFor={30}> <SplitScreen left={{ src: staticFile("before.mp4"), label: "Prototype" }} right={{ src: staticFile("after.mp4"), label: "Final clip" }} wipeAtSeconds={1.6} /> </Sequence> ``` ## Usage ```tsx import { SplitScreen } from "@/remotion/scenes/split-screen"; <SplitScreen left={{ src: before }} right={{ src: after }} /> ``` ## Props | Name | Type | Default | Description | | --- | --- | --- | --- | | `left` (required) | `SplitScreenPanel` | - | Left panel: { src, label, fit }. | | `right` (required) | `SplitScreenPanel` | - | Right panel; sits underneath so the wipe uncovers it. | | `title` | `string` | - | Headline above the comparison. | | `wipeAtSeconds` | `number` | - | When the divider travels right to leave the right panel whole. | | `split` | `number` | `0.5` | Where the divider rests before any wipe, 0–1. | | `accentColor` | `string` | `"#E8B86D"` | Divider and label colour. | | `theme` | `"dark" \| "light"` | `"dark"` | Surface palette. | | `speed` | `number` | `1` | Animation speed multiplier. | ## Related - [Media Frame](https://remotionui.com/docs/components/media-frame.md) - [B-Roll Stack](https://remotionui.com/docs/components/b-roll-stack.md) ## Machine-readable references - Props and usage as JSON: https://remotionui.com/ai/components/split-screen.json - Component index: https://remotionui.com/ai/components.json --- # Sports Scorebug > Broadcast score furniture with a live clock and scores that land. Source: https://remotionui.com/docs/components/sports-scorebug ## Installation ```bash npx remotion-ui@latest add sports-scorebug ``` The bug wipes in from its own edge, the game clock counts down live off `clockSeconds`, and points listed in `changes` land mid-scene, bumping the total and flashing that side rather than silently swapping the number. Each entry in `changes` is a side, a time in seconds, and the points to add, so the scores you pass in `home` and `away` are the values at the top of the scene, not the final ones. Anything not yet reached has not happened at that frame. It renders nothing but the bug, so overlay it straight onto footage. `align` moves it to whichever corner the frame leaves free, `scale` sizes the whole bug against the feed behind it, and `holdSeconds` retreats it the way it came. ## Usage ```tsx import { SportsScorebug } from "@/remotion/scenes/sports-scorebug"; <SportsScorebug away={{ abbr: "NOR", score: 66, color: "#7DD3E8" }} home={{ abbr: "VAL", score: 71, color: "#E8B86D", possession: true }} period="Q4" clockSeconds={154} changes={[{ side: "away", atSeconds: 1.1, points: 3 }]} /> ``` Transparent overlay scene designed to sit over footage. Points landing mid-scene bump the total and flash that side rather than silently swapping the number. ## Props | Name | Type | Default | Description | | --- | --- | --- | --- | | `home` (required) | `ScorebugTeam` | - | Home side: abbreviation, score, colour, possession. | | `away` (required) | `ScorebugTeam` | - | Away side: abbreviation, score, colour, possession. | | `period` | `string` | `"Q3"` | Period furniture (Q3, 2ND HALF, SET 2). | | `clockSeconds` | `number` | `154` | Game clock at the top of the scene, in seconds. Counts down. | | `changes` | `ScoreChange[]` | `[]` | Scores landing mid-scene. Each flashes its side and bumps the total. | | `align` | `"left" \| "center" \| "right"` | `"center"` | Edge the bug sits against. | | `accentColor` | `string` | `"#E8B86D"` | Period label and possession dot colour. | | `theme` | `"dark" \| "light"` | `"dark"` | Surface palette. | | `holdSeconds` | `number` | - | Seconds the bug holds before it retreats. Omit to leave it up. | | `speed` | `number` | `1` | Animation speed multiplier. | ## Related - [Countdown Timer](https://remotionui.com/docs/components/countdown-timer.md) - [Lower Third](https://remotionui.com/docs/components/lower-third.md) - [News Ticker Bar](https://remotionui.com/docs/components/news-ticker-bar.md) ## Machine-readable references - Props and usage as JSON: https://remotionui.com/ai/components/sports-scorebug.json - Component index: https://remotionui.com/ai/components.json --- # Stat Card > A number landing. Ring, counter, label, and the change behind it. Source: https://remotionui.com/docs/components/stat-card ## Installation ```bash npx remotion-ui@latest add stat-card ``` The ring fills while the counter rolls up under it, the label settles, and `delta` lands last, after the number it qualifies has stopped moving. Pass `max` when the value is a share and the ring becomes a meter filling to `value / max`. Leave it out for a count and the ring draws a full sweep instead, so "3 dependencies" is not rendered as 3% of something. ## Usage ```tsx import { StatCard } from "@/remotion/scenes/stat-card"; <StatCard value={98} label="Satisfaction" suffix="%" /> ``` ## Props | Name | Type | Default | Description | | --- | --- | --- | --- | | `value` | `number` | `98` | Number the counter lands on. | | `max` | `number` | - | What the value is out of. With it the ring is a meter; without it the ring draws a full sweep. | | `suffix` | `string` | `"%"` | Unit after the number. | | `prefix` | `string` | - | Unit before the number. | | `decimals` | `number` | `0` | Decimal places while counting and at rest. | | `label` | `string` | `"Satisfaction"` | Metric label. | | `caption` | `string` | - | Line under the label (source, window, cohort). | | `delta` | `number` | - | Change against the previous period; lands after the number settles. | | `deltaSuffix` | `string` | `"%"` | Unit on the delta chip. | | `accentColor` | `string` | `"#2DD4BF"` | Ring, suffix, and delta colour. | | `theme` | `"dark" \| "light"` | `"dark"` | Surface palette. | | `speed` | `number` | `1` | Animation speed multiplier. | ## Related - [Counter](https://remotionui.com/docs/components/counter.md) - [Feature List](https://remotionui.com/docs/components/feature-list.md) ## Machine-readable references - Props and usage as JSON: https://remotionui.com/ai/components/stat-card.json - Component index: https://remotionui.com/ai/components.json --- # Team Grid > A team arriving person by person. The avatar springs up first, the name and role follow it into place. Source: https://remotionui.com/docs/components/team-grid ## Installation ```bash npx remotion-ui@latest add team-grid ``` Each tile lands as one object: the avatar springs up, its ring closes from a thin stroke to a full one, and the name and role follow about a tenth of a second behind. Fading all three together is the version that looks like a placeholder loading; staggering them inside the tile is what gives the arrival depth. The stagger runs in reading order rather than by row or column. A grid of any width then feels like a list being read out, where a row-by-row wipe feels like a slide transition applied to people. Initials are derived from the name, first letters of the first two words, which is right for most Latin names and wrong for enough others that `initials` is worth passing by hand when it matters. Avatar colours cycle through `avatarColors` by index, so a longer team keeps varying without you assigning a colour to each person. Four columns at 1080p keeps names on one line. Past eight or so people, drop to `columns={5}` and shorten the roles before you shrink the type. ## Usage ```tsx import { TeamGrid } from "@/remotion/scenes/team-grid"; <TeamGrid title="The people behind it" subtitle="Eight of us, four timezones." members={[ { name: "Ada Okonjo", role: "Founder" }, { name: "Piotr Nowak", role: "Rendering" }, { name: "Dai Nakamura", role: "Design systems" }, ]} columns={4} holdSeconds={3.4} /> ``` Initials are the first letters of the first two words: right for most Latin names and wrong for enough others that `initials` is worth passing by hand. The avatar springs up ahead of its name and role so each tile lands as one object with depth rather than three elements agreeing to fade. ## Props | Name | Type | Default | Description | | --- | --- | --- | --- | | `members` | `TeamMember[]` | `8 sample people` | Name, role, optional avatar tint and hand-written initials. | | `title` | `string` | `"The people behind it"` | Heading above the grid. Omit to drop it. | | `subtitle` | `string` | `"Eight of us, four timezones."` | Line under the heading. | | `columns` | `number` | `4` | Members per row. Four keeps names on one line at 1080p. | | `startAtSeconds` | `number` | `0.4` | Second the first avatar arrives. | | `staggerSeconds` | `number` | `0.2` | Seconds between members, in reading order. | | `holdSeconds` | `number` | - | Seconds the settled grid holds before it retreats. Omit to leave it up. | | `accentColor` | `string` | `"#E8B86D"` | Role line on the first member: the one you want read first. | | `avatarColors` | `string[]` | `6 tints` | Cycled by index for members with no colour of their own. | | `backgroundColor` | `string` | - | Page behind the grid. Defaults to the theme page colour. | | `theme` | `"dark" \| "light"` | `"dark"` | Surface palette. | | `speed` | `number` | `1` | Animation speed multiplier. | ## Related - [Org Chart Build](https://remotionui.com/docs/components/org-chart-build.md) - [Logo Wall](https://remotionui.com/docs/components/logo-wall.md) - [Feature List](https://remotionui.com/docs/components/feature-list.md) ## Machine-readable references - Props and usage as JSON: https://remotionui.com/ai/components/team-grid.json - Component index: https://remotionui.com/ai/components.json --- # Timeline Steps > A process walked step by step, each one worked and checked off. Source: https://remotionui.com/docs/components/timeline-steps ## Installation ```bash npx remotion-ui@latest add timeline-steps ``` The rail draws first, then a travelling head lands on each step: the node lights, a ring closes over the time that step is being worked, and it checks off and dims to done as the head moves on, so the scene ends on a fully walked timeline rather than a row of dots that faded in. Horizontal in landscape, a left gutter rail in portrait. Add `title`/`eyebrow` for a heading, and `speed` to compress the walk. ## Usage ```tsx import { TimelineSteps } from "@/remotion/scenes/timeline-steps"; <TimelineSteps steps={[{ title: "Record" }, { title: "Render" }]} /> ``` ## Props | Name | Type | Default | Description | | --- | --- | --- | --- | | `steps` (required) | `TimelineStep[]` | - | Steps in order; up to five are walked. | | `title` | `string` | - | Heading above the rail. | | `eyebrow` | `string` | - | Small label above the heading. | | `accentColor` | `string` | `"#E8B86D"` | Rail, node, and check colour. | | `backgroundColor` | `string` | - | Overrides the page background. | | `theme` | `"dark" \| "light"` | `"dark"` | Surface palette. | | `speed` | `number` | `1` | Animation speed multiplier. | ## Related - [Data Story](https://remotionui.com/docs/components/data-story.md) - [Feature List](https://remotionui.com/docs/components/feature-list.md) ## Machine-readable references - Props and usage as JSON: https://remotionui.com/ai/components/timeline-steps.json - Component index: https://remotionui.com/ai/components.json --- # Title Card > An opening card where the headline stands up line by line. Source: https://remotionui.com/docs/components/title-card ## Installation ```bash npx remotion-ui@latest add title-card ``` Each line rises out of its own mask in turn, one sweep of light crosses the headline once it is standing, and the whole card holds under a slow push so a long title beat never sits dead still. Newlines in `title` are honoured; otherwise lines are balanced to `charsPerLine`. `eyebrow` adds a chip above, `meta` a small line under the subtitle. ## Usage ```tsx import { TitleCard } from "@/remotion/scenes/title-card"; <TitleCard title="Launch Week" subtitle="Day 1" /> ``` ## Props | Name | Type | Default | Description | | --- | --- | --- | --- | | `title` (required) | `string` | - | Headline. Newlines honoured; otherwise lines are balanced. | | `subtitle` | `string` | - | Supporting line. | | `eyebrow` | `string` | - | Chip above the headline. | | `meta` | `string` | - | Small line under the subtitle (date, author, run time). | | `charsPerLine` | `number` | `22` | Characters per line the headline balances to. | | `accentColor` | `string` | `"#E8B86D"` | Chip, glow, and sweep colour. | | `backgroundColor` | `string` | - | Overrides the page background. | | `theme` | `"dark" \| "light"` | `"dark"` | Surface palette. | | `holdSeconds` | `number` | - | Seconds before the card leaves. Omit to hold: correct inside a TransitionSeries. | | `speed` | `number` | `1` | Animation speed multiplier. | ## Related - [Intro](https://remotionui.com/docs/components/intro.md) - [End Card](https://remotionui.com/docs/components/end-card.md) ## Machine-readable references - Props and usage as JSON: https://remotionui.com/ai/components/title-card.json - Component index: https://remotionui.com/ai/components.json --- # Weather Card > Conditions with iconography that never stops. Rays turn, clouds drift, drops and flakes fall on their own loops. Source: https://remotionui.com/docs/components/weather-card ## Installation ```bash npx remotion-ui@latest add weather-card ``` The temperature counts up, the forecast row arrives day by day, and the iconography runs continuously underneath all of it. The motion is real but it is small: a forecast glyph is a few pixels tall, so the drift alone will not carry a tile. Pass `holdSeconds` when the card stands on its own and it leaves; omit it inside a `TransitionSeries`, where the transition covers the tail. Every moving part is a pure function of the frame: `frame * rate` wrapped into its own period, with each ray, drop or flake offset by its own index. Nothing accumulates state between frames, so a frame rendered out of order on a render farm is identical to the same frame rendered in sequence. That is a hard requirement in Remotion, not a stylistic choice: anything driven by a `useRef` counter will drift. Four conditions ship: `sun`, `cloud`, `rain` and `snow`. Each forecast column runs its own clock, offset by nine frames per column, so the row never becomes five glyphs moving in lockstep. The degree symbol takes `accentColor` while the glyph takes the condition colour. They are deliberately separate: the brand mark should not change hue when the weather does. ## Usage ```tsx import { WeatherCard } from "@/remotion/scenes/weather-card"; <WeatherCard place="Lisbon" temperature={24} condition="sun" conditionLabel="Clear, light breeze" forecast={[ { label: "Sat", condition: "sun", high: 24, low: 14 }, { label: "Sun", condition: "cloud", high: 22, low: 13 }, { label: "Mon", condition: "rain", high: 18, low: 12 }, ]} /> ``` Every moving part is a pure function of the frame (frame × rate wrapped into its own period, with per-particle offsets from the particle's index), so a frame rendered out of order on a render farm is identical to the same frame rendered in sequence. Each forecast column runs its own clock nine frames apart, so the row is never five glyphs in lockstep. The motion is real but small (a forecast glyph is only a few pixels tall), so pass holdSeconds when the card stands on its own. ## Props | Name | Type | Default | Description | | --- | --- | --- | --- | | `place` | `string` | `"Lisbon"` | Place name across the top. | | `detail` | `string` | `"Saturday · 14:20"` | Line under the place: a time, a date, a feels-like. | | `temperature` | `number` | `24` | The temperature the card counts up to. | | `unit` | `string` | `"°"` | Degree suffix, used on the headline and the forecast. | | `condition` | `"sun" \| "cloud" \| "rain" \| "snow"` | `"sun"` | Which glyph runs beside the headline. | | `conditionLabel` | `string` | `"Clear, light breeze"` | Words under the temperature. | | `forecast` | `ForecastDay[]` | `5 sample days` | Label, condition, high and low per column. | | `temperatureAtSeconds` | `number` | `0.4` | Second the temperature starts counting. | | `countSeconds` | `number` | `1` | How long the count takes. | | `forecastAtSeconds` | `number` | `1.4` | Second the first forecast day arrives. | | `staggerSeconds` | `number` | `0.34` | Seconds between forecast days. | | `holdSeconds` | `number` | - | Seconds the card holds before it retreats. Omit to leave it up; the iconography keeps moving either way. | | `accentColor` | `string` | `"#E8B86D"` | The degree symbol. Kept off the condition colour on purpose. | | `backgroundColor` | `string` | - | Page behind the card. Defaults to the theme page colour. | | `theme` | `"dark" \| "light"` | `"dark"` | Surface palette. | | `speed` | `number` | `1` | Animation speed multiplier. | ## Related - [Stat Card](https://remotionui.com/docs/components/stat-card.md) - [Gauge Dial](https://remotionui.com/docs/components/gauge-dial.md) - [Calendar Month Fill](https://remotionui.com/docs/components/calendar-month-fill.md) ## Machine-readable references - Props and usage as JSON: https://remotionui.com/ai/components/weather-card.json - Component index: https://remotionui.com/ai/components.json --- # Zoom Pan Frame > A camera move on a still, driven by focal points rather than pixel offsets. Source: https://remotionui.com/docs/components/zoom-pan-frame ## Installation ```bash npx remotion-ui@latest add zoom-pan-frame ``` `from` and `to` are focal points: `{ x, y, scale }` with `x`/`y` in 0–1 across the frame, so the framing lands on the subject at whatever size the composition is, instead of guessing pixel offsets per aspect. The move spans the composition minus a short settle by default, which is what keeps it reading as camera work rather than a jump cut. `label` adds a chip that rises once the move lands. ## Usage ```tsx import { ZoomPanFrame } from "@/remotion/scenes/zoom-pan-frame"; <ZoomPanFrame src={staticFile("screenshot.png")} to={{ x: 0.38, y: 0.4, scale: 1.2 }} /> ``` ## Props | Name | Type | Default | Description | | --- | --- | --- | --- | | `src` (required) | `string` | - | Image or video source. | | `from` | `FocalPoint` | - | Where the move starts: { x, y, scale } with x/y in 0–1. | | `to` | `FocalPoint` | - | Where the move lands. Defaults to a centred 1.24 push. | | `moveInFrames` | `number` | - | Length of the move. Defaults to the composition minus a short settle. | | `label` | `string` | - | Chip that rises once the move lands. | | `vignette` | `number` | `0.34` | Corner darkening; 0 turns it off. | | `fit` | `"cover" \| "contain"` | `"cover"` | Media object-fit behaviour. | | `theme` | `"dark" \| "light"` | `"dark"` | Surface palette. | ## Related - [Callout Spotlight](https://remotionui.com/docs/components/callout-spotlight.md) - [Cursor Path](https://remotionui.com/docs/components/cursor-path.md) ## Machine-readable references - Props and usage as JSON: https://remotionui.com/ai/components/zoom-pan-frame.json - Component index: https://remotionui.com/ai/components.json --- # Transitions > Scene cuts for TransitionSeries: wipes, pushes, flips, and shader effects. Source: https://remotionui.com/docs/components/transitions Transitions go between two scenes in a `TransitionSeries`. Each one exports a presentation you pass to `TransitionSeries.Transition` with your own timing. ## Components - [Blur Reveal](https://remotionui.com/docs/components/blur-reveal.md): The outgoing scene softens away while the incoming one resolves out of blur. - [Chromatic Aberration Wipe](https://remotionui.com/docs/components/chromatic-aberration-wipe.md): A slide hard enough to pull the colour channels apart. - [Directional Wipe](https://remotionui.com/docs/components/directional-wipe.md): A soft-edged wipe that uncovers the next scene without ever showing the background. - [Frosted Glass Wipe](https://remotionui.com/docs/components/frosted-glass-wipe.md): A pane of frosted glass crosses the frame and leaves the next scene behind it. - [Grid Pixelate Wipe](https://remotionui.com/docs/components/grid-pixelate-wipe.md): The next scene arrives one grid cell at a time. - [Spatial Push](https://remotionui.com/docs/components/spatial-push.md): Two scenes locked edge to edge, shoved across the frame as one move. - [Blinds](https://remotionui.com/docs/components/transition-blinds.md): Staggered slats sweeping open to reveal the next scene. - [Card Flip](https://remotionui.com/docs/components/transition-card-flip.md): A whole-frame 3D flip that hands one scene off to the next on backface culling. - [Circle Reveal](https://remotionui.com/docs/components/transition-circle-reveal.md): A circular mask that opens from any point in the frame onto the next scene. - [Transition Clock Wipe](https://remotionui.com/docs/components/transition-clock-wipe.md): A sweep hand travels the frame and leaves the next scene behind it. - [Transition Fade](https://remotionui.com/docs/components/transition-fade.md): Crossfade between scenes, or dip through a colour on the way. - [Transition Light Leak](https://remotionui.com/docs/components/transition-light-leak.md): A film flare that peaks on the cut and hides the seam under it. - [Liquid Warp](https://remotionui.com/docs/components/transition-liquid-warp.md): A liquid displacement warp that stirs one scene into the next. - [Morph Shape](https://remotionui.com/docs/components/transition-morph-shape.md): A reveal through a shape that changes form as it grows across the frame. - [Transition Slide](https://remotionui.com/docs/components/transition-slide.md): Slide transition helper for TransitionSeries. - [Whip Pan](https://remotionui.com/docs/components/transition-whip-pan.md): A fast pan between scenes with directional motion blur along the travel axis. - [Transition Wipe](https://remotionui.com/docs/components/transition-wipe.md): Wipe transition helper for TransitionSeries. - [Zoom Through](https://remotionui.com/docs/components/zoom-through.md): The camera pushes through one scene and lands in the next. --- # Blur Reveal > The outgoing scene softens away while the incoming one resolves out of blur. Source: https://remotionui.com/docs/components/blur-reveal ## Installation ```bash npx remotion-ui@latest add blur-reveal ``` The incoming scene resolves out of `maxBlur` under a slight scale settle while the outgoing one softens and gives up its opacity. Both are perfectly sharp outside the overlap: the blur exists only for the frames the cut is running. Set `shouldBlurOutExitingScene` to `false` to hold the outgoing scene sharp underneath and let the new one resolve on top of it. `scaleBy` controls the scale headroom the blur rides on; `0` keeps the frame dead still. Exports `transitionBlurReveal()` and `getTransitionBlurRevealDuration()` for use with `TransitionSeries.Transition`. Requires `@remotion/transitions`. Run `npx remotion add @remotion/transitions` if not already installed. ## Usage ```tsx import { transitionBlurReveal } from "@/remotion/primitives/blur-reveal"; <TransitionSeries.Transition {...transitionBlurReveal({ maxBlur: 24 })} /> ``` ## Props | Name | Type | Default | Description | | --- | --- | --- | --- | | `durationInFrames` | `number` | `22` | Transition overlap length. | | `maxBlur` | `number` | `24` | Peak blur radius in px, reached only mid-transition. | | `scaleBy` | `number` | `0.03` | Scale headroom the blur rides on. 0 keeps the frame still. | | `shouldBlurOutExitingScene` | `boolean` | `true` | Blur the outgoing scene too. false holds it sharp underneath. | | `variant` | `"linear" \| "spring" \| "editorial"` | `"editorial"` | Timing curve. | ## Related - [Transition Fade](https://remotionui.com/docs/components/transition-fade.md) - [Frosted Glass Wipe](https://remotionui.com/docs/components/frosted-glass-wipe.md) ## Machine-readable references - Props and usage as JSON: https://remotionui.com/ai/components/blur-reveal.json - Component index: https://remotionui.com/ai/components.json --- # Chromatic Aberration Wipe > A slide hard enough to pull the colour channels apart. Source: https://remotionui.com/docs/components/chromatic-aberration-wipe ## Installation ```bash npx remotion-ui@latest add chromatic-aberration-wipe ``` The two scenes slide across locked together while the red and blue channels separate against the green, an actual per-channel split, isolated with a colour matrix and recombined under `screen`, not a coloured shadow dropped behind the layer. The separation peaks in the middle of the move and is gone at both ends, so nothing is left tinted once the cut lands. `intensity` is the peak separation in px, `axis` swings the whole thing vertical, and `slide` is how far the scenes travel. Leave it at `1` unless you want the background to show. Exports `transitionChromaticAberrationWipe()` and `getTransitionChromaticAberrationWipeDuration()` for use with `TransitionSeries.Transition`. Requires `@remotion/transitions`. Run `npx remotion add @remotion/transitions` if not already installed. ## Usage ```tsx import { transitionChromaticAberrationWipe } from "@/remotion/primitives/chromatic-aberration-wipe"; <TransitionSeries.Transition {...transitionChromaticAberrationWipe({ intensity: 12 })} /> ``` ## Props | Name | Type | Default | Description | | --- | --- | --- | --- | | `durationInFrames` | `number` | `14` | Transition overlap length. | | `intensity` | `number` | `12` | Peak channel separation in px, reached in the middle of the cut. | | `axis` | `"horizontal" \| "vertical"` | `"horizontal"` | Axis the scenes slide along and the channels separate on. | | `slide` | `number` | `1` | Share of the frame the scenes travel. Below 1 shows background. | ## Related - [Blur Reveal](https://remotionui.com/docs/components/blur-reveal.md) - [Directional Wipe](https://remotionui.com/docs/components/directional-wipe.md) ## Machine-readable references - Props and usage as JSON: https://remotionui.com/ai/components/chromatic-aberration-wipe.json - Component index: https://remotionui.com/ai/components.json --- # Directional Wipe > A soft-edged wipe that uncovers the next scene without ever showing the background. Source: https://remotionui.com/docs/components/directional-wipe ## Installation ```bash npx remotion-ui@latest add directional-wipe ``` The incoming scene is revealed by a soft-edged mask travelling from `direction`, while the outgoing one holds whole underneath and carries a little counter parallax. Only the arriving scene is masked: wiping both at once would open a hole onto the background in the middle of the cut. `edgeSoftness` is the width of the feathered edge as a share of the frame; set it to `0` for a hard architectural line. `depth` is the parallax the two scenes carry against each other under the wipe. Exports `transitionDirectionalWipe()` and `getTransitionDirectionalWipeDuration()` for use with `TransitionSeries.Transition`. Requires `@remotion/transitions`. Run `npx remotion add @remotion/transitions` if not already installed. ## Usage ```tsx import { transitionDirectionalWipe } from "@/remotion/primitives/directional-wipe"; <TransitionSeries.Transition {...transitionDirectionalWipe({ direction: "from-left" })} /> ``` ## Props | Name | Type | Default | Description | | --- | --- | --- | --- | | `durationInFrames` | `number` | `22` | Transition overlap length. | | `direction` | `"from-left" \| "from-right" \| "from-top" \| "from-bottom"` | `"from-left"` | Wipe direction. | | `edgeSoftness` | `number` | `0.12` | Soft edge width as a share of the frame. 0 cuts hard. | | `depth` | `number` | `0.08` | Parallax the scenes carry under the wipe. | | `variant` | `"linear" \| "spring" \| "editorial"` | `"editorial"` | Timing curve. | ## Related - [Transition Wipe](https://remotionui.com/docs/components/transition-wipe.md) - [Spatial Push](https://remotionui.com/docs/components/spatial-push.md) ## Machine-readable references - Props and usage as JSON: https://remotionui.com/ai/components/directional-wipe.json - Component index: https://remotionui.com/ai/components.json --- # Frosted Glass Wipe > A pane of frosted glass crosses the frame and leaves the next scene behind it. Source: https://remotionui.com/docs/components/frosted-glass-wipe ## Installation ```bash npx remotion-ui@latest add frosted-glass-wipe ``` One panel of blurred glass travels across the frame, and the scene changes behind it. Because the panel covers the seam, the cut underneath can be hard: the outgoing scene holds whole until the glass has passed over it. `direction` takes any of the four edges, `panelWidth` is the pane's width as a share of the frame, and `frostColor` tints the glass. The pane parks off-frame at both ends, so it never sits over a scene that is not moving. Exports `transitionFrostedGlassWipe()` and `getTransitionFrostedGlassWipeDuration()` for use with `TransitionSeries.Transition`. Requires `@remotion/transitions`. Run `npx remotion add @remotion/transitions` if not already installed. ## Usage ```tsx import { transitionFrostedGlassWipe } from "@/remotion/primitives/frosted-glass-wipe"; <TransitionSeries.Transition {...transitionFrostedGlassWipe({ blur: 20 })} /> ``` ## Props | Name | Type | Default | Description | | --- | --- | --- | --- | | `durationInFrames` | `number` | `24` | Transition overlap length. | | `blur` | `number` | `20` | Frost panel blur radius. | | `panelWidth` | `number` | `0.14` | Sweep panel width as fraction of frame. | | `direction` | `"from-left" \| "from-right" \| "from-top" \| "from-bottom"` | `"from-left"` | Sweep direction. | | `frostColor` | `string` | `"rgba(255,255,255,0.12)"` | Tint of the glass panel. | ## Related - [Blur Reveal](https://remotionui.com/docs/components/blur-reveal.md) - [Transition Wipe](https://remotionui.com/docs/components/transition-wipe.md) ## Machine-readable references - Props and usage as JSON: https://remotionui.com/ai/components/frosted-glass-wipe.json - Component index: https://remotionui.com/ai/components.json --- # Grid Pixelate Wipe > The next scene arrives one grid cell at a time. Source: https://remotionui.com/docs/components/grid-pixelate-wipe ## Installation ```bash npx remotion-ui@latest add grid-pixelate-wipe ``` The incoming scene is revealed through a `cols` × `rows` mask whose cells light up in turn, with the outgoing scene holding whole underneath so the gaps between cells always show the old frame rather than the background. `order` picks where the fill starts (an edge, the diagonal, or the centre), and `stagger` sets how far the cells spread apart in time: `0` pops them all at once, `1` spreads them across the whole window. `shape: "dot"` grows each cell as a point instead of filling it as a block. Exports `transitionGridPixelateWipe()` and `getTransitionGridPixelateWipeDuration()` for use with `TransitionSeries.Transition`. Requires `@remotion/transitions`. Run `npx remotion add @remotion/transitions` if not already installed. ## Usage ```tsx import { transitionGridPixelateWipe } from "@/remotion/primitives/grid-pixelate-wipe"; <TransitionSeries.Transition {...transitionGridPixelateWipe({ cols: 12, rows: 8 })} /> ``` ## Props | Name | Type | Default | Description | | --- | --- | --- | --- | | `durationInFrames` | `number` | `26` | Transition overlap length. | | `cols` | `number` | `12` | Grid column count. | | `rows` | `number` | `8` | Grid row count. | | `order` | `"from-left" \| "from-top" \| "diagonal" \| "center"` | `"from-left"` | Which axis or point the cells light up from. | | `shape` | `"square" \| "dot"` | `"square"` | Cells fill as blocks, or as points that grow with their own reveal. | | `stagger` | `number` | `0.82` | 0 pops every cell together; 1 spreads them across the whole window. | ## Related - [Transition Wipe](https://remotionui.com/docs/components/transition-wipe.md) - [Blur Reveal](https://remotionui.com/docs/components/blur-reveal.md) ## Machine-readable references - Props and usage as JSON: https://remotionui.com/ai/components/grid-pixelate-wipe.json - Component index: https://remotionui.com/ai/components.json --- # Spatial Push > Two scenes locked edge to edge, shoved across the frame as one move. Source: https://remotionui.com/docs/components/spatial-push ## Installation ```bash npx remotion-ui@latest add spatial-push ``` A push, not two entrances: the outgoing scene is shoved out the far side while the incoming one arrives from `direction`, both travelling the same distance at the same time so the seam between them never opens onto the background. `pushDepth` is the share of the frame each scene covers, and it defaults to `1` for that reason. Lower it only over a solid backdrop you are happy to see. `tilt` rakes the panels in 3D and is off by default, because rotating a full-frame panel pulls one edge in and uncovers bare background behind it. Exports `transitionSpatialPush()` and `getTransitionSpatialPushDuration()` for use with `TransitionSeries.Transition`. Requires `@remotion/transitions`. Run `npx remotion add @remotion/transitions` if not already installed. ## Usage ```tsx import { transitionSpatialPush } from "@/remotion/primitives/spatial-push"; <TransitionSeries.Transition {...transitionSpatialPush()} /> ``` ## Props | Name | Type | Default | Description | | --- | --- | --- | --- | | `durationInFrames` | `number` | `24` | Transition overlap length. | | `direction` | `"from-left" \| "from-right" \| "from-top" \| "from-bottom"` | `"from-left"` | Push direction. | | `pushDepth` | `number` | `1` | Share of the frame each scene travels. Below 1 leaves background showing mid-push. | | `tilt` | `number` | `0` | Degrees each panel rotates in 3D. Off by default: a tilted full-frame panel uncovers bare background. | | `perspective` | `number` | `1200` | Perspective distance in px, used when tilt is set. | ## Related - [Directional Wipe](https://remotionui.com/docs/components/directional-wipe.md) - [Zoom Through](https://remotionui.com/docs/components/zoom-through.md) ## Machine-readable references - Props and usage as JSON: https://remotionui.com/ai/components/spatial-push.json - Component index: https://remotionui.com/ai/components.json --- # Blinds > Staggered slats sweeping open to reveal the next scene. Source: https://remotionui.com/docs/components/transition-blinds ## Installation ```bash npx remotion-ui@latest add transition-blinds ``` The arriving scene is masked by `slats` bands, each sweeping open along the short axis with a cascading start. The outgoing scene holds whole beneath them, and cutting it into slats too would open every gap onto the background rather than onto the next scene. `stagger` is the share of the window the cascade spans. The per-slat window is compressed so the *last* slat still finishes exactly at full coverage; a naive delay leaves the tail of the stack short of open at the end of the transition, which shows as permanent stripes over the scene for the rest of its sequence. `alternate` reverses every second slat for a woven counter-sweep, and `edgeSoftness` feathers each slat's leading edge. The feather is measured outside the slat, so a slat at full progress is solid all the way across. Exports `transitionBlinds()` and `getTransitionBlindsDuration()` for use with `TransitionSeries.Transition`. Requires `@remotion/transitions`. Run `npx remotion add @remotion/transitions` if not already installed. ## Usage ```tsx import { transitionBlinds } from "@/remotion/primitives/transition-blinds"; <TransitionSeries.Transition {...transitionBlinds({ slats: 12, stagger: 0.45 })} /> ``` ## Props | Name | Type | Default | Description | | --- | --- | --- | --- | | `durationInFrames` | `number` | `24` | Transition overlap length. | | `orientation` | `"horizontal" \| "vertical"` | `"horizontal"` | Horizontal slats stack top to bottom and sweep sideways. | | `slats` | `number` | `12` | Number of slats. Above ~24 it stops reading as slats at 1080p. | | `stagger` | `number` | `0.45` | Share of the window the cascade spans. 0 opens every slat together. | | `alternate` | `boolean` | `false` | Reverse alternate slats for a woven counter-sweep. | | `edgeSoftness` | `number` | `0.06` | Soft leading edge per slat, as a share of its length. | | `variant` | `"linear" \| "spring" \| "editorial"` | `"editorial"` | Timing curve. | ## Related - [Grid Pixelate Wipe](https://remotionui.com/docs/components/grid-pixelate-wipe.md) - [Directional Wipe](https://remotionui.com/docs/components/directional-wipe.md) ## Machine-readable references - Props and usage as JSON: https://remotionui.com/ai/components/transition-blinds.json - Component index: https://remotionui.com/ai/components.json --- # Card Flip > A whole-frame 3D flip that hands one scene off to the next on backface culling. Source: https://remotionui.com/docs/components/transition-card-flip ## Installation ```bash npx remotion-ui@latest add transition-card-flip ``` Each scene turns a half-circle in its own direction and the hand-off is done by backface culling: the outgoing face passes 90° at the midpoint and is hidden for the rest of the window, and the incoming one stays hidden until it crosses back through -90°. Clamping both at 90° instead leaves two faces parked edge-on, flickering against each other. A flipping frame is zero pixels wide at the halfway point, so *something* is visible behind it. `backdrop` is that something: the outgoing layer paints it, since it sits under the incoming one for the whole cut. Set it to your scene background rather than leaving the page through. `shading` darkens the face as it turns away, on `cos()` of the turn, which is exactly 1 at 0° and so leaves a settled scene untouched. `dip` recedes the card at the midpoint on a parabola that is exactly 1 at both ends. Exports `transitionCardFlip()` and `getTransitionCardFlipDuration()` for use with `TransitionSeries.Transition`. Requires `@remotion/transitions`. Run `npx remotion add @remotion/transitions` if not already installed. ## Usage ```tsx import { transitionCardFlip } from "@/remotion/primitives/transition-card-flip"; <TransitionSeries.Transition {...transitionCardFlip({ axis: "y" })} /> ``` ## Props | Name | Type | Default | Description | | --- | --- | --- | --- | | `durationInFrames` | `number` | `24` | Transition overlap length. | | `axis` | `"y" \| "x"` | `"y"` | y flips left-to-right like a page; x flips top over bottom. | | `perspective` | `number` | `1600` | Perspective distance in px. Lower is a wider-angle flip. | | `backdrop` | `string` | `"#05060a"` | Colour behind the card while it is edge-on. Without it the page background shows at the halfway frame. | | `shading` | `number` | `0.55` | Peak darkening of the face turning away, 0→1. | | `dip` | `number` | `0.86` | How far the card recedes at the halfway point. | | `variant` | `"linear" \| "spring" \| "editorial"` | `"editorial"` | Timing curve. | ## Related - [Whip Pan](https://remotionui.com/docs/components/transition-whip-pan.md) - [Spatial Push](https://remotionui.com/docs/components/spatial-push.md) ## Machine-readable references - Props and usage as JSON: https://remotionui.com/ai/components/transition-card-flip.json - Component index: https://remotionui.com/ai/components.json --- # Circle Reveal > A circular mask that opens from any point in the frame onto the next scene. Source: https://remotionui.com/docs/components/transition-circle-reveal ## Installation ```bash npx remotion-ui@latest add transition-circle-reveal ``` The incoming scene is revealed through a circle growing from `originX`/`originY`, while the outgoing one holds whole underneath. Only the arriving scene is masked. Punching the hole in both would open it onto the page background instead of onto the next scene. The radius is sized against the corner furthest from the origin, so an off-centre reveal still clears the frame; half the diagonal would leave a wedge unrevealed for any origin that is not dead centre. `edgeSoftness` feathers the edge as a share of that radius, and the mask is grown past full coverage by the feather width so no translucent ring survives into the last frames. `underScale` gives the outgoing scene a little push-back under the hole, which sells the circle as depth rather than as a sticker. Leave it at `1` for a flat graphic reveal. Exports `transitionCircleReveal()` and `getTransitionCircleRevealDuration()` for use with `TransitionSeries.Transition`. Requires `@remotion/transitions`. Run `npx remotion add @remotion/transitions` if not already installed. ## Usage ```tsx import { transitionCircleReveal } from "@/remotion/primitives/transition-circle-reveal"; <TransitionSeries.Transition {...transitionCircleReveal({ originX: 0.3, originY: 0.4 })} /> ``` ## Props | Name | Type | Default | Description | | --- | --- | --- | --- | | `durationInFrames` | `number` | `22` | Transition overlap length. | | `originX` | `number` | `0.5` | Centre of the circle, 0→1 of the frame width. | | `originY` | `number` | `0.5` | Centre of the circle, 0→1 of the frame height. | | `edgeSoftness` | `number` | `0.04` | Feathered edge as a share of the final radius. 0 cuts hard. | | `underScale` | `number` | `1` | Scale the outgoing scene drifts to under the hole. 1 holds it still. | | `variant` | `"linear" \| "spring" \| "editorial"` | `"editorial"` | Timing curve. | ## Related - [Morph Shape](https://remotionui.com/docs/components/transition-morph-shape.md) - [Transition Wipe](https://remotionui.com/docs/components/transition-wipe.md) ## Machine-readable references - Props and usage as JSON: https://remotionui.com/ai/components/transition-circle-reveal.json - Component index: https://remotionui.com/ai/components.json --- # Transition Clock Wipe > A sweep hand travels the frame and leaves the next scene behind it. Source: https://remotionui.com/docs/components/transition-clock-wipe ## Installation ```bash npx remotion-ui@latest add transition-clock-wipe ``` `width` and `height` are optional: the presentation reads the composition size itself. Previously every caller had to reach for `useVideoConfig()` before it could build a transition config, including in places where hooks are not available. Pass them explicitly only to sweep a different radius than the frame. ```tsx <TransitionSeries.Transition {...transitionClockWipe()} /> ``` Exports `transitionClockWipe()` and `getTransitionClockWipeDuration()` for use with `TransitionSeries.Transition`. Requires `@remotion/transitions`. Run `npx remotion add @remotion/transitions` if not already installed. ## Usage ```tsx import { transitionClockWipe } from "@/remotion/primitives/transition-clock-wipe"; <TransitionSeries.Transition {...transitionClockWipe({ width: 1920, height: 1080 })} /> ``` ## Props | Name | Type | Default | Description | | --- | --- | --- | --- | | `durationInFrames` | `number` | `26` | Transition overlap length. | | `width` | `number` | - | Sweep width. Defaults to the composition width. | | `height` | `number` | - | Sweep height. Defaults to the composition height. | ## Related - [Transition Wipe](https://remotionui.com/docs/components/transition-wipe.md) ## Machine-readable references - Props and usage as JSON: https://remotionui.com/ai/components/transition-clock-wipe.json - Component index: https://remotionui.com/ai/components.json --- # Transition Fade > Crossfade between scenes, or dip through a colour on the way. Source: https://remotionui.com/docs/components/transition-fade ## Installation ```bash npx remotion-ui@latest add transition-fade ``` By default the two scenes crossfade directly. Pass `dipTo` and the cut goes through that colour instead: the outgoing scene sinks into it, the frame holds it for an instant, and the new scene rises back out. Each scene paints its own colour layer and reaches full opacity by the midpoint, so the dip is solid whatever sits behind the transition. ```tsx <TransitionSeries.Transition {...transitionFade({ dipTo: "#000" })} /> ``` Exports `transitionFade()` and `getTransitionFadeDuration()` for use with `TransitionSeries.Transition`. Requires `@remotion/transitions`. Run `npx remotion add @remotion/transitions` if not already installed. ## Usage ```tsx import { TransitionSeries } from "@remotion/transitions"; import { transitionFade } from "@/remotion/primitives/transition-fade"; <TransitionSeries> <TransitionSeries.Sequence durationInFrames={60}>...</TransitionSeries.Sequence> <TransitionSeries.Transition {...transitionFade({ durationInFrames: 15 })} /> <TransitionSeries.Sequence durationInFrames={60}>...</TransitionSeries.Sequence> </TransitionSeries> ``` Returns a config object for `TransitionSeries.Transition`, not a React component. ## Props | Name | Type | Default | Description | | --- | --- | --- | --- | | `durationInFrames` | `number` | `18` | Overlap duration between scenes. | | `dipTo` | `string` | - | Colour the cut passes through. Omit to crossfade the scenes directly. | | `variant` | `"linear" \| "spring" \| "editorial"` | `"editorial"` | Timing curve for the fade. | ## Related - [Transition Slide](https://remotionui.com/docs/components/transition-slide.md) - [Showcase](https://remotionui.com/docs/components/showcase.md) ## Machine-readable references - Props and usage as JSON: https://remotionui.com/ai/components/transition-fade.json - Component index: https://remotionui.com/ai/components.json --- # Transition Light Leak > A film flare that peaks on the cut and hides the seam under it. Source: https://remotionui.com/docs/components/transition-light-leak ## Installation ```bash npx remotion-ui@latest add transition-light-leak ``` An overlay rather than a presentation: drop it in a `TransitionSeries.Overlay` and the flare blooms over whatever cut is happening underneath. It takes its length from the overlay it sits in, so the envelope always finishes exactly when the overlay does. `peakAt` moves the brightest moment inside that window. `TransitionSeries.Overlay` centres the overlay on the cut, so the default `0.5` puts the flare on the seam; lower values peak before it. `intensity` scales the whole envelope and `blendMode` decides how it composites. An overlay does not shorten the series the way a transition does, so budget its scenes yourself: two 60-frame sequences fill a 120-frame composition and cut at frame 60, and a 24-frame overlay then spans frames 48–72. Rendering needs the ANGLE backend: pass `--gl=angle` to `remotion render`, or set `chromiumOptions: { gl: "angle" }` when using the SSR APIs. Requires `@remotion/light-leaks`. Run `npx remotion add @remotion/light-leaks` if not already installed. ## Usage ```tsx import { TransitionLightLeak } from "@/remotion/primitives/transition-light-leak"; <TransitionSeries.Overlay durationInFrames={30}> <TransitionLightLeak seed={2} hueShift={45} /> </TransitionSeries.Overlay> ``` Advanced. Installs @remotion/light-leaks. Rendering needs the ANGLE backend: pass --gl=angle. ## Props | Name | Type | Default | Description | | --- | --- | --- | --- | | `durationInFrames` | `number` | - | Length of the flare. Defaults to the overlay's own length. | | `seed` | `number` | `0` | Light leak pattern seed. | | `hueShift` | `number` | `28` | Hue rotation in degrees, warm amber by default. | | `intensity` | `number` | `1` | Peak opacity of the leak. | | `peakAt` | `number` | `0.5` | Where the flare peaks in its window. Sit it on the cut to hide the seam. | | `blendMode` | `"screen" \| "plus-lighter" \| "normal"` | `"screen"` | How the leak composites over the frame. | ## Related - [Transition Fade](https://remotionui.com/docs/components/transition-fade.md) ## Machine-readable references - Props and usage as JSON: https://remotionui.com/ai/components/transition-light-leak.json - Component index: https://remotionui.com/ai/components.json --- # Liquid Warp > A liquid displacement warp that stirs one scene into the next. Source: https://remotionui.com/docs/components/transition-liquid-warp ## Installation ```bash npx remotion-ui@latest add transition-liquid-warp ``` A turbulence field displaces the frame hardest in the middle of the cut and is exactly zero at both ends, so a settled scene carries no filter at all. The default `frequency` of `0.006` gives large, slow lobes that read as liquid; the core's higher default reads as sand at 30 fps, and anything above about `0.02` reads as noise rather than as a warp. A warp on its own never reveals anything: the frame is still the old scene, just stirred, so the arriving scene dissolves onto the outgoing one underneath. Only the arriving scene fades: ramping both at once leaves two half-transparent layers and the page background flashes through the middle of the cut. `churn` is how much the noise field re-seeds across the cut. `0` holds one static field and reads as a lens; the default boils. `affect` chooses whether both scenes warp or only the arriving one. `scaleRatio` is the peak displacement as a fraction of the frame's **short** axis, not an absolute pixel count: the same absolute displacement is a quarter of a 540px stage and a fourteenth of a 1080p one, so a pixel value silently makes the effect a different strength at every composition size. The filtered layer is scaled up by `frameSize / (frameSize - 2 x drag)` so the transparent border the displacement drags in from outside the layer stays off screen. Adding `drag` pixels of height is not enough, because the scale-up moves the contaminated band outward too. This is a configuration of the shared displacement presentation: the turbulence channel with no mask. Exports `transitionLiquidWarp()` and `getTransitionLiquidWarpDuration()` for use with `TransitionSeries.Transition`. Requires `@remotion/transitions`. Run `npx remotion add @remotion/transitions` if not already installed. ## Usage ```tsx import { transitionLiquidWarp } from "@/remotion/primitives/transition-liquid-warp"; <TransitionSeries.Transition {...transitionLiquidWarp({ scaleRatio: 0.12 })} /> ``` Configuration of the shared displacement presentation: the turbulence channel with no mask. ## Props | Name | Type | Default | Description | | --- | --- | --- | --- | | `durationInFrames` | `number` | `26` | Transition overlap length. Long enough for the field to boil. | | `scaleRatio` | `number` | `0.12` | Peak displacement at the middle of the cut, as a fraction of the frame's short axis. Frame-relative so the warp reads the same at any composition size. | | `frequency` | `number` | `0.006` | Turbulence base frequency. Below 0.004 reads as a lens, above 0.02 as noise. | | `octaves` | `number` | `2` | Turbulence octaves. Above 3 costs a lot and adds almost nothing. | | `churn` | `number` | `6` | How much the noise field re-seeds across the cut. 0 holds one static lens. | | `blur` | `number` | `3` | Peak blur in px, on the same curve as the displacement. | | `seed` | `number` | `7` | Turbulence seed. | | `affect` | `"both" \| "entering"` | `"both"` | Warp both scenes, or only the arriving one. | | `variant` | `"linear" \| "spring" \| "editorial"` | `"editorial"` | Timing curve. | ## Related - [Morph Shape](https://remotionui.com/docs/components/transition-morph-shape.md) - [Transition Fade](https://remotionui.com/docs/components/transition-fade.md) ## Machine-readable references - Props and usage as JSON: https://remotionui.com/ai/components/transition-liquid-warp.json - Component index: https://remotionui.com/ai/components.json --- # Morph Shape > A reveal through a shape that changes form as it grows across the frame. Source: https://remotionui.com/docs/components/transition-morph-shape ## Installation ```bash npx remotion-ui@latest add transition-morph-shape ``` The arriving scene is revealed through a shape that both grows and morphs, so the reveal has a silhouette rather than an edge. A circle that only grows is [Circle Reveal](https://remotionui.com/docs/components/transition-circle-reveal.md); reach for this when the shape itself should be part of the cut. `from` and `to` take the shared `MORPH_SHAPES` presets (`circle`, `square`, `squircle`, `triangle`, `diamond`, `blob`), which are authored on one box with matched curve counts. A raw path `d` works too, but a pair with mismatched segment counts interpolates into geometry that is valid SVG and nonsense on screen. `overshoot` is the final size as a multiple of the frame diagonal; below `1` the corners furthest from the origin are never revealed. `warp` adds turbulence to the revealed scene and is `0` by default: the warp is [Liquid Warp](https://remotionui.com/docs/components/transition-liquid-warp.md)'s job. This is a configuration of the shared displacement presentation: the mask channel with the turbulence channel switched off. Exports `transitionMorphShape()` and `getTransitionMorphShapeDuration()` for use with `TransitionSeries.Transition`. Requires `@remotion/transitions`. Run `npx remotion add @remotion/transitions` if not already installed. ## Usage ```tsx import { transitionMorphShape } from "@/remotion/primitives/transition-morph-shape"; <TransitionSeries.Transition {...transitionMorphShape({ from: "circle", to: "diamond" })} /> ``` Configuration of the shared displacement presentation: the mask channel with turbulence off. ## Props | Name | Type | Default | Description | | --- | --- | --- | --- | | `durationInFrames` | `number` | `24` | Transition overlap length. | | `from` | `"circle" \| "square" \| "squircle" \| "triangle" \| "diamond" \| "blob" \| string` | `"circle"` | Shape the reveal starts as, at zero size. A raw path d also works. | | `to` | `"circle" \| "square" \| "squircle" \| "triangle" \| "diamond" \| "blob" \| string` | `"squircle"` | Shape it has become once it covers the frame. | | `originX` | `number` | `0.5` | Where the shape grows from, 0→1 of the frame width. | | `originY` | `number` | `0.5` | Where the shape grows from, 0→1 of the frame height. | | `overshoot` | `number` | `1.06` | Final size as a multiple of the frame diagonal. Below 1 leaves corners unrevealed. | | `warp` | `number` | `0` | Optional turbulence on the revealed scene, in px. 0 keeps the silhouette crisp. | | `variant` | `"linear" \| "spring" \| "editorial"` | `"editorial"` | Timing curve. | ## Related - [Circle Reveal](https://remotionui.com/docs/components/transition-circle-reveal.md) - [Liquid Warp](https://remotionui.com/docs/components/transition-liquid-warp.md) - [path-morph](https://remotionui.com/docs/components/path-morph.md) ## Machine-readable references - Props and usage as JSON: https://remotionui.com/ai/components/transition-morph-shape.json - Component index: https://remotionui.com/ai/components.json --- # Transition Slide > Slide transition helper for TransitionSeries. Source: https://remotionui.com/docs/components/transition-slide ## Installation ```bash npx remotion-ui@latest add transition-slide ``` Exports `transitionSlide()` for directional scene transitions in `TransitionSeries`. Requires `@remotion/transitions`. Run `npx remotion add @remotion/transitions` if not already installed. ## Usage ```tsx import { transitionSlide } from "@/remotion/primitives/transition-slide"; <TransitionSeries.Transition {...transitionSlide({ direction: "from-left", durationInFrames: 20 })} /> ``` Returns a config object for `TransitionSeries.Transition`, not a React component. ## Props | Name | Type | Default | Description | | --- | --- | --- | --- | | `durationInFrames` | `number` | `22` | Overlap duration between scenes. | | `direction` | `string` | `"from-left"` | Slide direction: from-left, from-right, from-top, from-bottom. | ## Related - [Transition Fade](https://remotionui.com/docs/components/transition-fade.md) - [Showcase](https://remotionui.com/docs/components/showcase.md) ## Machine-readable references - Props and usage as JSON: https://remotionui.com/ai/components/transition-slide.json - Component index: https://remotionui.com/ai/components.json --- # Whip Pan > A fast pan between scenes with directional motion blur along the travel axis. Source: https://remotionui.com/docs/components/transition-whip-pan ## Installation ```bash npx remotion-ui@latest add transition-whip-pan ``` Both scenes travel locked edge to edge (`travel` below `1` leaves a strip of background between them), and the blur is directional. `filter: blur()` is isotropic and smears the frame across the axis it is *not* moving on, which reads as out-of-focus rather than as speed, so this uses an SVG `feGaussianBlur` with a single-axis deviation instead. A blurred layer has soft, part-transparent edges and the seam between the two scenes sits inside the frame for the whole cut, so each layer is grown past its own edges by roughly 3σ. That overscan is sized against the **short** axis: a uniform scale driven by the width under-covers the short side of a 16:9 frame and bites a transparent corner mid-cut. `punch` front-loads the move into the middle of the window. `1` is the house ease and reads as a push. The shaping curve is exact at both ends by construction, so a settled scene carries neither offset nor filter. Exports `transitionWhipPan()` and `getTransitionWhipPanDuration()` for use with `TransitionSeries.Transition`. Requires `@remotion/transitions`. Run `npx remotion add @remotion/transitions` if not already installed. ## Usage ```tsx import { transitionWhipPan } from "@/remotion/primitives/transition-whip-pan"; <TransitionSeries.Transition {...transitionWhipPan({ direction: "from-left", blur: 26 })} /> ``` ## Props | Name | Type | Default | Description | | --- | --- | --- | --- | | `durationInFrames` | `number` | `14` | Transition overlap length. A whip is short by definition. | | `direction` | `"from-left" \| "from-right" \| "from-top" \| "from-bottom"` | `"from-left"` | Side the next scene arrives from. | | `blur` | `number` | `26` | Peak blur in px along the travel axis, at the fastest point. | | `travel` | `number` | `1` | Share of the frame each scene travels. Below 1 shows background between them. | | `punch` | `number` | `2.2` | How hard the move is front-loaded into the middle. 1 is the house ease and reads as a push. | | `variant` | `"linear" \| "spring" \| "editorial"` | `"editorial"` | Timing curve. | ## Related - [Spatial Push](https://remotionui.com/docs/components/spatial-push.md) - [Chromatic Aberration Wipe](https://remotionui.com/docs/components/chromatic-aberration-wipe.md) ## Machine-readable references - Props and usage as JSON: https://remotionui.com/ai/components/transition-whip-pan.json - Component index: https://remotionui.com/ai/components.json --- # Transition Wipe > Wipe transition helper for TransitionSeries. Source: https://remotionui.com/docs/components/transition-wipe ## Installation ```bash npx remotion-ui@latest add transition-wipe ``` Exports `transitionWipe()` for directional wipe transitions between scenes. ## Usage ```tsx import { transitionWipe } from "@/remotion/primitives/transition-wipe"; <TransitionSeries.Transition {...transitionWipe({ direction: "from-left" })} /> ``` ## Props | Name | Type | Default | Description | | --- | --- | --- | --- | | `durationInFrames` | `number` | `22` | Transition overlap length. | | `direction` | `string` | `"from-left"` | Wipe direction. | ## Related - [Transition Fade](https://remotionui.com/docs/components/transition-fade.md) - [Transition Clock Wipe](https://remotionui.com/docs/components/transition-clock-wipe.md) ## Machine-readable references - Props and usage as JSON: https://remotionui.com/ai/components/transition-wipe.json - Component index: https://remotionui.com/ai/components.json --- # Zoom Through > The camera pushes through one scene and lands in the next. Source: https://remotionui.com/docs/components/zoom-through ## Installation ```bash npx remotion-ui@latest add zoom-through ``` Both scenes travel the same way through the lens: the outgoing one keeps pushing past it, blurring as it goes, while the incoming one arrives out of the same move and settles at exactly 1×, no residual scale is left on the scene once the cut is over. `maxScale` is how far the camera travels and `blurPeak` the blur at the fastest point of the move. It rides a velocity envelope, so it is exactly 0 at both ends of the overlap and reaches `blurPeak` at the midpoint, and the blurred layer is overscanned so its soft edge never exposes the background. `direction: "out"` inverts the move so the camera pulls back from the frame instead of driving through it. Exports `transitionZoomThrough()` and `getTransitionZoomThroughDuration()` for use with `TransitionSeries.Transition`. Requires `@remotion/transitions`. Run `npx remotion add @remotion/transitions` if not already installed. ## Usage ```tsx import { transitionZoomThrough } from "@/remotion/primitives/zoom-through"; <TransitionSeries.Transition {...transitionZoomThrough({ maxScale: 2.4 })} /> ``` ## Props | Name | Type | Default | Description | | --- | --- | --- | --- | | `durationInFrames` | `number` | `20` | Transition overlap length. | | `maxScale` | `number` | `2.4` | Scale the camera travels through. | | `blurPeak` | `number` | `8` | Blur radius in px at the fastest point of the move. | | `direction` | `"in" \| "out"` | `"in"` | Push the camera through the frame, or pull back from it. | | `variant` | `"linear" \| "spring" \| "editorial"` | `"editorial"` | Timing curve. | ## Related - [Spatial Push](https://remotionui.com/docs/components/spatial-push.md) - [Blur Reveal](https://remotionui.com/docs/components/blur-reveal.md) ## Machine-readable references - Props and usage as JSON: https://remotionui.com/ai/components/zoom-through.json - Component index: https://remotionui.com/ai/components.json --- # Compositions > Full video templates that combine scenes, transitions, and audio. Source: https://remotionui.com/docs/components/compositions Compositions are complete videos built from the other components. Install one as a starting point and edit its scenes, copy, and timing. ## Components - [AI Composer Showcase](https://remotionui.com/docs/components/ai-composer-showcase.md): Reel cutting through five AI composer interfaces (ChatGPT, Claude, v0, Claude Code, and OpenCode), with title and end cards. - [AI Generation Canvas](https://remotionui.com/docs/components/ai-generation-canvas.md): Prompt-to-dashboard generation composition with morphing input, skeleton shimmer, and card reveals. - [Bento Pan](https://remotionui.com/docs/components/bento-pan.md): A camera pan across a bento grid of metric cards. - [Browser Flow](https://remotionui.com/docs/components/browser-flow.md): Browser Flow for Remotion. - [Creator Reel](https://remotionui.com/docs/components/creator-reel.md): Vertical creator media composition template. - [Dashboard Populate](https://remotionui.com/docs/components/dashboard-populate.md): Dashboard Populate for Remotion. - [Data Story](https://remotionui.com/docs/components/data-story.md): Data storytelling composition template. - [Deploy Reveal](https://remotionui.com/docs/components/deploy-reveal.md): Deploy Reveal for Remotion. - [Ecosystem Orbit](https://remotionui.com/docs/components/ecosystem-orbit.md): Ecosystem Orbit for Remotion. - [Hero Device Assemble](https://remotionui.com/docs/components/hero-device-assemble.md): Hero Device Assemble for Remotion. - [Hero Loop](https://remotionui.com/docs/components/hero-loop.md): 12-second seamless brand ident, the RemotionUI logo animated from its own parts over the site's phosphor light. - [Image Expand](https://remotionui.com/docs/components/image-expand.md): A still opens from a card to full frame, then takes its caption. - [Intro](https://remotionui.com/docs/components/intro.md): 5-second branded intro composition. - [Landing Code Showcase](https://remotionui.com/docs/components/landing-code-showcase.md): Landing Code Showcase for Remotion. - [Live Code Split](https://remotionui.com/docs/components/live-code-split.md): An editor and its rendered output side by side. - [Podcast Clip](https://remotionui.com/docs/components/podcast-clip.md): Podcast composition with audio visuals and captions. - [Pricing Focus](https://remotionui.com/docs/components/pricing-focus.md): Pricing Focus for Remotion. - [Showcase](https://remotionui.com/docs/components/showcase.md): Full demo reel chaining scenes with TransitionSeries fades. - [Social Clip](https://remotionui.com/docs/components/social-clip.md): 9:16 Remotion social clip template with hook, captions, and CTA. Install with npx remotion-ui@latest add social-clip. - [Tool Menu Slide](https://remotionui.com/docs/components/tool-menu-slide.md): Tool Menu Slide for Remotion. - [Tutorial Clip](https://remotionui.com/docs/components/tutorial-clip.md): Tutorial composition for demos and explainers. --- # AI Composer Showcase > Reel cutting through five AI composer interfaces (ChatGPT, Claude, v0, Claude Code, and OpenCode), with title and end cards. Source: https://remotionui.com/docs/components/ai-composer-showcase ## Installation ```bash npx remotion-ui@latest add ai-composer-showcase ``` A title card fades into five composer interfaces in sequence (ChatGPT, Claude, v0, Claude Code, and OpenCode), each labelled with its standout feature, then closes on an end card. Built from the five AI composer scenes. Swap the `SCENES` list in the composition source to reorder, drop, or add interfaces. ## Usage ```tsx import { AiComposerShowcase } from "@/compositions/ai-composer-showcase"; <AiComposerShowcase /> ``` 1920×1080 showcase reel: title card, five AI composer scenes (ChatGPT, Claude, v0, Claude Code, OpenCode) each with a feature label, then an end card. No props; customize by editing the SCENES list in source. ## Related - [ChatGPT](https://remotionui.com/docs/components/chat-gpt.md) - [Claude Chat](https://remotionui.com/docs/components/claude-chat.md) - [v0](https://remotionui.com/docs/components/v0.md) - [Claude Code](https://remotionui.com/docs/components/claude-code.md) - [OpenCode](https://remotionui.com/docs/components/opencode.md) ## Machine-readable references - Props and usage as JSON: https://remotionui.com/ai/components/ai-composer-showcase.json - Component index: https://remotionui.com/ai/components.json --- # AI Generation Canvas > Prompt-to-dashboard generation composition with morphing input, skeleton shimmer, and card reveals. Source: https://remotionui.com/docs/components/ai-generation-canvas ## Installation ```bash npx remotion-ui@latest add ai-generation-canvas ``` From prompt to dashboard in one beat: type a prompt, morph the input into a header, shimmer skeleton cards, then flip to live metrics. Generic AI workflow scene, not a branded product interface. Customize `prompt`, `accentColor`, and `cardCount` for your video. ## Usage ```tsx import { AiGenerationCanvas } from "@/compositions/ai-generation-canvas"; <AiGenerationCanvas prompt="Generate a revenue dashboard for this launch" accentColor="#e8b86d" cardCount={4} /> ``` Responsive prompt-to-dashboard generation beat with safe-area layout, skeleton shimmer, and card flips. ## Props | Name | Type | Default | Description | | --- | --- | --- | --- | | `prompt` | `string` | - | Prompt typed into the input during phase one. | | `accentColor` | `string` | - | Accent for border, shimmer, and chart highlights. | | `cardCount` | `number` | - | Dashboard cards revealed in the grid. Clamped between 1 and 6. | | `metrics` | `AiGenerationMetric[]` | - | Labels, values, and optional deltas for the revealed dashboard cards. | | `eyebrow` | `string` | - | Small label above the generated dashboard headline. | | `statusLabel` | `string` | - | Header status text shown after the prompt morphs. | | `speed` | `number` | - | Timeline multiplier for the composition beat. | ## Related - [Dashboard Populate](https://remotionui.com/docs/components/dashboard-populate.md) - [Chat to Preview](https://remotionui.com/docs/components/chat-to-preview.md) ## Machine-readable references - Props and usage as JSON: https://remotionui.com/ai/components/ai-generation-canvas.json - Component index: https://remotionui.com/ai/components.json --- # Bento Pan > A camera pan across a bento grid of metric cards. Source: https://remotionui.com/docs/components/bento-pan ## Installation ```bash npx remotion-ui@latest add bento-pan ``` A 3x3 bento of metric cards under a slow camera move: each card springs in on a stagger, the grid drifts across the frame for the whole hold, and the beat closes by settling in and dimming rather than cutting to black. Pass `tiles` to change the grid. Each tile carries a `label`, the `value` that has to read at small sizes, an optional `note`, and an optional `trend` of bar heights between 0 and 1. Nine tiles is the sweet spot, more than that and the figures stop being legible. ## Usage ```tsx import { BentoPan } from "@/compositions/bento-pan"; <BentoPan /> ``` 1920×1080 diagonal bento grid pan with vignette. ## Props | Name | Type | Default | Description | | --- | --- | --- | --- | | `backgroundColor` | `string` | `"#080810"` | Stage background. | ## Related - [Media Sequence](https://remotionui.com/docs/components/media-sequence.md) - [Showcase](https://remotionui.com/docs/components/showcase.md) ## Machine-readable references - Props and usage as JSON: https://remotionui.com/ai/components/bento-pan.json - Component index: https://remotionui.com/ai/components.json --- # Browser Flow > Browser Flow for Remotion. Source: https://remotionui.com/docs/components/browser-flow ## Installation ```bash npx remotion-ui@latest add browser-flow ``` Browser Flow. ## Usage ```tsx import { BrowserFlow } from "@/compositions/browser-flow"; <BrowserFlow url="remotionui.com/docs" title="Browse the registry" /> ``` 1920×1080 URL-to-preview flow using chat-to-preview scene. ## Props | Name | Type | Default | Description | | --- | --- | --- | --- | | `url` | `string` | - | URL shown in the title card subtitle. | | `title` | `string` | - | Opening headline. | ## Related - [Chat to Preview](https://remotionui.com/docs/components/chat-to-preview.md) - [Title Card](https://remotionui.com/docs/components/title-card.md) ## Machine-readable references - Props and usage as JSON: https://remotionui.com/ai/components/browser-flow.json - Component index: https://remotionui.com/ai/components.json --- # Creator Reel > Vertical creator media composition template. Source: https://remotionui.com/docs/components/creator-reel ## Installation ```bash npx remotion-ui@latest add creator-reel ``` Combine hook, talking-head, comment, b-roll, captions, and end-card scenes into a complete vertical reel. ## Usage ```tsx import { CreatorReel } from "@/compositions/creator-reel"; <CreatorReel mediaSrc={staticFile("speaker.mp4")} audioSrc={staticFile("voice.wav")} captions={captions} /> ``` 9:16 creator template. Advanced tier. ## Props | Name | Type | Default | Description | | --- | --- | --- | --- | | `hookHeadline` | `string` | - | Opening hook headline (auto-fit in portrait). | | `hookSubtitle` | `string` | - | Supporting line under the hook. | | `mediaSrc` | `string` | - | Speaker image or video source. | | `mediaFit` | `"cover" \| "contain"` | `"cover"` | Speaker media object-fit behavior. | | `audioSrc` | `string` | - | Optional audio source for waveform visuals. | | `captions` | `Caption[]` | - | Synced captions layered over the talking-head scene. | | `talkingHeadEyebrow` | `string` | - | Eyebrow label above the talking-head title. | | `talkingHeadTitle` | `string` | - | Short title in the talking-head layout. | | `comment` | `string` | - | Comment callout body text. | | `author` | `string` | - | Comment author display name. | | `handle` | `string` | - | Comment author handle. | | `bRollItems` | `BRollItem[]` | - | Media cards for the proof/b-roll section. | | `bRollTitle` | `string` | - | Headline beside the b-roll stack. | | `bRollKicker` | `string` | `"Proof beats"` | Eyebrow above the b-roll headline. | | `accentColor` | `string` | - | Accent used across hook, captions, and end card. | | `ctaTitle` | `string` | - | End card headline (separate from hook). | | `ctaLabel` | `string` | - | End card CTA pill label. | ## Related - [Hook Card](https://remotionui.com/docs/components/hook-card.md) - [Talking Head Layout](https://remotionui.com/docs/components/talking-head-layout.md) - [Comment Callout](https://remotionui.com/docs/components/comment-callout.md) ## Machine-readable references - Props and usage as JSON: https://remotionui.com/ai/components/creator-reel.json - Component index: https://remotionui.com/ai/components.json --- # Dashboard Populate > Dashboard Populate for Remotion. Source: https://remotionui.com/docs/components/dashboard-populate ## Installation ```bash npx remotion-ui@latest add dashboard-populate ``` Dashboard Populate. ## Usage ```tsx import { DashboardPopulate } from "@/compositions/dashboard-populate"; <DashboardPopulate metrics={metrics} barData={barData} /> ``` 1920×1080 metric ticker then animated bar chart, fading between beats. ## Props | Name | Type | Default | Description | | --- | --- | --- | --- | | `metrics` | `MetricTickerItem[]` | - | Metric cards shown in the opening ticker beat. | | `barData` | `ChartDatum[]` | - | Bars charted in the closing beat. | | `metricsTitle` | `string` | `"Dashboard waking up"` | Title over the metric ticker beat. | | `chartTitle` | `string` | `"Weekly throughput"` | Title over the bar chart beat. | | `backgroundColor` | `string` | `"#080810"` | Scene background color. | ## Related - [Metric Ticker](https://remotionui.com/docs/components/metric-ticker.md) - [Animated Bar Chart](https://remotionui.com/docs/components/animated-bar-chart.md) ## Machine-readable references - Props and usage as JSON: https://remotionui.com/ai/components/dashboard-populate.json - Component index: https://remotionui.com/ai/components.json --- # Data Story > Data storytelling composition template. Source: https://remotionui.com/docs/components/data-story ## Installation ```bash npx remotion-ui@latest add data-story ``` Turn metrics, chart data, and process context into a complete explainer. ## Usage ```tsx import { DataStory } from "@/compositions/data-story"; <DataStory barData={barData} metrics={metrics} steps={steps} /> ``` 1920×1080 data explainer template. Advanced tier. ## Props | Name | Type | Default | Description | | --- | --- | --- | --- | | `title` | `string` | - | Opening hook headline (auto-fit). | | `subtitle` | `string` | - | Supporting line under the hook. | | `barData` (required) | `ChartDatum[]` | - | Bar chart data. | | `metrics` (required) | `MetricTickerItem[]` | - | Metric cards. | | `steps` (required) | `TimelineStep[]` | - | Context steps. | | `chartTitle` | `string` | - | Headline on the bar chart scene. | | `metricsTitle` | `string` | - | Headline on the metric ticker scene. | | `timelineTitle` | `string` | - | Headline on the timeline scene. | | `insight` | `string` | - | Takeaway quote in the insight bumper. | | `insightEyebrow` | `string` | - | Eyebrow above the insight quote. | | `ctaTitle` | `string` | - | End card headline (separate from hook). | | `ctaLabel` | `string` | - | End card CTA pill label. | ## Related - [Animated Bar Chart](https://remotionui.com/docs/components/animated-bar-chart.md) - [Metric Ticker](https://remotionui.com/docs/components/metric-ticker.md) - [Timeline Steps](https://remotionui.com/docs/components/timeline-steps.md) ## Machine-readable references - Props and usage as JSON: https://remotionui.com/ai/components/data-story.json - Component index: https://remotionui.com/ai/components.json --- # Deploy Reveal > Deploy Reveal for Remotion. Source: https://remotionui.com/docs/components/deploy-reveal ## Installation ```bash npx remotion-ui@latest add deploy-reveal ``` Deploy Reveal. ## Usage ```tsx import { DeployReveal } from "@/compositions/deploy-reveal"; <DeployReveal /> ``` 1920×1080 terminal deploy log then browser reveal. ## Related - [Terminal Simulator](https://remotionui.com/docs/components/terminal-simulator.md) - [Device Mockup Zoom](https://remotionui.com/docs/components/device-mockup-zoom.md) ## Machine-readable references - Props and usage as JSON: https://remotionui.com/ai/components/deploy-reveal.json - Component index: https://remotionui.com/ai/components.json --- # Ecosystem Orbit > Ecosystem Orbit for Remotion. Source: https://remotionui.com/docs/components/ecosystem-orbit ## Installation ```bash npx remotion-ui@latest add ecosystem-orbit ``` Ecosystem Orbit. ## Usage ```tsx import { EcosystemOrbit } from "@/compositions/ecosystem-orbit"; <EcosystemOrbit centerLabel="Your product" satellites={["GitHub", "Vercel", "Stripe"]} /> ``` 1920×1080 integration orbit with pulsing connection lines. ## Props | Name | Type | Default | Description | | --- | --- | --- | --- | | `centerLabel` | `string` | `"RemotionUI"` | Center brand label. | | `satellites` | `string[]` | - | Orbiting integration labels. | | `accentColor` | `string` | `"#e8b86d"` | Center accent color. | ## Related - [Logo Reveal](https://remotionui.com/docs/components/logo-reveal.md) - [Showcase](https://remotionui.com/docs/components/showcase.md) ## Machine-readable references - Props and usage as JSON: https://remotionui.com/ai/components/ecosystem-orbit.json - Component index: https://remotionui.com/ai/components.json --- # Hero Device Assemble > Hero Device Assemble for Remotion. Source: https://remotionui.com/docs/components/hero-device-assemble ## Installation ```bash npx remotion-ui@latest add hero-device-assemble ``` Hero Device Assemble. ## Usage ```tsx import { HeroDeviceAssemble } from "@/compositions/hero-device-assemble"; <HeroDeviceAssemble title="Ship on every screen" /> ``` 1920×1080 product hero. Title card then device mockup assemble. ## Props | Name | Type | Default | Description | | --- | --- | --- | --- | | `title` | `string` | - | Opening title card headline. | | `subtitle` | `string` | - | Supporting line under the title. | ## Related - [Title Card](https://remotionui.com/docs/components/title-card.md) - [Device Mockup Zoom](https://remotionui.com/docs/components/device-mockup-zoom.md) ## Machine-readable references - Props and usage as JSON: https://remotionui.com/ai/components/hero-device-assemble.json - Component index: https://remotionui.com/ai/components.json --- # Hero Loop > 12-second seamless brand ident, the RemotionUI logo animated from its own parts over the site's phosphor light. Source: https://remotionui.com/docs/components/hero-loop ## Installation ```bash npx remotion-ui@latest add hero-loop ``` A silent 1920×1080 ident built to run on loop forever. The RemotionUI lockup holds over the site's gold phosphor light and moves three times, each move built from the logo's own anatomy: the back frame slides out from behind the front frame in parallax, the gold play triangle presses and springs back with a bloom, and the wordmark drops behind a mask and rises back letter by letter. Every move uses keyframed bezier curves with anticipation and a small overshoot, and each lands exactly on its rest pose, so the last frame hands back to frame 0 with no seam. The light is a single-pass port of the homepage shader, driven by frame on a closed path. Pass `background="transparent"` to drop the stage and light so a page can show its own background through the video; `tone="light"` inks the wordmark for a light page. ## Usage ```tsx import { HeroLoop } from "@/compositions/hero-loop"; <HeroLoop /> <HeroLoop background="transparent" tone="light" /> ``` 12-second silent brand ident: the RemotionUI logo animated from its own parts (parallax frames, play press, wordmark re-reveal) over a port of the site's phosphor light. Loops without a seam. The light needs WebGL2 and falls back to a flat stage. ## Props | Name | Type | Default | Description | | --- | --- | --- | --- | | `background` | `"phosphor" \| "transparent"` | `"phosphor"` | Paint the gold phosphor stage, or nothing so the page shows through. | | `tone` | `"dark" \| "light"` | `"dark"` | Page theme under the transparent variant; light inks the wordmark dark. | ## Related - [Logo Reveal](https://remotionui.com/docs/components/logo-reveal.md) - [Path Draw](https://remotionui.com/docs/components/path-draw.md) ## Machine-readable references - Props and usage as JSON: https://remotionui.com/ai/components/hero-loop.json - Component index: https://remotionui.com/ai/components.json --- # Image Expand > A still opens from a card to full frame, then takes its caption. Source: https://remotionui.com/docs/components/image-expand ## Installation ```bash npx remotion-ui@latest add image-expand ``` Two beats. The frame opens from a small card to the full canvas on a perceptual scale ramp, and once it has landed the caption block rises over a scrim at the bottom: `eyebrow`, `title`, `subtitle`. `src` is the point of the component. Without one the frame expands as a tinted plate, which is useful as a transition card but is not what the name promises. Any `<Img>`-compatible source works; use `staticFile()` for local media. ## Usage ```tsx import { ImageExpand } from "@/compositions/image-expand"; <ImageExpand accentColor="#e8b86d" /> ``` 1920×1080 thumbnail expands to full frame. ## Props | Name | Type | Default | Description | | --- | --- | --- | --- | | `accentColor` | `string` | `"#e8b86d"` | Thumbnail accent color. | ## Related - [Media Frame](https://remotionui.com/docs/components/media-frame.md) - [Zoom Pan Frame](https://remotionui.com/docs/components/zoom-pan-frame.md) ## Machine-readable references - Props and usage as JSON: https://remotionui.com/ai/components/image-expand.json - Component index: https://remotionui.com/ai/components.json --- # Intro > 5-second branded intro composition. Source: https://remotionui.com/docs/components/intro ## Installation ```bash npx remotion-ui@latest add intro ``` Registers a `<Composition>` in your `Root.tsx` automatically. The chapter marker and headline stand up first, then the `topics` rail staggers in along the bottom to say what the section covers. One `<Sequence>` wrapped in one `<FadeOut>` closes the last second. A second `<TitleCard>` mounted inside the fade would restart its own entrance from frame 0 and drop the subtitle. ## Usage ```tsx import { Intro } from "@/remotion/compositions/intro"; <Intro title="My Product" subtitle="Launch video" /> ``` Full intro sequence with staggered title, subtitle, and progress bar. ## Props | Name | Type | Default | Description | | --- | --- | --- | --- | | `title` | `string` | `"Chapter open"` | Main title. | | `subtitle` | `string` | - | Tagline under the title. | | `backgroundColor` | `string` | - | Page background behind the intro. | | `accentColor` | `string` | - | Accent used by the progress bar and title. | ## Related - [Showcase](https://remotionui.com/docs/components/showcase.md) - [Title Card](https://remotionui.com/docs/components/title-card.md) ## Machine-readable references - Props and usage as JSON: https://remotionui.com/ai/components/intro.json - Component index: https://remotionui.com/ai/components.json --- # Landing Code Showcase > Landing Code Showcase for Remotion. Source: https://remotionui.com/docs/components/landing-code-showcase ## Installation ```bash npx remotion-ui@latest add landing-code-showcase ``` Landing Code Showcase. ## Usage ```tsx import { LandingCodeShowcase } from "@/compositions/landing-code-showcase"; <LandingCodeShowcase /> ``` 1920×1080 title card plus install command code reveal. ## Related - [Title Card](https://remotionui.com/docs/components/title-card.md) - [Code Reveal](https://remotionui.com/docs/components/code-reveal.md) ## Machine-readable references - Props and usage as JSON: https://remotionui.com/ai/components/landing-code-showcase.json - Component index: https://remotionui.com/ai/components.json --- # Live Code Split > An editor and its rendered output side by side. Source: https://remotionui.com/docs/components/live-code-split ## Installation ```bash npx remotion-ui@latest add live-code-split ``` The file is written on the left. The moment its JSX finishes typing, the pane on the right wakes up and starts rendering the clip that code describes, then replays it on a loop with a playhead running under it, the way a preview player does. `previewAt` is the frame the pane goes live. It defaults to the frame the sample code's JSX lands on, so change it whenever you pass your own `code`. ## Usage ```tsx import { LiveCodeSplit } from "@/compositions/live-code-split"; <LiveCodeSplit code={sourceCode} /> ``` 1920×1080 code editor then live device preview. ## Props | Name | Type | Default | Description | | --- | --- | --- | --- | | `code` | `string` | - | Code reveal content. | ## Related - [Code Reveal](https://remotionui.com/docs/components/code-reveal.md) - [Device Mockup Zoom](https://remotionui.com/docs/components/device-mockup-zoom.md) ## Machine-readable references - Props and usage as JSON: https://remotionui.com/ai/components/live-code-split.json - Component index: https://remotionui.com/ai/components.json --- # Podcast Clip > Podcast composition with audio visuals and captions. Source: https://remotionui.com/docs/components/podcast-clip ## Installation ```bash npx remotion-ui@latest add podcast-clip ``` Audio-first template with pulse rings, waveform, captions, and CTA. ## Usage ```tsx import { PodcastClip } from "@/compositions/podcast-clip"; <PodcastClip audioSrc={staticFile("podcast.wav")} captions={captions} /> ``` 9:16 podcast template (1080×1920). ## Props | Name | Type | Default | Description | | --- | --- | --- | --- | | `audioSrc` (required) | `string` | - | Audio source. | | `captions` (required) | `Caption[]` | - | Synced captions. | | `title` | `string` | - | Opening title, reused as the episode title. | | `subtitle` | `string` | `"Pull one quote into a vertical clip"` | Supporting line under the opening title. | | `showName` | `string` | `"Studio Sessions"` | Show name above the episode title. | | `ctaTitle` | `string` | - | End card headline. Defaults to `showName`. | | `ctaLabel` | `string` | - | End card CTA pill label. | ## Related - [Audio Pulse](https://remotionui.com/docs/components/audio-pulse.md) - [Waveform Line](https://remotionui.com/docs/components/waveform-line.md) - [Caption Scene](https://remotionui.com/docs/components/caption-scene.md) ## Machine-readable references - Props and usage as JSON: https://remotionui.com/ai/components/podcast-clip.json - Component index: https://remotionui.com/ai/components.json --- # Pricing Focus > Pricing Focus for Remotion. Source: https://remotionui.com/docs/components/pricing-focus ## Installation ```bash npx remotion-ui@latest add pricing-focus ``` Pricing Focus. ## Usage ```tsx import { PricingFocus } from "@/compositions/pricing-focus"; <PricingFocus tiers={[{ name: "Starter", price: "$0" }, { name: "Studio", price: "$29", featured: true }]} /> ``` 1920×1080 pricing tier focus with lift and dim siblings. ## Props | Name | Type | Default | Description | | --- | --- | --- | --- | | `tiers` | `Array<{ name: string; price: string; featured?: boolean }>` | - | Pricing cards. | ## Related - [Stat Card](https://remotionui.com/docs/components/stat-card.md) - [Feature List](https://remotionui.com/docs/components/feature-list.md) ## Machine-readable references - Props and usage as JSON: https://remotionui.com/ai/components/pricing-focus.json - Component index: https://remotionui.com/ai/components.json --- # Showcase > Full demo reel chaining scenes with TransitionSeries fades. Source: https://remotionui.com/docs/components/showcase ## Installation ```bash npx remotion-ui@latest add showcase ``` Chains `title-card` → `feature-list` → `stat-card` → `end-card` with fade transitions. Adds a `Showcase` composition to your `Root.tsx` on install. ## Usage ```tsx import { Showcase } from "@/remotion/compositions/showcase"; <Showcase title="Product story" subtitle="Install source, compose scenes, render on your timeline" statValue={3} statLabel="Runtime dependencies" /> ``` Demo reel using TransitionSeries across multiple scenes. ## Props | Name | Type | Default | Description | | --- | --- | --- | --- | | `title` | `string` | - | Opening title. | | `subtitle` | `string` | - | Opening subtitle. | | `featureTitle` | `string` | `"Three layers you own"` | Headline on the feature list scene. | | `featureItems` | `string[]` | - | Rows ticked off in the feature list. | | `statValue` | `number` | `3` | Counter value for the stat scene. | | `statLabel` | `string` | `"Runtime dependencies"` | Stat card label. | | `statSuffix` | `string` | `""` | Unit appended to the stat value, e.g. "%". | | `ctaLabel` | `string` | - | End card CTA pill label. | | `ctaUrl` | `string` | - | URL shown on the end card. | ## Related - [Transition Fade](https://remotionui.com/docs/components/transition-fade.md) - [Feature List](https://remotionui.com/docs/components/feature-list.md) ## Machine-readable references - Props and usage as JSON: https://remotionui.com/ai/components/showcase.json - Component index: https://remotionui.com/ai/components.json --- # Social Clip > 9:16 Remotion social clip template with hook, captions, and CTA. Install with npx remotion-ui@latest add social-clip. Source: https://remotionui.com/docs/components/social-clip ## Installation ```bash npx remotion-ui@latest add social-clip ``` Full 1080×1920 social template combining hook title, audiogram, captions, and end card. ## Usage ```tsx import { SocialClip } from "@/compositions/social-clip"; <SocialClip audioSrc={staticFile("podcast.wav")} captions={captions} /> ``` 9:16 social template (1080×1920). Advanced tier. ## Props | Name | Type | Default | Description | | --- | --- | --- | --- | | `audioSrc` (required) | `string` | - | Podcast audio source. | | `captions` (required) | `Caption[]` | - | Synced caption array. | | `hookTitle` | `string` | - | Opening hook headline. | | `hookSubtitle` | `string` | - | Supporting line under the hook. | | `podcastTitle` | `string` | `"Weekly Brief"` | Show name shown over the audiogram body. | | `logoSrc` | `string` | - | Optional brand mark shown in hook, body, and end card. | | `ctaTitle` | `string` | `"Hear the full episode"` | End card headline. | | `ctaLabel` | `string` | - | End card CTA pill label. | | `ctaUrl` | `string` | - | URL shown on the end card. | ## Related - [Caption Scene](https://remotionui.com/docs/components/caption-scene.md) - [Audiogram Scene](https://remotionui.com/docs/components/audiogram-scene.md) - [Auto-Fit Title](https://remotionui.com/docs/components/auto-fit-title.md) ## Machine-readable references - Props and usage as JSON: https://remotionui.com/ai/components/social-clip.json - Component index: https://remotionui.com/ai/components.json --- # Tool Menu Slide > Tool Menu Slide for Remotion. Source: https://remotionui.com/docs/components/tool-menu-slide ## Installation ```bash npx remotion-ui@latest add tool-menu-slide ``` A tool's navigation in motion: the sidebar rows slide in staggered, the highlight steps down the list, and the content panel on the right swaps with it, so the menu is shown doing the job a menu does rather than as four rows on a plate. Duration comes from `lib/preview-config.ts`. ## Usage ```tsx import { ToolMenuSlide } from "@/compositions/tool-menu-slide"; <ToolMenuSlide /> ``` 1920×1080 staggered tool menu slide-in. ## Related - [Feature List](https://remotionui.com/docs/components/feature-list.md) - [Slide Left](https://remotionui.com/docs/components/slide-left.md) ## Machine-readable references - Props and usage as JSON: https://remotionui.com/ai/components/tool-menu-slide.json - Component index: https://remotionui.com/ai/components.json --- # Tutorial Clip > Tutorial composition for demos and explainers. Source: https://remotionui.com/docs/components/tutorial-clip ## Installation ```bash npx remotion-ui@latest add tutorial-clip ``` Full tutorial template: hook, demo frame, spotlight, code reveal, and CTA. ## Usage ```tsx import { TutorialClip } from "@/compositions/tutorial-clip"; <TutorialClip mediaSrc={staticFile("demo.png")} /> ``` 9:16 walkthrough template. `calloutTarget` is read in media pixels and mapped through the same cover crop as the background, so pass `mediaWidth`/`mediaHeight` whenever the capture is not the composition size. ## Props | Name | Type | Default | Description | | --- | --- | --- | --- | | `mediaSrc` (required) | `string` | - | Screenshot or video source. | | `mediaWidth` | `number` | `1280` | Pixel width `calloutTarget` was measured against. | | `mediaHeight` | `number` | `720` | Pixel height `calloutTarget` was measured against. | | `title` | `string` | - | Opening hook title. | | `subtitle` | `string` | - | Supporting line under the hook. | | `calloutTitle` | `string` | `"Tap Render to queue the job"` | Headline on the spotlight callout card. | | `calloutSubtitle` | `string` | - | Supporting line on the callout card. | | `calloutTarget` | `SpotlightTarget` | - | Region to spotlight, in media pixels. | | `code` | `string` | - | Code reveal content. | | `ctaTitle` | `string` | - | End card headline. Defaults to `title`. | | `ctaLabel` | `string` | - | End card CTA pill label. | ## Related - [Media Frame](https://remotionui.com/docs/components/media-frame.md) - [Callout Spotlight](https://remotionui.com/docs/components/callout-spotlight.md) - [Code Reveal](https://remotionui.com/docs/components/code-reveal.md) ## Machine-readable references - Props and usage as JSON: https://remotionui.com/ai/components/tutorial-clip.json - Component index: https://remotionui.com/ai/components.json --- # Helpers > Layout, spring, timing, and stagger utilities the components are built on. Source: https://remotionui.com/docs/components/helpers Helpers are the shared utilities behind the components: layout math, spring presets, frame timing, and a stagger hook. Install them when you write your own scenes. ## Components - [Layout](https://remotionui.com/docs/components/layout.md): Video-safe padding and responsive font scaling. - [Springs](https://remotionui.com/docs/components/springs.md): Shared spring configs for physics-based motion. - [Timing](https://remotionui.com/docs/components/timing.md): Frame helpers, stagger delays, and Bézier enter/exit progress. - [useStagger](https://remotionui.com/docs/components/use-stagger.md): Hook for per-child delayInFrames in custom components. --- # Layout > Video-safe padding and responsive font scaling. Source: https://remotionui.com/docs/components/layout ## Installation ```bash npx remotion-ui@latest add layout ``` ```bash npx remotion-ui@latest add layout ``` ```tsx import { getSafeAreaPadding, scaleFont } from "@/remotion/lib/layout"; const { width, height } = useVideoConfig(); const safeArea = getSafeAreaPadding({ width, height }); const headline = scaleFont(84, width); // 1080p baseline const supporting = scaleFont(44, width); ``` Based on Remotion video-layout guidance: 80px horizontal / 100px vertical safe area at 1080p. ## Machine-readable references - Props and usage as JSON: https://remotionui.com/ai/components/layout.json - Component index: https://remotionui.com/ai/components.json --- # Springs > Shared spring configs for physics-based motion. Source: https://remotionui.com/docs/components/springs ## Installation ```bash npx remotion-ui@latest add springs ``` ```bash npx remotion-ui@latest add springs ``` ```tsx import { springSmooth, springSnappy, springBouncy } from "@/remotion/lib/springs"; const progress = spring({ frame, fps, config: springSnappy, durationInFrames: 30, }); ``` | Token | Feel | |-------|------| | `springSmooth` | Subtle, no overshoot; highlights, wipes | | `springSnappy` | Quick pop; `spring-in` | | `springBouncy` | Playful overshoot | ## Machine-readable references - Props and usage as JSON: https://remotionui.com/ai/components/springs.json - Component index: https://remotionui.com/ai/components.json --- # Timing > Frame helpers, stagger delays, and Bézier enter/exit progress. Source: https://remotionui.com/docs/components/timing ## Installation ```bash npx remotion-ui@latest add timing ``` ```bash npx remotion-ui@latest add timing ``` ```tsx import { secondsToFrames, staggerDelay, enterProgress, exitProgress, EASING_ENTER, } from "@/remotion/lib/timing"; const delay = staggerDelay(index, 8); const opacity = enterProgress(frame, delay, 30); ``` Use `enterProgress` for entrances and `exitProgress` for exits. Most primitives depend on this lib. ## Machine-readable references - Props and usage as JSON: https://remotionui.com/ai/components/timing.json - Component index: https://remotionui.com/ai/components.json --- # useStagger > Hook for per-child delayInFrames in custom components. Source: https://remotionui.com/docs/components/use-stagger ## Installation ```bash npx remotion-ui@latest add use-stagger ``` ```bash npx remotion-ui@latest add use-stagger ``` ```tsx import { useStagger } from "@/remotion/hooks/use-stagger"; function ListItem({ index, label }: { index: number; label: string }) { const delayInFrames = useStagger({ index, staggerInFrames: 8 }); return ( <FadeIn delayInFrames={delayInFrames} durationInFrames={20}> <span>{label}</span> </FadeIn> ); } ``` For wrapping existing children, prefer the `stagger-children` primitive instead. ## Machine-readable references - Props and usage as JSON: https://remotionui.com/ai/components/use-stagger.json - Component index: https://remotionui.com/ai/components.json --- # AI Usage > How coding agents should use RemotionUI with Remotion. Source: https://remotionui.com/docs/ai RemotionUI is the **component layer for Remotion**: production-ready source you install with the CLI. Use [Remotion](https://www.remotion.dev/docs) for framework fundamentals, rendering, Studio, Player, and APIs. Use RemotionUI when you need ready-made components for captions, charts, scenes, transitions, and composition templates. ## Starter prompt For an agent with no MCP server and no installed skill, paste this and go: ## Agent workflow 1. Create or open a Remotion project. 2. Install RemotionUI components with the CLI. 3. Import components from local source paths after installation. 4. Customize the copied files directly. 5. Use Remotion frame APIs for motion. ```bash npx remotion-ui@latest search -q caption ``` ```bash npx remotion-ui@latest add caption-highlight lower-third ``` ```tsx import { CaptionHighlight } from "@/remotion/primitives/caption-highlight"; import { LowerThird } from "@/remotion/scenes/lower-third"; ``` Do not import RemotionUI components from the npm package. The npm package is the CLI only. Components are installed as source files into the user's project. ## Hard rules for agents - Run `npx remotion-ui@latest add <component>` before importing a component. - Import from local project paths such as `@/remotion/primitives/...`, `@/remotion/scenes/...`, or `@/compositions/...`. - Use `useCurrentFrame()`, `interpolate()`, `spring()`, and `<Sequence />` for render-time motion. - Do not use CSS transitions or Tailwind animation classes for video motion. - Preserve source ownership: edit copied component files when customization is needed. ## AI-readable files - [`/llms.txt`](/llms.txt): short agent entry point - [`/llms-full.txt`](/llms-full.txt): full usage guide for LLMs - [`/ai/components.json`](/ai/components.json): component discovery index - `/ai/components/<name>.json`: per-component detail: props (`name`, `type`, `required`, `default`, `description`), usage snippets, install command, import path, and related components - [`/ai/remotionui-agent.md`](/ai/remotionui-agent.md): reusable agent prompt - `/llms.mdx/docs/<path>`: any docs page as raw Markdown. The **Copy page for AI** button at the top of each page copies exactly this ## Agent-native tooling - `npx remotion-ui init --agent-skill` installs a Claude Code skill into the project at `.claude/skills/remotionui-agent/SKILL.md`, covering the CLI workflow and animation rules above. - Every CLI command supports `--json` for structured output and structured `{code, message}` errors, safe for agents to parse instead of scraping stdout. - `remotion-ui-mcp` is an MCP server exposing the registry as agent tools (`list-components`, `search-components`, `get-component-detail`, `get-install-command`) over stdio, for MCP-capable agents. See [MCP Server](https://remotionui.com/docs/mcp.md) for install and config. - Registry items may declare `compat.remotion`; `add` warns on a mismatch with the installed Remotion version. See [Remotion version compatibility](https://remotionui.com/docs/cli.md). ## Start with compositions Browse the [component catalog](https://remotionui.com/docs/components.md) for flagship compositions and install commands. - [Social Clip](https://remotionui.com/docs/components/social-clip.md): A vertical clip with captions, audio visuals, and CTA. - [Data Story](https://remotionui.com/docs/components/data-story.md): A chart-led video with metrics and timeline steps. - [Podcast Clip](https://remotionui.com/docs/components/podcast-clip.md): An audio-first clip with waveform and synced captions. --- # MCP Server > Expose the RemotionUI registry to agents as MCP tools. Source: https://remotionui.com/docs/mcp `remotion-ui-mcp` is a [Model Context Protocol](https://modelcontextprotocol.io) server that exposes the RemotionUI registry as agent-callable tools over stdio. It reuses the CLI's registry client, so results match `remotion-ui search`, `view`, and `add` exactly. Use it when your agent should *discover* components on its own. For installing them, the agent still runs the CLI. The server returns the command, it does not write files. ## Tools | Tool | Input | Returns | |------|-------|---------| | `list-components` | `registryUrl?` | The full registry index | | `search-components` | `query?`, `lane?`, `tier?`, `registryUrl?` | Matching index entries | | `get-component-detail` | `name`, `preset?`, `registryUrl?` | The full registry item: files, dependencies, `composition`, `compat` | | `get-install-command` | `name` | `npx remotion-ui@latest add <name>` | Lanes: `atoms`, `signals`, `vectors`, `spatial`, `blocks`, `cuts`, `reels`. Tiers: `core`, `advanced`. Failures come back as `isError` results carrying the same `{ code, message }` envelope as the CLI's `--json` mode. See [Error codes](https://remotionui.com/docs/cli.md). ## Install The server is published to npm, no checkout required. ```bash npx remotion-ui-mcp ``` ### Claude Code Add to `.mcp.json` in your project root: ```json { "mcpServers": { "remotion-ui": { "command": "npx", "args": ["-y", "remotion-ui-mcp"] } } } ``` ### Other MCP clients Point any stdio-capable client at the same command. Claude Desktop uses the same `command` / `args` shape in its config file. ### From a checkout Working on the server itself, or pinning to unreleased changes: ```bash git clone https://github.com/riaz37/remotion-ui cd remotion-ui && pnpm install pnpm --filter remotion-ui-mcp build ``` That produces `packages/remotion-ui-mcp/dist/index.js`. Point `command: "node"` at it instead. ## Agent workflow with MCP 1. `search-components` or `list-components` to find a fit. 2. `get-component-detail` to read files, dependencies, and composition metadata. 3. `get-install-command`, then run it with the CLI. 4. Import from local source paths, never from the `remotion-ui` npm package. The [agent skill](https://remotionui.com/docs/installation.md) encodes the same workflow for agents that do not speak MCP. See [AI Usage](https://remotionui.com/docs/ai.md) for the plain HTTP endpoints (`/llms.txt`, `/ai/components.json`). --- # Registry > Author and build custom RemotionUI registries. Source: https://remotionui.com/docs/registry ## Adding a component 1. Create source under `apps/web/registry/bases/default/` 2. Add an entry to `registry.json` 3. Run `pnpm registry:build` ## Item types | Type | Folder | Install path | |------|--------|--------------| | `registry:ui` | `primitives/` | `src/remotion/primitives/` | | `registry:block` | `scenes/`, `compositions/` | `src/remotion/scenes/` or `src/compositions/` | | `registry:lib` | `lib/` | `src/remotion/lib/` | | `registry:hook` | `hooks/` | `src/remotion/hooks/` | ## Custom registry (CLI) ```bash npx remotion-ui@latest build ./registry.json -o ./public/r ``` See [CLI Reference](https://remotionui.com/docs/cli.md) for `diff` and `update` workflows.