# Card Swap

> A 3D stack of cards that sends the front card to the back on a timer, or when you fling it.

A 3D stack of cards. On a timer the front card drops away and lands at the back, with a spring that overshoots. Drag or fling the front card in any direction to send it back yourself, click a card behind to bring it forward, or use the arrow keys. The stack shifts in depth with the cursor and fans out while hovered.

<demo-card-swap>



</demo-card-swap>

## Installation

```bash
npx shadcn-vue@latest add "https://nxui.geoql.in/r/card-swap.json"
```

## Usage

```vue
<script setup lang="ts">
  import { CardSwap } from '~/components/ui/card-swap';
  import type { CardSwapItem } from '~/components/ui/card-swap';

  const items: CardSwapItem[] = [
    { title: 'Golden hour', image: '/sunset.jpg', icon: 'lucide:sunset' },
    { title: 'Black beach', image: '/beach.jpg', icon: 'lucide:tree-palm' },
    { title: 'Steel arches', image: '/bridge.jpg', icon: 'lucide:bridge' },
  ];

  function onChange(index: number) {
    console.log('front card', index);
  }
</script>

<template>
  <div class="relative h-150 w-full">
    <CardSwap :items="items" theme="dark" @change="onChange" />
  </div>
</template>
```

Pass your own cards through the default slot. Wrap each one in `CardSwapCard` to get the matching tile style:

```vue
<CardSwap :width="400" :height="300">
  <CardSwapCard>Your content</CardSwapCard>
  <CardSwapCard>More content</CardSwapCard>
  <CardSwapCard>Even more</CardSwapCard>
</CardSwap>
```

The stack scales down to fit its container, so give the parent a real height.

## Props

<table>
<thead>
  <tr>
    <th>
      Prop
    </th>
    
    <th>
      Type
    </th>
    
    <th>
      Default
    </th>
    
    <th>
      Description
    </th>
  </tr>
</thead>

