abdxdev/cn

Shake Element

A component that adds a shaking animation to its child elements, triggerable via an imperative ref handle.

Wrong password

Click the button to simulate a failed login shake.

badge
"use client";

import { useRef } from "react";
import { ShakeElement, ShakeHandle } from "@/components/shake-element";

export function ShakeElementDemo() {
  const cardRef = useRef<ShakeHandle>(null);
  const badgeRef = useRef<ShakeHandle>(null);
  const buttonRef = useRef<ShakeHandle>(null);

  return (
    <div className="flex flex-col items-center gap-6 p-8">

      {/* wrong password card */}
      <ShakeElement ref={cardRef} className="w-full max-w-sm rounded-lg border p-5 space-y-3">
        <p className="text-sm font-medium">Wrong password</p>
        <p className="text-xs text-fd-muted-foreground">
          Click the button to simulate a failed login shake.
        </p>
        <button
          onClick={() => cardRef.current?.shake()}
          className="w-full rounded-md border px-3 py-1.5 text-xs font-medium hover:bg-fd-accent transition-colors"
        >
          Shake card
        </button>
      </ShakeElement>

      <div className="flex items-center gap-4">
        {/* badge */}
        <ShakeElement ref={badgeRef}>
          <span className="rounded-full border px-3 py-1 text-xs text-fd-muted-foreground cursor-pointer select-none">
            badge
          </span>
        </ShakeElement>
        <button
          onClick={() => badgeRef.current?.shake()}
          className="text-xs text-fd-muted-foreground underline underline-offset-2 hover:text-fd-foreground transition-colors"
        >
          shake badge
        </button>

        <div className="w-px h-4 bg-fd-border" />

        {/* button shaking itself */}
        <ShakeElement ref={buttonRef}>
          <button
            onClick={() => buttonRef.current?.shake()}
            className="rounded-md border px-3 py-1.5 text-xs font-medium hover:bg-fd-accent transition-colors"
          >
            Shake me
          </button>
        </ShakeElement>
      </div>

    </div>
  );
}

Installation

npx shadcn@latest add https://abdxdev-cn.vercel.app/r/shake-element-ts.json

Usage

Basic

Wrap any element with ShakeElement and call .shake() via a ref:

import { useRef } from "react";
import { ShakeElement, ShakeHandle } from "@/components/shake-element";

export default function Page() {
  const ref = useRef<ShakeHandle>(null);

  return (
    <ShakeElement ref={ref} className="rounded-lg border p-4">
      <button onClick={() => ref.current?.shake()}>
        Shake me
      </button>
    </ShakeElement>
  );
}

External Trigger

The ref can be held by a parent and triggered from anywhere — useful for shaking a form on failed validation:

const formRef = useRef<ShakeHandle>(null);

function onSubmit() {
  const valid = validate();
  if (!valid) formRef.current?.shake();
}

return (
  <>
    <ShakeElement ref={formRef} className="rounded-lg border p-5">
      {/* form fields */}
    </ShakeElement>
    <button onClick={onSubmit}>Submit</button>
  </>
);

That's it. Pass any div props — className, style, event handlers — directly to ShakeElement. The shake is triggered imperatively so it never conflicts with your own state.

API Reference

Prop

Type

On this page