# Pixel Wave

> A looping pixel-art scene rendered on a dark LED grid of colored patches, with four swappable presets.

<demo-pixel-wave>



</demo-pixel-wave>

## Installation

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

## Usage

```vue
<script setup lang="ts">
  import PixelWave from '~/components/ui/pixel-wave/PixelWave.vue';
</script>

<template>
  <div class="bg-neutral-950">
    <PixelWave class="h-100" />
    <h2>A Wave From Tahiti</h2>
    <p>Faded memories of wave breaks, rendered in pixel patches.</p>
  </div>
</template>
```

A fixed 20×19 grid of square cells renders a looping pixel-art scene. The
grid never moves — the animation is pure cell-state: colored bands turn on
and off as procedural fields morph through a crest, trough, near-black fade
window, and a rebuild before the loop restarts. Empty cells keep a faint LED
outline, so the display reads as a pixel patch panel even when the scene is
gone.

Four `scene` presets ship built in, each with its own palette and motion:

- **tahiti** — a rolling ocean swell of foam, turquoise, teal and navy.
- **desert** — sky bands over a pulsing sun disc and undulating dunes.
- **hearth** — an inverted-triangle flame from white core to crimson tips.
- **mind** — two sparse threads that drift, briefly meet, then separate.

The canvas sizes itself to its container (cells scale to fit), honors
`prefers-reduced-motion` by freezing on a static frame, and reports the
current phase through the `phase` event so you can drive captions or
accessibility status text.

## Props

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

<tbody>
  <tr>
    <td>
      <code>
        scene
      </code>
    </td>
    
    <td>
      <code>
        PixelWaveScene
      </code>
    </td>
    
    <td>
      <code>
        'tahiti'
      </code>
    </td>
    
    <td>
      Scene preset: <code>
        tahiti
      </code>
      
      , <code>
        desert
      </code>
      
      , <code>
        hearth
      </code>
      
       or <code>
        mind
      </code>
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        speed
      </code>
    </td>
    
    <td>
      <code>
        number
      </code>
    </td>
    
    <td>
      <code>
        1
      </code>
    </td>
    
    <td>
      Animation speed multiplier
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        vertical-padding
      </code>
    </td>
    
    <td>
      <code>
        number
      </code>
    </td>
    
    <td>
      <code>
        0
      </code>
    </td>
    
    <td>
      Extra empty rows above and below the grid
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        animate
      </code>
    </td>
    
    <td>
      <code>
        boolean
      </code>
    </td>
    
    <td>
      <code>
        true
      </code>
    </td>
    
    <td>
      Run the looping animation
    </td>
  </tr>
</tbody>
</table>

## Events

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

<tbody>
  <tr>
    <td>
      <code>
        phase
      </code>
    </td>
    
    <td>
      <code>
        PixelWavePhase
      </code>
    </td>
    
    <td>
      Fired when the loop enters a new phase (<code>
        crest
      </code>
      
      , <code>
        trough
      </code>
      
      , <code>
        fade
      </code>
      
      , <code>
        rebuild
      </code>
      
      )
    </td>
  </tr>
</tbody>
</table>

## Credits

Inspired by a series of pixel-patch scene experiments shared in the Vue
community.
