# Flip Card

A card with a front and a back that turns over in 3D. Click it, or press Enter or Space, to flip it. Drag it sideways to turn it by hand; on release it springs to the nearest face and keeps the speed of a flick, so a fast swipe can carry it all the way round. On hover it leans toward the cursor, lifts a little and a soft sheen follows the pointer. The shadow underneath narrows as the card turns edge on.

<demo-flip-card>



</demo-flip-card>

## Installation

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

## Usage

```vue
<script setup lang="ts">
  import { ref } from 'vue';
  import FlipCard from '~/components/ui/flip-card/FlipCard.vue';

  const flipped = ref(false);
</script>

<template>
  <FlipCard v-model:flipped="flipped" aria-label="Wooded Landscape">
    <template #front>
      <img
        src="/landscape.jpg"
        alt="Wooded Landscape"
        class="size-full object-cover"
      />
    </template>
    <template #back>
      <div class="flex h-full flex-col justify-between p-7">
        <span class="text-2xl font-medium">Wooded Landscape</span>
        <span class="text-sm opacity-70">17th century</span>
      </div>
    </template>
  </FlipCard>
</template>
```

Leave out `flipped` and the card keeps its own state; use `default-flipped` to start on the back.

## Props

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

<tbody>
  <tr>
    <td>
      <code>
        flipped
      </code>
    </td>
    
    <td>
      <code>
        boolean
      </code>
    </td>
    
    <td>
      —
    </td>
    
    <td>
      Controlled state, also <code>
        v-model:flipped
      </code>
      
      . <code>
        true
      </code>
      
       shows the back. Omit it to let the card manage itself.
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        default-flipped
      </code>
    </td>
    
    <td>
      <code>
        boolean
      </code>
    </td>
    
    <td>
      <code>
        false
      </code>
    </td>
    
    <td>
      Start on the back face.
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        axis
      </code>
    </td>
    
    <td>
      <code>
        'y' | 'x'
      </code>
    </td>
    
    <td>
      <code>
        'y'
      </code>
    </td>
    
    <td>
      <code>
        y
      </code>
      
       turns the card sideways and drags horizontally. <code>
        x
      </code>
      
       turns it over the top and drags vertically.
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        flip-on-click
      </code>
    </td>
    
    <td>
      <code>
        boolean
      </code>
    </td>
    
    <td>
      <code>
        true
      </code>
    </td>
    
    <td>
      A press without movement flips the card.
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        draggable
      </code>
    </td>
    
    <td>
      <code>
        boolean
      </code>
    </td>
    
    <td>
      <code>
        true
      </code>
    </td>
    
    <td>
      Drag to turn the card by hand. On release it springs to the nearest face, carrying the flick speed.
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        drag-distance
      </code>
    </td>
    
    <td>
      <code>
        number
      </code>
    </td>
    
    <td>
      <code>
        0
      </code>
    </td>
    
    <td>
      Pixels of drag for a half turn. <code>
        0
      </code>
      
       uses the card width, or its height on the <code>
        x
      </code>
      
       axis.
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        tilt
      </code>
    </td>
    
    <td>
      <code>
        boolean
      </code>
    </td>
    
    <td>
      <code>
        true
      </code>
    </td>
    
    <td>
      The card leans toward the cursor on hover.
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        tilt-max
      </code>
    </td>
    
    <td>
      <code>
        number
      </code>
    </td>
    
    <td>
      <code>
        12
      </code>
    </td>
    
    <td>
      Largest tilt angle in degrees.
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        glare
      </code>
    </td>
    
    <td>
      <code>
        boolean
      </code>
    </td>
    
    <td>
      <code>
        true
      </code>
    </td>
    
    <td>
      A soft sheen that follows the cursor.
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        glare-opacity
      </code>
    </td>
    
    <td>
      <code>
        number
      </code>
    </td>
    
    <td>
      <code>
        0.22
      </code>
    </td>
    
    <td>
      Strength of the sheen at its centre.
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        hover-scale
      </code>
    </td>
    
    <td>
      <code>
        number
      </code>
    </td>
    
    <td>
      <code>
        1.03
      </code>
    </td>
    
    <td>
      Lift while hovered or held.
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        perspective
      </code>
    </td>
    
    <td>
      <code>
        number
      </code>
    </td>
    
    <td>
      <code>
        1100
      </code>
    </td>
    
    <td>
      Viewing distance in px. Smaller is more dramatic.
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        stiffness
      </code>
    </td>
    
    <td>
      <code>
        number
      </code>
    </td>
    
    <td>
      <code>
        170
      </code>
    </td>
    
    <td>
      Stiffness of the flip spring.
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        damping
      </code>
    </td>
    
    <td>
      <code>
        number
      </code>
    </td>
    
    <td>
      <code>
        20
      </code>
    </td>
    
    <td>
      Damping of the flip spring. Lower overshoots more.
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        width
      </code>
    </td>
    
    <td>
      <code>
        number
      </code>
    </td>
    
    <td>
      <code>
        300
      </code>
    </td>
    
    <td>
      Card width in px, capped at the parent.
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        height
      </code>
    </td>
    
    <td>
      <code>
        number
      </code>
    </td>
    
    <td>
      <code>
        400
      </code>
    </td>
    
    <td>
      Card height in px.
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        radius
      </code>
    </td>
    
    <td>
      <code>
        number
      </code>
    </td>
    
    <td>
      <code>
        22
      </code>
    </td>
    
    <td>
      Corner radius in px.
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        background
      </code>
    </td>
    
    <td>
      <code>
        string
      </code>
    </td>
    
    <td>
      <code>
        '#27272a'
      </code>
    </td>
    
    <td>
      Surface of both faces. Also exposed to the faces as <code>
        --fc-bg
      </code>
      
      .
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        color
      </code>
    </td>
    
    <td>
      <code>
        string
      </code>
    </td>
    
    <td>
      <code>
        '#f5f5f5'
      </code>
    </td>
    
    <td>
      Text colour of both faces.
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        shadow
      </code>
    </td>
    
    <td>
      <code>
        boolean
      </code>
    </td>
    
    <td>
      <code>
        true
      </code>
    </td>
    
    <td>
      A soft shadow beneath the card that narrows as it turns edge on.
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        shadow-color
      </code>
    </td>
    
    <td>
      <code>
        string
      </code>
    </td>
    
    <td>
      <code>
        '#000000'
      </code>
    </td>
    
    <td>
      Shadow colour.
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        shadow-opacity
      </code>
    </td>
    
    <td>
      <code>
        number
      </code>
    </td>
    
    <td>
      <code>
        0.45
      </code>
    </td>
    
    <td>
      Shadow strength.
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        disabled
      </code>
    </td>
    
    <td>
      <code>
        boolean
      </code>
    </td>
    
    <td>
      <code>
        false
      </code>
    </td>
    
    <td>
      Dimmed, flat and inert.
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        aria-label
      </code>
    </td>
    
    <td>
      <code>
        string
      </code>
    </td>
    
    <td>
      <code>
        'Flip card'
      </code>
    </td>
    
    <td>
      Accessible name. The face shown is carried by <code>
        aria-pressed
      </code>
      
      .
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        class
      </code>
    </td>
    
    <td>
      <code>
        string
      </code>
    </td>
    
    <td>
      <code>
        ''
      </code>
    </td>
    
    <td>
      Extra classes for the root.
    </td>
  </tr>
