UI/Components/Text elements/Typing Text

Typing Text

A Remotion video component that animates text with a typewriter effect.

0:00 / 0:06

Installation

CLI

npx shadcn@latest add "https://clippkit.com/r/typing-text"

Manual

Create a new file, for example, at src/components/clippkit/typing-text.tsx (or your preferred location) and paste the following code into it.

/**
 * Free Remotion Template Component
 * ---------------------------------
 * This template is free to use in your projects!
 * Credit appreciated but not required.
 *
 * Created by the team at https://www.reactvideoeditor.com
 *
 * Happy coding and building amazing videos! 🎉
 */
 
"use client";
 
import React from "react";
import { interpolate, useCurrentFrame } from "remotion";
 
interface TypingTextProps {
  text?: string;
  textColor?: string;
  cursorColor?: string;
  fontSize?: string;
  fontFamily?: string;
  fontWeight?: string;
  durationInFramesToType?: number; // Total frames to type out the entire text
  cursorBlinkSpeed?: number; // Frames for one blink cycle (e.g., 15 means it blinks every 15 frames)
}
 
export function TypingText({
  text = "TYPE ME...",
  textColor = "white",
  cursorColor = "white",
  fontSize = "3rem",
  fontFamily = "'Courier New', monospace",
  fontWeight = "bold",
  durationInFramesToType, // If not provided, defaults to text.length * 5 frames
  cursorBlinkSpeed = 15,
}: TypingTextProps) {
  const frame = useCurrentFrame();
 
  const actualDurationInFramesToType =
    durationInFramesToType !== undefined
      ? durationInFramesToType
      : text.length * 5; // Default: 5 frames per character
 
  const visibleCharacters = Math.floor(
    interpolate(frame, [0, actualDurationInFramesToType], [0, text.length], {
      extrapolateRight: "clamp",
    })
  );
 
  const charactersToRender = text.slice(0, visibleCharacters).split("");
 
  return (
    <div
      style={{
        position: "absolute",
        top: "50%",
        left: "50%",
        transform: "translate(-50%, -50%)",
        width: "90%", // Ensure it doesn't overflow easily
        textAlign: "center",
        padding: "1rem", // Add some padding
      }}
    >
      <span
        style={{
          fontFamily,
          fontSize,
          fontWeight,
          color: textColor,
          display: "inline-block", // To keep cursor on the same line
        }}
      >
        {charactersToRender.map((char, index) => (
          <React.Fragment key={index}>
            {char === " " ? "\u00A0" : char}
          </React.Fragment>
        ))}
      </span>
      <span
        style={{
          display: "inline-block",
          fontFamily,
          fontSize,
          fontWeight,
          color: cursorColor,
          opacity: frame % cursorBlinkSpeed < cursorBlinkSpeed / 2 ? 1 : 0,
          marginLeft: "0.2rem", // Space between text and cursor
          verticalAlign: "middle",
        }}
      >

      </span>
    </div>
  );
}
Update the import paths in your Remotion compositions if you placed the file in a different location than shown in the usage examples.

Usage

Once the TypingText component is added to your project (either via CLI or Manually), you can integrate it into your Remotion project by importing it and defining a Composition.

Prerequisite

Ensure you have a Remotion project set up. If not, please refer to the Remotion documentation to get started.

Project Structure Example

Here’s an example folder layout showing where to place the component and how it fits into a typical Remotion project

app/main.tsx
import { Player } from "@remotion/player";
 
import TypingText from "../components/typing-text";
 
export function TypingTextDemo() {
  const typingTextProps = {
    text: "Typing text...",
    textColor: "var(--foreground)",
    cursorColor: "var(--primary)",
    fontSize: "2.5rem",
    fontFamily: "monospace",
    fontWeight: "normal",
    durationInFramesToType: 120, // Type out over 4 seconds at 30fps
    cursorBlinkSpeed: 15, // Default blink speed
  };
 
  return (
    <Player
      component={TypingText}
      inputProps={typingTextProps}
      durationInFrames={180} // Allow time for text to be fully typed + pause
      compositionWidth={480}
      compositionHeight={270} // 16:9 aspect ratio
      fps={30}
      style={{
        width: "100%",
        height: "100%", // Player will scale to fit its container
      }}
      autoPlay
      controls // Show player controls
      loop // Loop the animation
    />
  );
}

Define a Composition

In your Remotion project's entry file (commonly src/Root.tsx, src/index.tsx, app/main.tsx), import TypingText and define a Composition.

app/main.tsx (or equivalent)
import { Player } from "@remotion/player";

import TypingText from "@/components/clippkit/typing-text"; // Assuming you placed it in src/components/clippkit

export default function TypingTextDemo() {
  const typingTextProps = {
    text: "This is a typing animation!",
    textColor: "var(--foreground)",
    cursorColor: "var(--primary)",
    fontSize: "2.5rem",
    fontFamily: "monospace",
    fontWeight: "normal",
    durationInFramesToType: 120,
    cursorBlinkSpeed: 15,
  };

  return (
    <Player
      component={TypingText}
      inputProps={typingTextProps}
      durationInFrames={180}
      compositionWidth={480}
      compositionHeight={270}
      fps={30}
      style={{
        width: "100%",
        height: "100%",
      }}
      autoPlay
      controls
      loop
    />
  );
}

API Reference

The component exported as TypingText (e.g., from apps/docs/ui/typing-text.tsx or your project's component path) accepts the following props to customize its animation and appearance:

PropTypeDefault ValueDescription
textstring"TYPE ME..."The text content to display.
textColorstring"white"The color of the text. Accepts any valid CSS color value.
cursorColorstring"white"The color of the cursor. Accepts any valid CSS color value.
fontSizestring"3rem"The font size of the text. Accepts any valid CSS font-size value.
fontFamilystring"'Courier New', monospace"The font family of the text. Accepts any valid CSS font-family value.
fontWeightstring"bold"The font weight of the text. Accepts any valid CSS font-weight value.
durationInFramesToTypenumbertext.length * 5Total frames to type out the entire text. Defaults to 5 frames per character.
cursorBlinkSpeednumber15Frames for one blink cycle of the cursor (e.g., 15 for a blink every 15 frames).

On this page