Skip to content
WANCRAFT

F.21Forms & Inputs

Animated Toggle

A tactile switch whose thumb springs across the track and squashes when pressed.

ReactMotionSVGTailwindbasic

Overview

Animated Toggle is a real <button role="switch"> with aria-checked, a properly associated <label> and optional description. The thumb travels on a configurable spring and stretches toward its destination while pressed — by pointer or keyboard — before snapping across. It works controlled or uncontrolled, can submit with native forms through a hidden input, and switches instantly when reduced motion is preferred.

01Installation

Method 01 · Registry

CLI verified

Uses the shadcn CLI in a project initialised with shadcn init. Installs the file to components/ui/animated-toggle.tsx and adds its dependencies.

npx shadcn@latest add https://wancraft.my/r/animated-toggle.json

Method 02 · Copy and paste

  1. 1. Install the dependencies below.
  2. 2. Copy the source from the Code tab into components/ui/animated-toggle.tsx.
  3. 3. Import it and adjust props.
npm install motion
Dependencies
motion
Peer
react ≥ 18, tailwindcss ≥ 4
Added
1 Oct 2026
Updated
—

02Usage

The default configuration. Change properties above to generate a tailored example in the Usage tab.

example.tsx
import { AnimatedToggle } from "@/components/ui/animated-toggle";

export function AnimatedToggleExample() {
  return (
    <AnimatedToggle
      label="Email notifications"
      defaultChecked
      onCheckedChange={(checked) => console.log(checked)}
    />
  );
}

03Props

PropTypeDefaultDescription
checkedboolean—Controlled state. Pair with onCheckedChange.
defaultCheckedbooleanfalseInitial state when uncontrolled.
onCheckedChange(checked: boolean) => void—Called with the next state on every toggle.
labelReactNode—Visible label, linked via <label htmlFor>. Without it, pass aria-label.
descriptionReactNode—Helper text linked with aria-describedby.
labelPosition"start" | "end""end"Side of the switch the label sits on.
size"sm" | "md" | "lg""md"Switch dimensions.
accentstring"#FF7448"Track colour when on; also the focus ring.
iconsbooleanfalseDraws a check / cross glyph in the thumb.
spring{ stiffness: number; damping: number; mass: number }{ stiffness: 520, damping: 30, mass: 0.8 }Spring for travel and squash.
namestring—Submits "on" with native forms while checked.
...propsButtonHTMLAttributes—Forwarded to the <button> (disabled, aria-*, handlers); ref is forwarded.

04Features

  • 01Controlled and uncontrolled modes
  • 02Spring travel with a press squash toward the destination
  • 03Animated check / cross glyphs drawn with SVG path length
  • 04Hidden input for native form submission
motion · springinput · clickinput · pressinput · keyboardinput · focus

05Accessibility

  • Native <button role="switch"> with aria-checked; Space and Enter toggle it.
  • Visible label uses <label htmlFor>, so clicking the label toggles and names the switch.
  • Description is linked through aria-describedby.
  • Accent-coloured focus-visible ring; disabled state is native.
  • prefers-reduced-motion switches instantly with no squash.