Skip to content
shadcn.io

shadcn.io is not affiliated with official shadcn/ui

Buttons

Pro

Shake Button for React

A button that shakes its head, side to side, when an action didn't go through. For React with Base UI, when a failed submit needs a signal right where the click was.

Framework
UI library

When you trigger it, the button swings left and right a few times, smaller each time, and settles in half a second. It's the same signal a phone gives for a wrong passcode.

Use it for a failed submit, a wrong password, or a step that can't go ahead yet, together with a message that says what went wrong. Don't use it as the only error signal: the shake is easy to miss and says nothing about the cause. For a press that should be confirmed rather than refused, use the Confetti Button. It wraps the Button, so variant and size work as usual. The shake is CSS keyframes, which the install adds to your stylesheet; each trigger swaps the button between two names of them, which restarts the shake. When the system asks for reduced motion, the button doesn't move: it flashes an outline in the destructive color instead.

Preview width

Installation

Part of Pro
Pro unlocks the code and one-line install of every Pro button and text effect, plus the MCP for your AI editor.
Have Pro already? Sign in to open it.Opens here as soon as you're Pro.

Usage

import { ShakeButton } from "@/components/ui/shake-button";
<ShakeButton shakeKey={failedAttempts}>Sign in</ShakeButton>

Demos

Intensity

intensity sets how far the button swings each way: subtle is 2px, medium 4px and strong 7px, with medium by default. Press each one to compare. A subtle shake suits a small, inline button; a strong one suits a blocked, serious action.

Preview width

Controlled

shake shakes the button once each time it turns true, and onShakeEnd is called when the shake is over, so you can set it back to false. Here a destructive button shakes when the action is refused, and a message under it says why. For repeated failures, shakeKey is simpler: it needs no reset.

Preview width

Accessibility

The shake is visual only, and it isn't announced. Put the reason in text, near the button, in a live region such as aria-live="polite", so screen readers say it too, as the demos do. Enter and Space press the button as usual, and a shake started from the keyboard looks the same as one started by a pointer.

Enter
Activate the button.
Space
Activate the button.

FAQ

How do I trigger the shake?

Two ways. Change shakeKey, such as a count of failed attempts, and it shakes once per change, with nothing to reset. Or set shake to true, and set it back to false in onShakeEnd.

Can it shake again while it's still shaking?

Yes. A new shakeKey, or shake turning true again, restarts the shake from the beginning, so a quick second failure is never lost.

How do I make it shake harder or softer?

Set intensity to subtle (2px), medium (4px, the default) or strong (7px). The Intensity demo shows all three.

How long does a shake last?

Half a second, long enough to notice and short enough not to get in the way. onShakeEnd is called when the animation ends, not after a timer, so it's always in step with what's on screen.

Should the button also turn red?

Only when the action itself is destructive, with variant="destructive". For most errors the shake and a short message are enough.

What happens with reduced motion?

The button doesn't move. It flashes an outline in the destructive color for about half a second, and onShakeEnd is still called when the flash ends.

API Reference

ShakeButton

PropType
focusableWhenDisabled?boolean

Whether the button should be focusable when disabled.

Default
false
intensity?"subtle" | "medium" | "strong"

How far the button swings each way: subtle is 2px, medium 4px, strong 7px.

Type
"subtle" | "medium" | "strong"
Default
"medium"
nativeButton?boolean

Whether the component renders a native <button> element when replacing it via the render prop. Set to false if the rendered element is not a button (for example, <div>).

Default
true
onShakeEnd?() → void

Called each time a shake has finished.

Returns
void
shake?boolean

Shake once each time this turns true. Set it back to false in onShakeEnd, or use shakeKey, which needs no reset.

Default
false
shakeKey?number | string

Shake once each time this value changes, such as a count of failed attempts. The first value doesn't shake.

Type
number | string
render?ReactElement | ((props: object, state: object) => ReactElement)

Replace the host element or compose it with another component.

Type
ReactElement | ((props: object, state: object) => ReactElement)
className?string

Merged with the part's classes.

AttributeType
data-shake?string

Mirrors wave.

CSS variableType
--shake-button-distancestring

How far the button swings each way (4px).

All 35 buttons