Skip to content
shadcn.io

shadcn.io is not affiliated with official shadcn/ui

Buttons

Pro

Flip Button for React

A button that rolls over in 3D on hover to show a second face, such as a price that turns into a call to action. For React with Base UI, when one button has two things to say.

Framework
UI library

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.

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 { 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.

Preview width

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.

Preview width

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.

Preview width

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.

What happens on a touch screen?

There's no hover, so the back face only shows while the button has keyboard focus or when flipped is set. Put what people need on the front.

What happens with reduced motion?

The faces stay flat and cross-fade in place. The button still shows its back face on hover and focus.

API Reference

FlipButton

data-slot="flip-button-front"

PropType
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.

AttributeType
data-flipped?string

Present when flipped is set.

CSS variableType
--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).

All 35 buttons