Click Trigger

Play animations on click with toggle support for reverse and restart.

.onClick() plays a timeline when an element is clicked. By default it toggles between play and reverse on each click — first click plays forward, next click reverses.

Basic usage

Chain .onClick() after defining your animation. By default the click target is the first animated element.

typescript
import { Motion } from "@motion.page/sdk";

Motion("expand", ".card", {
  to: { height: "240px", paddingBottom: "24px" },
  duration: 0.4,
  ease: "power2.inOut",
}).onClick();

Options

OptionTypeDefaultDescription
targetstring | ElementFirst animated elementCSS selector or element that triggers the click.
secondTargetstring | ElementAdditional trigger element — clicking either target or secondTarget fires the animation.
toggle'reverse' | 'restart' | 'play''reverse'What happens on the second click. 'reverse' plays backward, 'restart' replays from start, 'play' always plays forward.
eachbooleanfalseGive each matched element its own independent timeline instance.
preventDefaultbooleanfalseCall event.preventDefault() on the click event — useful when the trigger is a link or submit button.

Toggle behavior

The toggle option controls what the second (and every even) click does:

  • 'reverse' (default) — alternates play/reverse. Click once: plays forward. Click again: plays backward.
  • 'restart' — always replays from the start on each click. No reverse.
  • 'play' — always plays forward from current position. No reverse.
typescript
// Default — first click plays, second click reverses (accordion, drawer, etc.)
Motion("menu", "#nav-dropdown", {
  from: { height: 0, opacity: 0 },
  duration: 0.35,
  ease: "power2.inOut",
}).onClick({ target: "#menu-btn", toggle: "reverse" });

// restart — replay from scratch on every click
Motion("flash", ".notification", {
  to: { backgroundColor: "#ff4444", scale: 1.04 },
  duration: 0.25,
  ease: "power2.out",
}).onClick({ toggle: "restart" });

Separate click target

Use target to specify a different element as the trigger — the clicked element doesn’t have to be the animated element.

typescript
// Click the button to expand/collapse the panel
Motion("details", ".details-body", {
  from: { height: 0, opacity: 0 },
  duration: 0.4,
  ease: "power2.inOut",
}).onClick({ target: ".details-toggle", toggle: "reverse" });

Add secondTarget when multiple elements should trigger the same animation:

typescript
// Click either the title or the icon to toggle the accordion
Motion("accordion", ".accordion-body", {
  from: { height: 0 },
  to: { height: "auto" },
  duration: 0.35,
  ease: "power2.inOut",
}).onClick({
  target: ".accordion-title",
  secondTarget: ".accordion-icon",
  toggle: "reverse",
});

each — independent per-element instances

Without each, all matched elements share one timeline — clicking any card plays/reverses all of them together. With each: true, every element gets its own independent timeline.

typescript
// Without each — all cards toggle together
Motion("cards", ".card", {
  to: { y: -8 },
  duration: 0.3,
}).onClick({ toggle: "reverse" });

// With each — each card toggles independently
Motion("cards", ".card", {
  to: { y: -8 },
  duration: 0.3,
}).onClick({ each: true, toggle: "reverse" });


Click to rotate

Rotate an icon on each click — useful for chevrons next to dropdowns, arrows on toggles.

typescript
Motion("icon-spin", ".chevron", {
  to: { rotate: 180 },
  duration: 0.3,
  ease: "power2.inOut",
}).onClick({ target: ".dropdown-btn", toggle: "reverse" });

When the click target is an <a> tag or a <button type="submit">, use preventDefault: true to stop the default browser action.

typescript
Motion("lightbox", ".lightbox", {
  from: { opacity: 0, scale: 0.92 },
  duration: 0.35,
  ease: "power2.out",
}).onClick({
  target: "a[data-lightbox]",
  toggle: "reverse",
  preventDefault: true,
});

Theme toggle

Animate a color transition driven by a toggle button:

typescript
Motion("theme", "#banner", {
  to: { backgroundColor: "#1a1a2e", color: "#e0e0ff" },
  duration: 0.5,
  ease: "power2.inOut",
}).onClick({ target: "#dark-toggle", toggle: "reverse" });