PParable
All components

Expandable Card

Interactive

A card that spring-expands in place to reveal a body whose children fade and slide in with a slight stagger, while siblings in a grid stay put. Works controlled or uncontrolled with full button/aria-expanded keyboard semantics, and expands or collapses instantly under prefers-reduced-motion.

Inspired by Cult UI — Expandable Card (free, MIT) — independently built, not affiliated. Attribution policy

A GPU-cheap animated backdrop built from drifting radial bands — transform and opacity only, so it stays buttery at 60fps.

WebGLReduced-motion safe

Installation

npx shadcn@latest add https://parable-three.vercel.app/r/expandable-card.json

Runs the shadcn CLI — the component source is copied intocomponents/parable/expandable-card.tsx. You own it from there.

Usage

The exact code rendering the preview above.

<div className="w-full max-w-sm">
    <ExpandableCard
      title="Aurora Engine"
      subtitle="Real-time gradient renderer"
      defaultExpanded
      media={<Sparkles />}
    >
      <p>A GPU-cheap animated backdrop built from drifting radial bands — transform and opacity only, so it stays buttery at 60fps.</p>
      <div className="flex gap-2">
        <span className="rounded-full bg-white/10 px-2.5 py-1 text-xs text-white/70">WebGL</span>
        <span className="rounded-full bg-white/10 px-2.5 py-1 text-xs text-white/70">Reduced-motion safe</span>
      </div>
    </ExpandableCard>
  </div>

Props

ExpandableCardProps extends Omit<React.HTMLAttributes<HTMLDivElement>, "title">

PropTypeDefaultDescription
title*React.ReactNodePrimary heading shown in the collapsed row.
subtitleReact.ReactNodeOptional secondary line under the title.
mediaReact.ReactNodeDecorative media — a left thumbnail or a full-width top strip.
mediaLayout"thumb" | "strip""thumb"Where `media` renders. `"thumb"` = left of the title; `"strip"` = above it.
accentstring"#8b5cf6"Accent used for the chevron and focus ring. Mirrors the site `--pb-violet` token.
defaultExpandedbooleanfalseUncontrolled initial open state.
expandedbooleanControlled open state. Pair with `onExpandedChange`.
onExpandedChange(expanded: boolean) => voidFires with the next open state when the header is toggled.
children*React.ReactNodeExpanded body content. Direct children fade/slide in with a slight stagger.

npm dependencies

  • motion