UI.MD

Card Fan

A stack of cards that fans open on hover. The card you point at comes forward, turns level and rises, and the others darken. For a collection and a peek at what is inside it.

Installation

$
npx shadcn@latest add https://ui.mattdowney.com/r/card-fan.json

Usage

import { CardFan } from "@/components/motion/card-fan"

Examples

Default

Three covers fanned sideways. Point at one and it comes to the front. Each card is a link through render; without it a card is a button. variant="image" gives a photo one edge, a hairline inside it.

One link

The whole tile is the link and the covers are decoration. Mark the link data-card-fan-trigger and pass decorative: hovering anywhere on it, or tabbing to it, fans the covers, and no cover lifts or takes a click.

API Reference

PropTypeDefaultDescription
slotsCardFanSlot[]three sideways cardsOne entry per card, back to front. Each sets its resting pose (cx, cy, rot), how far it moves when the fan opens (dx, dy, drot), its content, its label, and an optional render.
labelstring"Cards"Accessible name for the whole fan.
variant"default" | "image""default"image when every card is a picture. The card drops its outside ring for a 1px hairline inside its edge and keeps its shadow, so a photo never carries two lines.
decorativebooleanfalseThe covers decorate a larger link. They take no pointer, focus or name, and the fan opens when the nearest data-card-fan-trigger ancestor is hovered or has keyboard focus.
renderCardFanSlotReactElement-Renders the card as another element, most often a link: <Link href="/posts/one" />.
labelCardFanSlotstring-Accessible name for one card. Pass a real one, like the title of the page it opens.
slotsCardFanSlot[] = three sideways cardsOne entry per card, back to front. Each sets its resting pose (cx, cy, rot), how far it moves when the fan opens (dx, dy, drot), its content, its label, and an optional render.
labelstring = "Cards"Accessible name for the whole fan.
variant"default" | "image" = "default"image when every card is a picture. The card drops its outside ring for a 1px hairline inside its edge and keeps its shadow, so a photo never carries two lines.
decorativeboolean = falseThe covers decorate a larger link. They take no pointer, focus or name, and the fan opens when the nearest data-card-fan-trigger ancestor is hovered or has keyboard focus.
renderCardFanSlotReactElementRenders the card as another element, most often a link: <Link href="/posts/one" />.
labelCardFanSlotstringAccessible name for one card. Pass a real one, like the title of the page it opens.