Back to elements
ElementMiscFree

Icon Swap Toggle React component

A toggle button that swaps between two icons with a rotate, 3D flip, pop or slide: ready-made pairs for play/pause, mute, like, save, show/hide, menu/close, light/dark and copy/copied, or any two icons of your own.

When to use the Icon Swap Toggle component

Use Icon Swap Toggle for two-state controls that live as a single icon: play / pause, mute, like, bookmark, show password, menu / close, theme. The swap animation makes the state change obvious without any text.

Always set labels for custom pairs so screen reader users hear what the button will do.

Installation

Add the Icon Swap Toggle component to your project with the shadcn CLI. It lands in components/icon-swap-toggle.tsx as plain React + Tailwind CSS source you own and can edit.

Install
Copied!
npx shadcn@latest add https://reactframe.com/r/icon-swap-toggle.json

Or copy the source by hand and install its dependencies:

Install
Copied!
npm install motion clsx tailwind-merge

Props

<IconSwapToggle /> accepts 12 props, all optional.

  • preset
    "play" | "sound" | "heart" | "bookmark" | "eye" | "menu" | "theme" | "copy"
    Default: "play"
  • iconOff

    Your own pair; overrides the preset.

    React.ReactNode
  • iconOn
    React.ReactNode
  • effect
    "rotate" | "flip" | "scale" | "slide"
    Default: "rotate"
  • on
    boolean
  • defaultOn
    boolean
    Default: false
  • onChange
    (on: boolean) => void
  • labels

    Accessible names for each state, e.g. ["Play", "Pause"].

    [string, string]
  • variant
    "ghost" | "outline" | "solid"
    Default: "outline"
  • size
    number
    Default: 44
  • theme
    "dark" | "light"
    Default: "dark"
  • className
    string

FAQ

Which effect should I use?
Rotate for symbolic swaps (play/pause, menu/close), pop for likes and saves, flip for view switches, slide for media controls. They all respect reduced motion.
Is it accessible?
It's a real button with aria-pressed and a label that changes with the state (Play / Pause, Mute / Unmute...).
Can I control it from outside?
Yes. Pass on and onChange to keep it in sync with your player, form or store.

More Misc components

Ripple Click Effect
Free
Focus Trap
Free
Toggle Price Counter
Free
Animate on Scroll
Free
Animated Underline Link
Free
Speed Dial
Free