# Chromatic Wave
URL: https://remocn.dev/docs/typography/chromatic-wave

A soft wave travels down through the type; where it crosses, the letters ripple and split into RGB fringes, then settle back to white

- Install: `npx shadcn@latest add @remocn/chromatic-wave`
- Vibe: tech
- Natural length: 150f @ 30fps

## Installation

```bash
npx shadcn@latest add @remocn/chromatic-wave
```

## Usage

```tsx
// src/Root.tsx
import { Composition } from "remotion";
import { ChromaticWave } from "@/components/remocn/chromatic-wave";

const ChromaticWaveScene = () => (
  <ChromaticWave headline="MUSIC" kicker="APPLES" />
);

export const RemotionRoot = () => (
  <Composition
    id="ChromaticWave"
    component={ChromaticWaveScene}
    durationInFrames={100}
    fps={30}
    width={1920}
    height={1080}
  />
);
```

Three copies of the type are displaced by the same traveling wave at three
different depths — one per color channel — and summed back together with
`screen` blending. Where the copies still coincide the sum is white; where the
depths pull them apart, red, green and blue fringes appear. The component
paints its own `background` (default black) because the reassembly is only
exact over black.

## Props

| Prop | Type | Default | Description |
|---|---|---|---|
| `headline` | `string` | `"MUSIC"` | The large center line |
| `kicker` | `string` | `"APPLES"` | The small tracked line, repeated above and below the headline |
| `headlineFontFamily / kickerFontFamily` | `string` | `Helvetica stack` | Fonts of the two lines |
| `headlineFontSize / kickerFontSize` | `number` | `174 / 52` | Font sizes in comp pixels |
| `kickerTracking` | `number` | `32` | Letter spacing of the kicker lines |
| `headlineBaselineY / kickerBaselines` | `number / [number, number]` | `601 / [444, 670]` | Baselines of the three lines in comp pixels |
| `textCenterX` | `number` | `960` | Horizontal center of the type |
| `fill` | `string` | `"#ffffff"` | Color of the type before the split |
| `background` | `string` | `"#000000"` | Painted stage background. Keep it dark — the channel reassembly is only exact over black |
| `width / height` | `number` | `1920 / 1080` | Coordinate space of the composition |
| `bandHeight / bandCopies / bandPitch` | `number` | `147.1 / 7 / 750` | Geometry of the traveling distortion bands |
| `mapStartY / mapEndY / mapTravelFrames` | `number` | `31 / 1560 / 150` | The bands' travel. Deliberately linear — an ease reads as the ripple hesitating inside the word |
| `waveHeight / waveWidth / waveSpeed` | `number` | `28 / 272 / 1` | The sine ripple on each band's edges |
| `turbulentAmount / turbulentSize` | `number` | `130 / 163` | Turbulent displacement breaking the wave's regular rhythm |
| `evolutionPerSecond` | `number` | `50` | How fast the turbulence field pans |
| `mapBlurRadius / mapBlurIterations` | `number` | `13 / 6` | Blur on the displacement map — without it the map's edges tear the output |
| `glassDisplacement / maxDisplacementPx` | `number` | `100 / 39` | Displacement strength, and the pixel span it maps to |
| `glassPasses` | `number` | `3` | How many depth passes — also how many channels split |
| `channelOrder` | `("red" \| "green" \| "blue")[]` | `["blue", "green", "red"]` | Which channel rides which depth, shallowest first |
| `className` | `string` | — | Optional className passed to the wrapper |

Inspired by [5 Clean Text Animations](https://www.youtube.com/watch?v=Nmi7cE2wT54) by Mapal.

## Use when
- A held title — an album cover, a poster hold, a loop — needs slow, ambient distortion instead of a one-shot entrance.
- The aesthetic is music-video or vaporwave: rippling glass with red, green and blue fringes at the distortion edges.
- The type can sit on a dark background — the channel split sums back to white via screen blending, which is only exact over black.

## Don't use when
- You need a quick glitch accent rather than a five-second traveling wave — use `rgb-glitch-text`.
- The background is light — the screen blend that reassembles the channels breaks over anything but dark fills.
- The copy changes or enters mid-scene — the type is static; this is a treatment, not a reveal; use `soft-blur-in` first.