Flip Card
loomui/flip-cardFreeComponent
A card with two faces that turns in 3D when it is clicked, controlled or on its own.
Live preview
live · rendered by the registry
Rendered by loomui on their own page — this is the component running, not a screenshot of it.Install it
npx shadcn@latest add https://loomui.design/r/flip-card.jsonSource
1"use client"23import * as React from "react"45import { cn } from "@/lib/utils"67export interface FlipCardProps extends Omit<8 React.ComponentProps<"button">,9 "content"10> {11 /** Face shown at rest. It sets the card's size; the back is laid over it. */12 front: React.ReactNode13 /** Face shown once the card is turned. */14 back: React.ReactNode15 /** Turn the card yourself. Leave it out to let the card own its state. */16 flipped?: boolean17 /** Starting face when the card owns its state. */18 defaultFlipped?: boolean19 /** Called with the face the card is turning to. */20 onFlippedChange?: (flipped: boolean) => void21 /** Turn around the vertical axis (`y`) or the horizontal one (`x`). */22 axis?: "x" | "y"23 /** Length of the turn in milliseconds. */24 duration?: number25 /** How much perspective the turn is drawn with, in pixels. Lower is deeper. */26 depth?: number27}2829const FACE = "absolute inset-0 [backface-visibility:hidden]"3031export function FlipCard({32 front,33 back,34 flipped,35 defaultFlipped = false,36 onFlippedChange,37 axis = "y",38 duration = 480,39 depth = 900,40 className,41 disabled,42 onClick,43 style,44 ...props45}: FlipCardProps) {46 const [ownFlipped, setOwnFlipped] = React.useState(defaultFlipped)47 const isControlled = flipped !== undefined48 const isFlipped = isControlled ? flipped : ownFlipped4950 const handleClick = (event: React.MouseEvent<HTMLButtonElement>) => {51 onClick?.(event)5253 if (event.defaultPrevented || disabled) {54 return55 }5657 const next = !isFlipped58 if (!isControlled) {59 setOwnFlipped(next)60 }61 onFlippedChange?.(next)62 }6364 const turn = axis === "x" ? "rotateX" : "rotateY"6566 return (67 // A real button, so the card is reachable by keyboard and announces its68 // state. `aria-pressed` is the honest mapping: this is a toggle, not a69 // link to somewhere else.70 <button71 type="button"72 data-slot="flip-card"73 data-flipped={isFlipped ? "" : undefined}74 aria-pressed={isFlipped}75 disabled={disabled}76 onClick={handleClick}77 className={cn(78 "group relative block text-left",79 !disabled && "cursor-pointer",80 className81 )}82 style={{ perspective: `${depth}px`, ...style }}83 {...props}84 >85 <span86 className="relative block h-full w-full transition-transform ease-[var(--ease-back-out)] [transform-style:preserve-3d] motion-reduce:transition-none"87 style={{88// … truncated
What it pulls in
Other registry items
Files it writes
More from loomui
All 91 items| Component | Registry | Kind | Access | Installs | Command |
|---|---|---|---|---|---|
| Aurora Backdropaurora-backdrop | loomui | Components | Free | no deps | |
| Bento Gridbento-grid | loomui | Components | Free | no deps | |
| Card Stackcard-stack | loomui | Components | Free | no deps | |
| Compare Slidercompare-slider | loomui | Components | Free | no deps | |
| Confetti Buttonconfetti-button | loomui | Components | Free | no deps | |
| Count Upcount-up | loomui | Components | Free | no deps | |
| Credit Cardcredit-card | loomui | Components | Free | no deps | |
| Drawerdrawer | loomui | Components | Free | 1 dep |
