Motion & GSAP UI for React. Built for shadcn/ui.
Sora UI

Text Morph

Per-character layout morphing for labels, counters, and live text swaps.

Made by Axyl
Loading...

Examples

Text Morph Input

Loading...

Installation

Usage

import { TextMorph } from '@/components/sora-ui/texts/text-morph';

export default function StatusLabel({ value }: { value: string }) {
  return (
    <TextMorph
      as="span"
      className="font-mono text-sm uppercase tracking-widest"
      live="polite"
    >
      {value}
    </TextMorph>
  );
}

Cycle copy on click:

'use client';

import { useState } from 'react';
import { TextMorph } from '@/components/sora-ui/texts/text-morph';

export function TextMorphButton() {
  const [text, setText] = useState('Continue');

  return (
    <button
      className="flex h-10 w-[120px] shrink-0 items-center justify-center rounded-full bg-foreground px-4 text-base font-medium text-background shadow-xs transition-colors hover:bg-foreground/85"
      onClick={() =>
        setText((current) => (current === 'Continue' ? 'Confirm' : 'Continue'))
      }
      type="button"
    >
      <TextMorph as="span">{text}</TextMorph>
    </button>
  );
}

Live morph while typing:

'use client';

import { useState } from 'react';
import { TextMorph } from '@/components/sora-ui/texts/text-morph';

export function TextMorphInput() {
  const [text, setText] = useState('Craft');

  return (
    <div className="flex w-full max-w-sm flex-col items-center space-y-12">
      <TextMorph className="text-5xl font-medium" live="polite">
        {text}
      </TextMorph>
      <input
        className="h-9 w-full rounded-lg border border-input bg-transparent p-2 text-base shadow-xs outline-none placeholder:text-muted-foreground focus-visible:border-ring focus-visible:ring-3 focus-visible:ring-ring/50"
        onChange={(event) => setText(event.target.value)}
        placeholder="Type your text here"
        type="text"
        value={text}
      />
    </div>
  );
}

Props

PropTypeDefault
children?
string
-
as?
ElementType
"p"
variant?
"blur" | "slide"
-
staggerDelay?
number
0
skipUnchanged?
boolean
false
charClassName?
string
-
live?
"off" | "polite" | "assertive"
"off"
variants?
Variants
-
transition?
Transition
-
className?
string
-

Credits

Inspired by motion-primitives.

Built by Axyl. A motion-first component registry for React.

Last updated: 6/27/2026