Ring Text

Text runs around a tilted 3D band that spins, reading on the near side and mirrored on the far side

Installation
$ pnpm dlx shadcn@latest add @remocn/ring-text

Usage

// src/Root.tsx
import { AbsoluteFill, Composition } from "remotion";
import { RingText } from "@/components/remocn/ring-text";
 
const Ring = () => (
  <AbsoluteFill style={{ backgroundColor: "#d4ff1f" }}>
    <RingText text="Type in motion" color="#d4ff1f" band="#0a0a0a" />
  </AbsoluteFill>
);
 
export const RemotionRoot = () => (
  <Composition
    id="RingText"
    component={Ring}
    durationInFrames={180}
    fps={30}
    width={1280}
    height={720}
  />
);

Every character sits on its own panel, placed around the ring with rotateY(θ) translateZ(radius), and the panel background forms the band. The text and separator repeat as many times as fit the circumference, and the remainder is spread as letter spacing so the band closes without a gap. A phrase longer than one lap grows the radius instead.

The ring is viewed from above: the near side reads left to right, and the far side shows the letters mirrored and dimmed. It turns once every period frames, and its tilt sways by six degrees. It arrives scaled down, spinning fast, and settles into its cruise speed by frame 30.

The ring is centered in its parent; place it with a wrapper. Sizes scale with height / 720.

Props
PropTypeDefaultDescription
text
string"Type in motion"The phrase around the ring
separator
string"•"Glyph between repeats. An empty string leaves a space
radius
number210Ring radius in reference px. Long text grows it
fontSize
number40Font size in reference px. The band is 1.5em tall
fontWeight
number800Font weight
fontFamily
stringInterFont family
color
string"#fafafa"Letter color
band
string"#0a0a0a"Band color
tilt
number38Degrees the ring leans toward the camera
roll
number-16Degrees the ring is rotated in the frame
period
number240Frames for one full turn
speed
number1Timeline speed multiplier
className
string—Optional className passed to the wrapper