</tbody>
</table>

## Slots and events

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

<tbody>
  <tr>
    <td>
      <code>
        front
      </code>
      
       slot
    </td>
    
    <td>
      —
    </td>
    
    <td>
      Content of the front face.
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        back
      </code>
      
       slot
    </td>
    
    <td>
      —
    </td>
    
    <td>
      Content of the back face.
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        update:flipped
      </code>
      
       event
    </td>
    
    <td>
      <code>
        boolean
      </code>
    </td>
    
    <td>
      Fires when a click, drag, flick or key lands on the other face.
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        flip-change
      </code>
      
       event
    </td>
    
    <td>
      <code>
        boolean
      </code>
    </td>
    
    <td>
      Same as <code>
        update:flipped
      </code>
      
      , for listeners that don't use <code>
        v-model
      </code>
      
      .
    </td>
  </tr>
</tbody>
</table>

## Accessibility

- The card is a `role="button"` with `aria-pressed` set while the back is shown.
- Enter and Space flip it. Focus shows a visible ring.
- The hidden face is `inert` and `aria-hidden`, so its links and text are skipped.
- With `prefers-reduced-motion: reduce`, the faces cross-fade instead of turning, and tilt, lift and drag are off.
- Ported from [React Bits](https://reactbits.dev/micro/flip-card) by David Haz.
