Animated Stacked Card Component for React – Hero Card Stack

Description:

Hero Card Stack is a React animation component that creates a scrollable deck of cards with spring-physics transitions, blur effects, and built-in keyboard navigation. Inspired by Apple’s Time Machine.

Features

  • Scroll-driven card navigation that maps vertical scroll distance to an active card index with a configurable 50px snap interval.
  • Spring-physics animations via Framer Motion applied individually to each card’s scale, vertical position, blur, and opacity.
  • Arrow key support (left and right) for keyboard-first navigation through the card stack.
  • Automatic keyboard shortcut suppression when the user focuses on an input, textarea, or select element.
  • Cards fan out with an 8% scale reduction and a -30px vertical offset per stack position.
  • Images load from src/assets/ as static imports. The component duplicates the sequence internally for an extended scroll range.
  • Tailwind CSS v4 styling with Vite-powered hot module replacement for fast iteration.

Preview

hero-card-stack

Use Cases

  • A product landing page that presents multiple features or pricing tiers as stacked cards, where users scroll through each one in sequence.
  • A developer portfolio where project cards reveal one at a time as the visitor scrolls down, each displaying its own image and context.
  • A multi-step onboarding flow where each instruction or action appears as the next card in the deck.
  • A media gallery or photo viewer that presents images as a tactile card deck with spring-based transitions between items.

How To Use It

1. Clone and install.

git clone https://github.com/mirayatech/hero-card-stack.git
cd hero-card-stack
npm install

2. Start the development server. Vite starts the dev server at http://localhost:5173 by default. Open it, scroll the page, or press the arrow keys to see the card stack in action.

npm run dev

3: Add your images. Place .jpg images named 1.jpg through 7.jpg in src/assets/. The component imports these files statically and duplicates the sequence to extend the scroll depth.

src/
  assets/
    1.jpg
    2.jpg
    3.jpg
    4.jpg
    5.jpg
    6.jpg
    7.jpg

4. The TimeMachine component manages the scroll listener and card index internally. Drop it into any layout:

// src/App.tsx
// Import the main card stack component
import { TimeMachine } from './components/time-machine';
function App() {
  return (
    // The scroll container must span at least 100vh + 200px
    // to support the full snap sequence
    <main className="relative min-h-screen">
      {/* TimeMachine attaches its own scroll listener on mount */}
      <TimeMachine />
    </main>
  );
}
export default App;

5. All animation parameters live in src/lib/constants.ts. Edit these values to tune the stack behavior:

// src/lib/constants.ts
export const CARD_COUNT = 5;
export const LENGTH = CARD_COUNT - 1;
export const SNAP_DISTANCE = 50;
export const FRAME_OFFSET = -30;
export const FRAMES_VISIBLE_LENGTH = 3;

6. The useShortcuts hook in src/hooks/use-shortcuts.ts wires ArrowRight and ArrowLeft to navigation callbacks. It suppresses automatically when a form field holds focus:

// Register arrow key listeners with navigation callbacks
import { useShortcuts } from '../hooks/use-shortcuts';
useShortcuts({
  // Arrow Right advances to the next card in the stack
  onNext: () => setActiveIndex((i) => i + 1),
  // Arrow Left steps back to the previous card
  onPrev: () => setActiveIndex((i) => i - 1),
});

Add Comment