entrances

WordRotate

Cycles through a list of phrases in place. Each phrase rises and fades in on SPRING_SMOOTH, holds, then fades out as the next arrives. One focal element per moment.

$ npx ondajs add word-rotate

WordRotate

Cycles through a list of phrases in place. Each phrase rises 12px and fades in on SPRING_SMOOTH, holds at full opacity, then fades out as the next arrives. Phrases are stacked at the same center point so only one is visible at a time — one focal element per moment, the Onda way.

Props

NameTypeDefaultNotes
phrasesstring[]['fast', 'beautiful', 'restrained']Phrases shown in order, one at a time.
delayinteger ≥ 00Frames before the first phrase begins to enter.
holdDurationinteger ≥ 130Frames each phrase holds at full opacity.
transitionDurationinteger ≥ 112Frames to fade a phrase in (and, separately, out).
colorstring"#F2F2F4"Text color — defaults to --onda-text.
fontSizenumber96Pixels. Wins over size if both are passed.
sizeSizeRole?Semantic typography role — 'hero' | 'heading' | 'subheading' | 'body' | 'caption'. Resolves to canvas-aware pixels via the smaller canvas dimension. fontSize wins when both are passed.
fontFamilystring'"Clash Display", sans-serif'The Onda display font. Never default to Inter / Arial / system.
fontWeightnumber600Font weight.
letterSpacingstring"-0.02em"CSS letter-spacing — tight tracking by default.
lineHeightnumber1.1Unitless line height.
align"left" | "center" | "right""left"Text alignment.
placementPlacement?Where on the canvas this sits. Region ("center", "upper-third", …) or { x, y, anchor } in 0..1 canvas fractions. Coordinates may be negative or >1 for off-canvas.

Usage

TSX
import { Composition } from 'remotion';
import { WordRotate, wordRotateSchema } from './components/onda/word-rotate/WordRotate';

export const Root: React.FC = () => (
  <Composition
    id="WordRotate"
    component={WordRotate}
    durationInFrames={150}
    fps={30}
    width={1080}
    height={1920}
    schema={wordRotateSchema}
    defaultProps={{
      phrases: ['fast', 'beautiful', 'restrained'],
      delay: 0,
      holdDuration: 30,
      transitionDuration: 12,
      color: '#F2F2F4',
      fontSize: 96,
      fontFamily: '"Clash Display", sans-serif',
    }}
  />
);

Motion notes

  • Each phrase occupies a slot of transitionDuration + holdDuration frames. Inside the slot it fades in over transitionDuration, holds at 1 for holdDuration, then fades out over the next transitionDuration — overlapping the incoming phrase's fade-in so the swap reads as one motion.
  • Rise is driven by SPRING_SMOOTH from lib/motion.ts (the Onda house default, no overshoot). 12px travel — small on purpose.
  • Opacity uses HOUSE_EASE from lib/easing.ts per CLAUDE.md §3.
  • All phrases after the first are absolutely positioned at the same center point so they stack visually — only one is visible at a time.
  • All interpolate calls clamp at both ends — the component is correct on frame 0 and on any frame past the last phrase's window.