<tbody>
  <tr>
    <td>
      <code>
        items
      </code>
    </td>
    
    <td>
      <code>
        CardSwapItem[]
      </code>
    </td>
    
    <td>
      Sample cards
    </td>
    
    <td>
      Cards to show when no slot content is passed. <code>
        title
      </code>
      
      , <code>
        image
      </code>
      
      , <code>
        icon
      </code>
      
       (Iconify name), <code>
        alt
      </code>
      
      .
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        width
      </code>
    </td>
    
    <td>
      <code>
        number
      </code>
    </td>
    
    <td>
      <code>
        460
      </code>
    </td>
    
    <td>
      Width of each card, in px.
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        height
      </code>
    </td>
    
    <td>
      <code>
        number
      </code>
    </td>
    
    <td>
      <code>
        340
      </code>
    </td>
    
    <td>
      Height of each card, in px.
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        card-distance
      </code>
    </td>
    
    <td>
      <code>
        number
      </code>
    </td>
    
    <td>
      <code>
        60
      </code>
    </td>
    
    <td>
      Horizontal step between stacked cards, in px.
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        vertical-distance
      </code>
    </td>
    
    <td>
      <code>
        number
      </code>
    </td>
    
    <td>
      <code>
        70
      </code>
    </td>
    
    <td>
      Vertical step between stacked cards, in px.
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        depth
      </code>
    </td>
    
    <td>
      <code>
        number
      </code>
    </td>
    
    <td>
      <code>
        90
      </code>
    </td>
    
    <td>
      How far back each card sits, in px. More depth makes cards smaller.
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        skew-amount
      </code>
    </td>
    
    <td>
      <code>
        number
      </code>
    </td>
    
    <td>
      <code>
        6
      </code>
    </td>
    
    <td>
      Slant of the cards, in degrees.
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        visible-cards
      </code>
    </td>
    
    <td>
      <code>
        number
      </code>
    </td>
    
    <td>
      <code>
        4
      </code>
    </td>
    
    <td>
      How many cards show. Extra cards wait hidden at the back.
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        delay
      </code>
    </td>
    
    <td>
      <code>
        number
      </code>
    </td>
    
    <td>
      <code>
        4000
      </code>
    </td>
    
    <td>
      Time between swaps, in ms.
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        autoplay
      </code>
    </td>
    
    <td>
      <code>
        boolean
      </code>
    </td>
    
    <td>
      <code>
        true
      </code>
    </td>
    
    <td>
      Sends the front card to the back on a timer.
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        pause-on-hover
      </code>
    </td>
    
    <td>
      <code>
        boolean
      </code>
    </td>
    
    <td>
      <code>
        true
      </code>
    </td>
    
    <td>
      Pauses the timer while the cursor is over a card.
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        draggable
      </code>
    </td>
    
    <td>
      <code>
        boolean
      </code>
    </td>
    
    <td>
      <code>
        true
      </code>
    </td>
    
    <td>
      Lets people drag or fling the front card to the back.
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        speed
      </code>
    </td>
    
    <td>
      <code>
        number
      </code>
    </td>
    
    <td>
      <code>
        1
      </code>
    </td>
    
    <td>
      Speed of the swap animation.
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        bounce
      </code>
    </td>
    
    <td>
      <code>
        number
      </code>
    </td>
    
    <td>
      <code>
        0.35
      </code>
    </td>
    
    <td>
      How much the cards overshoot as they settle, from 0 to 1.
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        parallax
      </code>
    </td>
    
    <td>
      <code>
        number
      </code>
    </td>
    
    <td>
      <code>
        0.5
      </code>
    </td>
    
    <td>
      How much the stack shifts in depth with the cursor, from 0 to 1.
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        hover-spread
      </code>
    </td>
    
    <td>
      <code>
        number
      </code>
    </td>
    
    <td>
      <code>
        0.12
      </code>
    </td>
    
    <td>
      How much the stack fans out while hovered.
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        dim
      </code>
    </td>
    
    <td>
      <code>
        number
      </code>
    </td>
    
    <td>
      <code>
        0.5
      </code>
    </td>
    
    <td>
      How much the cards behind fade back, from 0 to 1.
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        card-radius
      </code>
    </td>
    
    <td>
      <code>
        number
      </code>
    </td>
    
    <td>
      <code>
        18
      </code>
    </td>
    
    <td>
      Corner radius of the cards, in px.
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        intro
      </code>
    </td>
    
    <td>
      <code>
        boolean
      </code>
    </td>
    
    <td>
      <code>
        true
      </code>
    </td>
    
    <td>
      Fans the cards out from the front one on mount.
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        theme
      </code>
    </td>
    
    <td>
      <code>
        'dark' | 'light'
      </code>
    </td>
    
    <td>
      <code>
        'dark'
      </code>
    </td>
    
    <td>
      Color theme of the cards.
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        class
      </code>
    </td>
    
    <td>
      <code>
        string
      </code>
    </td>
    
    <td>
      <code>
        ''
      </code>
    </td>
    
    <td>
      Extra classes for the container.
    </td>
  </tr>
</tbody>
</table>

## Events

<table>
<thead>
  <tr>
    <th>
      Event
    </th>
    
    <th>
      Payload
    </th>
    
    <th>
      Description
    </th>
  </tr>
</thead>

<tbody>
  <tr>
    <td>
      <code>
        change
      </code>
    </td>
    
    <td>
      <code>
        index: number
      </code>
    </td>
    
    <td>
      Index of the new front card after each swap.
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        card-click
      </code>
    </td>
    
    <td>
      <code>
        index: number
      </code>
    </td>
    
    <td>
      A card was clicked. Clicking a card behind also brings it forward.
    </td>
  </tr>
</tbody>
</table>

## Slots / Exposed

<table>
<thead>
  <tr>
    <th>
      API
    </th>
    
    <th>
      Description
    </th>
  </tr>
</thead>

<tbody>
  <tr>
    <td>
      <code>
        default
      </code>
    </td>
    
    <td>
      Your own cards. Wrap each in <code>
        CardSwapCard
      </code>
      
       for the tile style.
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        next()
      </code>
    </td>
    
    <td>
      Template ref method. Sends the front card to the back.
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        prev()
      </code>
    </td>
    
    <td>
      Template ref method. Brings the back card to the front.
    </td>
  </tr>
</tbody>
</table>

## Accessibility

- The stack is a focusable `region` with `aria-roledescription="carousel"`. Arrow Right / Down swap forward, Arrow Left / Up swap back. The front card shows a focus ring when the stack has keyboard focus.
- The timer pauses while the stack is offscreen, while the tab is hidden, and (by default) while the cursor is over a card.
- With `prefers-reduced-motion: reduce`, the springs are critically damped (no overshoot), the intro, parallax and hover fan-out are off.
- Ported from [React Bits](https://reactbits.dev/components/card-swap) by David Haz.
