Gooey Morph

Bars fly in Tetris-style, land as a row, and melt into a word through a gooey blur-and-threshold morph

Installation

$ pnpm dlx shadcn@latest add @remocn/gooey-morph

Usage

// src/Root.tsx
import { Composition } from "remotion";
import { GooeyMorph } from "@/components/remocn/gooey-morph";
 
const GooeyMorphScene = () => (
  <GooeyMorph word="HELLO" fontFamily="'Bodoni Moda', Georgia, serif" />
);
 
export const RemotionRoot = () => (
  <Composition
    id="GooeyMorph"
    component={GooeyMorphScene}
    durationInFrames={120}
    fps={30}
    width={1920}
    height={1080}
  />
);

The melt works by blurring the alpha channel and pushing it through a near-vertical threshold: where two shapes sit close, their blurred edges add up, cross the threshold, and paint a solid neck between them. Everything that should fuse lives inside the component's single filtered group — nearby elements outside it never join the goo.

Props

PropTypeDefaultDescription
word
string"HELLO"The word the bars melt into
fill
string"#ffffff"Fill color of the bars and the word
fontFamily
string"sans-serif"Font family of the word — heavy display faces melt best
fontSize
number237Font size in comp pixels
tracking
number0Letter spacing of the word
wordCenterX / wordBaselineY
number961.4 / 601.3Horizontal center and baseline of the word in comp pixels
width / height
number1920 / 1080Coordinate space of the composition
barWidth / barHeight
number213 / 181Size of each bar in comp pixels
barStartPositions
[number, number][]4 scattered pointsWhere each bar starts, as `[x, y]` centers
barRestPositions
[number, number][]4 points in a rowWhere each bar lands before the melt
barEntryFrames
number[][8, 0, 4, 13]Per-bar entry frames — deliberately non-monotonic so the build reads as Tetris, not a wave
barTravelFrames
number30Length of one bar's L-shaped move: horizontal into the column, then vertical into the row
morphStartFrame / morphPeakFrame / morphEndFrame
number50 / 63 / 76The melt window. Blur and displacement are zero outside it
blurRadius
number6Peak goo blur radius
blurIterations
number6Box blur passes folded into the equivalent Gaussian sigma
alphaInputBlack / alphaInputWhite
number0.4588 / 0.5098Alpha threshold range — the narrower, the harder the goo edge
displaceAmount
number20Peak turbulent displacement of the goo edge, in pixels
displaceSize
number19Feature size of the displacement noise
displaceComplexity
number1Noise octaves
displaceEvolutionPerSecond
number50How fast the noise field pans, per second
className
stringOptional className passed to the wrapper

Inspired by 5 Clean Text Animations by Mapal.