# Decay Card

> An image card that tears and melts as the pointer moves, then pulls itself back together.

An image card drawn with a WebGL shader. Move the pointer fast and the photo tears apart at the edges; slow down and it pulls itself back together. The card drifts and tilts toward the pointer, and while nobody interacts its edges keep fraying slowly. With `scope="card"` it only reacts while hovered. Pick a preset in the panel to try the shatter, melt and prism looks.

<demo-decay-card>



</demo-decay-card>

## Installation

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

## Usage

```vue
<script setup lang="ts">
  import DecayCard from '~/components/ui/decay-card/DecayCard.vue';
</script>

<template>
  <DecayCard
    image="https://images.unsplash.com/photo-1778849097774-0ab2a873a858?w=900&q=80&auto=format&fit=crop"
  >
    <p class="mb-1 text-xs text-white/70">No. 01</p>
    <p class="text-2xl/tight font-semibold tracking-tight">Afterglow</p>
  </DecayCard>

  <!-- Melting, with split colors, only reacting on hover -->
  <DecayCard
    image="/photo.jpg"
    :intensity="0.45"
    :grain="0.1"
    :detail="2"
    :flow="0.4"
    :chroma="0.6"
    :radius="16"
    scope="card"
  />
</template>
```

The image must be served with CORS headers (most image CDNs do), because it is uploaded to WebGL. If WebGL2 is not available or the image cannot be used, a plain `<img>` is shown instead.

## Props

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

<tbody>
  <tr>
    <td>
      <code>
        image
      </code>
    </td>
    
    <td>
      <code>
        string
      </code>
    </td>
    
    <td>
      An Unsplash photo
    </td>
    
    <td>
      Image URL. It fills the card like a cover.
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        width
      </code>
    </td>
    
    <td>
      <code>
        number
      </code>
    </td>
    
    <td>
      <code>
        300
      </code>
    </td>
    
    <td>
      Card width, in px.
    </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>
        intensity
      </code>
    </td>
    
    <td>
      <code>
        number
      </code>
    </td>
    
    <td>
      <code>
        0.5
      </code>
    </td>
    
    <td>
      How far the image tears apart at full decay, from 0 to 2. The edges tear the most.
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        sensitivity
      </code>
    </td>
    
    <td>
      <code>
        number
      </code>
    </td>
    
    <td>
      <code>
        0.5
      </code>
    </td>
    
    <td>
      How little pointer movement it takes to reach full decay, from 0 to 1.
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        hover-decay
      </code>
    </td>
    
    <td>
      <code>
        number
      </code>
    </td>
    
    <td>
      <code>
        0.05
      </code>
    </td>
    
    <td>
      Decay that stays while the pointer rests on the card, from 0 to 1.
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        recovery
      </code>
    </td>
    
    <td>
      <code>
        number
      </code>
    </td>
    
    <td>
      <code>
        0.6
      </code>
    </td>
    
    <td>
      Seconds the image takes to pull itself back together once the pointer slows down.
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        idle
      </code>
    </td>
    
    <td>
      <code>
        number
      </code>
    </td>
    
    <td>
      <code>
        0.35
      </code>
    </td>
    
    <td>
      Keeps the edges slowly fraying while nobody interacts, from 0 to 1.
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        grain
      </code>
    </td>
    
    <td>
      <code>
        number
      </code>
    </td>
    
    <td>
      <code>
        0.25
      </code>
    </td>
    
    <td>
      Size of the tears, from broad melting shapes at 0 to fine shards at 1.
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        detail
      </code>
    </td>
    
    <td>
      <code>
        number
      </code>
    </td>
    
    <td>
      <code>
        5
      </code>
    </td>
    
    <td>
      Layers of noise in the tears, from 1 to 8. More layers give rougher edges.
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        pattern
      </code>
    </td>
    
    <td>
      <code>
        number
      </code>
    </td>
    
    <td>
      <code>
        4
      </code>
    </td>
    
    <td>
      Picks a different tear pattern.
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        flow
      </code>
    </td>
    
    <td>
      <code>
        number
      </code>
    </td>
    
    <td>
      <code>
        0
      </code>
    </td>
    
    <td>
      Lets the tears churn while the card is decaying, from 0 to 2. 0 keeps them still.
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        chroma
      </code>
    </td>
    
    <td>
      <code>
        number
      </code>
    </td>
    
    <td>
      <code>
        0
      </code>
    </td>
    
    <td>
      Splits the color channels apart inside the tears, from 0 to 2.
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        travel
      </code>
    </td>
    
    <td>
      <code>
        number
      </code>
    </td>
    
    <td>
      <code>
        50
      </code>
    </td>
    
    <td>
      How far in px the card drifts toward the pointer before it slows down.
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        tilt
      </code>
    </td>
    
    <td>
      <code>
        number
      </code>
    </td>
    
    <td>
      <code>
        10
      </code>
    </td>
    
    <td>
      How far in degrees the card rotates as the pointer moves sideways.
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        scope
      </code>
    </td>
    
    <td>
      <code>
        'window' | 'card'
      </code>
    </td>
    
    <td>
      <code>
        'window'
      </code>
    </td>
    
    <td>
      <code>
        window
      </code>
      
       follows the pointer anywhere on the page. <code>
        card
      </code>
      
       only reacts while it is hovered.
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        radius
      </code>
    </td>
    
    <td>
      <code>
        number
      </code>
    </td>
    
    <td>
      <code>
        0
      </code>
    </td>
    
    <td>
      Corner radius of the image, in px.
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        grayscale
      </code>
    </td>
    
    <td>
      <code>
        boolean
      </code>
    </td>
    
    <td>
      <code>
        false
      </code>
    </td>
    
    <td>
      Shows the image in grayscale.
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        class
      </code>
    </td>
    
    <td>
      <code>
        string
      </code>
    </td>
    
    <td>
      <code>
        ''
      </code>
    </td>
    
    <td>
      Extra classes on the root.
    </td>
  </tr>
</tbody>
</table>

## Slots

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

<tbody>
  <tr>
    <td>
      <code>
        default
      </code>
    </td>
    
    <td>
      Content shown over the bottom of the image, in white text.
    </td>
  </tr>
</tbody>
</table>

## Accessibility

- The canvas is decorative (`aria-hidden`). Put any text that matters in the default slot, where it stays readable.
- With `prefers-reduced-motion: reduce`, the card does not drift, tilt or churn. The tears still follow the pointer speed.
- Rendering pauses while the card is off screen and once it has settled.
- Ported from [React Bits](https://reactbits.dev/components/decay-card) by David Haz.
