shadcn.io is not affiliated with official shadcn/ui
The button has a front and a back face. When the pointer arrives or the button takes keyboard focus, it rolls over like a cube to show the back, and rolls back when it leaves. The back can roll in from the top, the bottom, the left or the right.
Use it where a second line earns the hover: a price that becomes Get started, Talk to sales that becomes Book a call, Follow that stays on Following. Don't hide something people need to read before they click, since touch screens have no hover. It wraps the Button, so variant and size work as usual. Both faces sit in the same spot, so the wider one sizes the button and it never changes width. The roll is a 3D transform on each face in a CSS transition, with no JavaScript and no animation library; with reduced motion the faces cross-fade in place.
Installation
Usage
import { FlipButton } from "@/components/ui/flip-button";<FlipButton back="Get started">$29 / month</FlipButton>Demos
Direction
from sets the edge the back face rolls in from. top, the default, and bottom turn on the horizontal axis; left and right on the vertical one. In a right-to-left layout, left and right swap, so the roll follows the reading direction.
Faces
The front face is the button's children and the back face is back; both take any content, icons included. The front has no color of its own and shows the button's variant. The back is backColor with its text in backForeground, each any CSS color, the primary color and its foreground by default. Here a ghost button turns into a file summary on the secondary color, and a pill turns from primary to the foreground color.
Flipped
flipped keeps the back face showing without hover. Tie it to state for a two-state button: here pressing Follow flips it to Following, and it stays there until it's pressed again.
Accessibility
The face that's showing at rest is the button's name: the front, or the back when flipped is set. The other face is hidden from assistive tech, so it shouldn't carry anything people must know. Keyboard focus flips the button as hover does.
- Enter
- Activate the button.
- Space
- Activate the button.
FAQ
How do I change the flip direction?
Set from to top, bottom, left or right. Top and bottom turn on the horizontal axis, left and right on the vertical one. The Direction demo shows all four.
How do I make the flip faster or slower?
Set duration in milliseconds; 500 is the default. The easing overshoots a little at the end, so the face settles with a small bounce.
How do I style the front and back differently?
The front shows the button's variant, so pick one for it. The back takes backColor and backForeground, any CSS colors, the primary color and its foreground by default. The Faces demo uses both.
Does the button change width when it flips?
No. Both faces are laid out in the same grid cell, so the button takes the wider one's width from the start, and each face is rendered once.
What do screen readers announce?
The front face, or the back one when flipped is set. The face that isn't showing is hidden. If neither face names the action well, pass an aria-label.
API Reference
FlipButton
data-slot="flip-button-front"
backReactNode
The face it flips to on hover or keyboard focus: a call to action, a price, a confirmation.
backColor?string
The back face's color, any CSS color.
- Default
"var(--primary)"
backForeground?string
The back face's text color, any CSS color: pick one that reads on
backColor.
- Default
"var(--primary-foreground)"
children?ReactNode
The face the button shows at rest; it's also what the button is called.
It has no color of its own, so it shows the button's variant.
duration?number
How long the flip takes, in milliseconds.
- Default
500
flipped?boolean
Show the back face without hover, as a selected or done state; it's then what the button is called.
- Default
false
focusableWhenDisabled?boolean
Whether the button should be focusable when disabled.
- Default
false
from?"top" | "bottom" | "left" | "right"
The edge the back face rolls in from. Top and bottom turn on the horizontal axis, left and right on the vertical one (mirrored in a right-to-left layout).
- Type
"top" | "bottom" | "left" | "right"- Default
"top"
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
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.
data-flipped?string
Present when flipped is set.
--flip-button-backstring
The back face's color.
--flip-button-back-foregroundstring
The back face's text color.
--flip-button-durationstring
How long the flip takes (500ms).
Related
- Pro
Depth Button
Motion & feedbackAnother 3D effect, on press
- Pro
Liquid Button
Hover revealsHover reveals a filled state
Arrow Button
Hover revealsHover hint that the action moves on
- Pro
Success Button
Progress & resultsSwap the label once it's done
Magnetic Button
Motion & feedbackPointer-driven motion
- Pro
Glow Border Button
Glow & lightAlways-on effect, no hover needed