Typewriter
Character-by-character text reveal with a deterministic blinking cursor.
A typography primitive that reveals text one character at a time using interpolate and substring. The cursor blinks via integer math on the current frame, so it stays consistent across re-renders.
Installation
$ pnpm dlx shadcn@latest add @remocn/typewriterUsage
// src/Root.tsx
import { Composition } from "remotion";
import { Typewriter } from "@/components/remocn/typewriter";
const TypewriterScene = () => (
<Typewriter text="Hello, world" speed={20} fontSize={72} />
);
export const RemotionRoot = () => (
<Composition
id="Typewriter"
component={TypewriterScene}
durationInFrames={120}
fps={30}
width={1280}
height={720}
/>
);Props
| Prop | Type | Default | Description |
|---|---|---|---|
textrequired | string | — | The text to type out. |
cursor | boolean | true | Whether to render the blinking cursor at the end. |
speed | number | 20 | Typing speed in characters per second. |
fontSize | number | 48 | Font size in pixels. |
fontWeight | number | 600 | CSS font-weight. |
color | string | "#171717" | Text color (any valid CSS color). |
cursorColor | string | "#171717" | Color of the blinking cursor block. |
className | string | — | Optional className passed to the underlying span. |
Notes
Deterministic blink
The cursor uses Math.floor(frame / 15) % 2 === 0 instead of setInterval or Math.random(). This is required for Remotion: every frame must be a pure function of frame, otherwise the rendered video will glitch.
Composition length
Make sure your composition's durationInFrames is long enough to fit text.length / speed seconds of typing plus a hold at the end.