Skip to content
Sign in
EffectsGlyph morphMenu

Glyph morphPro

An icon that morphs into the next one by path interpolation, for state swaps: play to pause, mic to stop, copy to check. Any two icons from the set.

ProEight state swaps from the icon set

Installation

$ pnpm dlx shadcn@latest add @chatcn-pro/glyph-morph

Usage

tsx
import { GlyphMorph } from "@/components/ui/chatcn/pro/glyph-morph"
import { PauseIcon, PlayIcon } from "@/lib/chatcn-icons"

<button aria-label={playing ? "Pause" : "Play"} onClick={toggle}>
  <GlyphMorph icon={playing ? PauseIcon : PlayIcon} rotate={90} />
</button>

Pass the icon to show; change it and the strokes travel into the next one. At rest it renders the real icon, so it is pixel identical to a static icon. Every stroke of both icons is sampled into evenly spaced points and paired with its closest partner; a stroke with no partner grows out of the nearest point of the other icon, and loops rotate to the start that travels least. A change mid morph starts from where the strokes are.

Examples

In controls

ProPlay to pause and mic to stop in place

Sizes

ProA send button's life at 16, 24 and 48 px

Props

PropTypeNotes
iconIconAny icon from @/lib/chatcn-icons
sizenumberDefault 24
strokeWidthnumberDefault 1.5, like every icon
durationnumberMorph length in ms. Default 220
rotatenumberDegrees turned while morphing, ending upright. Default 0
labelstringAccessible name. Without it the glyph is decorative
onMorphEnd() => voidCalled when a morph settles

Keyboard

The glyph is not focusable. Put it in the button that changes state; the button owns the keyboard and the label.

Accessibility

  • Decorative by default (aria-hidden). The button around it carries the changing label, for example Play and Pause, and aria-pressed when it is a toggle.
  • With label it becomes role=img with that name.

Motion

  • 220 ms on the kit curve, cubic-bezier(0.23, 1, 0.32, 1), driven per frame without React renders.
  • Under reduced motion the swap is a 120 ms fade with no movement.