Components / Actions

IconMorph

Icons that morph between states: menu to close, play to pause, copy to check, and more.

Install

npx shadcn@latest add https://irisui.dev/r/icon-morph.json
import { IconMorph } from "@/components/iris/icon-morph/icon-morph";
Registry item icon-morphBrings in foundationRegistry JSON

Preview

IconMorph

Stroke icons that morph between two states — menu to close, play to pause, plus to check, copy to check, sun to moon, chevron turn, bell muted to on, heart to liked.

When to use

  • Inside toggle buttons where the icon itself should show the new state: nav menu, media play, add-to-list, copy, theme, expand/collapse, notifications, like.
  • When you want state changes to read as one continuous shape change rather than an icon swap.
  • The icons carry no label: always put them inside a button (or Button) with an accessible name. For a full copy control with feedback text, use CopyButton; for a light/dark control, use ThemeSwitch.

Usage

import { IconMorph } from "@/components/iris/icon-morph/icon-morph";

<button type="button" aria-label={open ? "Close menu" : "Open menu"} aria-expanded={open} onClick={() => setOpen(!open)}>
  <MenuIcon state={open} size={20} />
</button>

<IconMorph name="heart" state={liked} />
<ChevronIcon state={expanded} pointing="right" turn={90} size={16} />

Props

Prop Type Default Description
name "menu" | "play" | "plus" | "copy" | "theme" | "chevron" | "bell" | "heart" — Which icon (required on IconMorph only). Each also has a named export: MenuIcon, PlayPauseIcon, PlusCheckIcon, CopyCheckIcon, SunMoonIcon, ChevronIcon, BellIcon, HeartIcon.
state boolean false The second state: close, pause, check, check, moon, turned, notifications on, liked.
size number 24 Rendered size in px.
strokeWidth number 1.75 Stroke width in the 24-unit grid.
turn number 180 ChevronIcon only: degrees turned when state is true.
pointing "down" | "right" "down" ChevronIcon only: rest direction.
...props SVGProps<SVGSVGElement> — Other SVG attributes (className, style).

Notes

  • The SVG is aria-hidden; convey state on the button (aria-pressed, aria-expanded, or a changing aria-label).
  • Strokes use currentColor, so the icon follows the button's text colour (play and pause are filled with currentColor); the liked heart fills when state is true and takes --icon-morph-like (default --red).
  • Morphs ride spring tokens; reduced motion switches states instantly.