SwatchFan
A fanned stack of {@link Swatch} tiles — the unified material-fan primitive
that merges the retired CardFan (fixed 3-image editorial fan) and
StackedSwatchFan (interactive N-tile splay) into one component.
Pass 3 items with interaction="breathe" to reproduce CardFan's Figma
geometry (variant spread/stack, white 3px mount via bordered); pass N
items with interaction="hover-fan" for the interactive splay-on-hover with
pointer tilt. bordered={false} swaps the white mount for the 1px hairline
tile.
Usage
import { SwatchFan, SwatchFanImageProps, SwatchFanInteraction, SwatchFanItem, SwatchFanProps, SwatchFanSize, SwatchFanVariant } from "@desk/ui/components/swatch-fan";Best practices
Feed 3 items for the
breathe/nonecard engine — its Figma geometry, z-order, andvariantmorphing are built around a fixed left/center/right trio; the hover-fan engine is the N-tile path.Needs
ReducedMotionProvider; it already collapses the mount fan-out, hover nudge, and splay under reduced motion (snapping to the settled frame), so don't gate the interaction yourself.borderedis the mount-as-a-prop:true= white 3px card mount,false= 1px hairline — don't hand-roll either border in a wrapper.
Props
| Prop | Type | Default | Description |
|---|---|---|---|
| animateOnMount | boolean | Animate cards fanning out on mount (card engine — | |
| bordered | boolean | true | Mount as a prop. |
| cardBorderWidth | number | 3 | Border width for each material card (card engine). |
| cardRadius | number | 20 | Corner radius for each material card (card engine). |
| cardShadow | string | Shadow applied to each material card (card engine). | |
| className | string | ||
| fanOnHover | boolean | true | Own the fan state via hover/focus (default) or drive it via |
| fanned | boolean | Controlled fan state (hover-fan engine) — e.g. a sibling CTA triggers it. | |
| hovered | boolean | Controlled hover/open state for parent-driven compositions (card engine). | |
| hoverRotate | number | 1 | Extra side-card rotation while hovered (card engine). |
| hoverShift | number | 3 | Extra outward shift for side cards while hovered (card engine). |
| interaction | SwatchFanInteraction | "breathe" | Motion/geometry engine: |
| items | SwatchFanItem[] | Tiles to fan. The card engine ( | |
| label | string | Accessible label applied as the fan's | |
| mountDelay | number | Delay before the mount fan-out starts, in seconds (card engine). | |
| onFannedChange | (fanned: boolean) => void | Fires when the hover-fan opens or closes, with the next fanned state. | |
| overlap | number | Override the horizontal overlap between adjacent cards, px (card engine). | |
| renderImage | (props: SwatchFanImageProps) => ReactNode | Escape hatch for framework-optimized images (e.g. next/image). | |
| rotationDeg | number | 8 | Side-card rotation in degrees (card engine). |
| size | SwatchFanSize | "xl" | Tile size — a SwatchTileSize scale step or pixel number. |
| style | CSSProperties | Inline styles applied to the hover-fan root. | |
| wrapperSize | number | Override the square wrapper size for rotated side cards, px (card engine). | |
| variant | SwatchFanVariant | Layout variant (card engine): |
Also exports
- interface
SwatchFanImageProps - type
SwatchFanInteraction - interface
SwatchFanItem - interface
SwatchFanProps - type
SwatchFanSize - type
SwatchFanVariant
Composition
Builds on