# Lattice Loader

A status row for an agent that is thinking. A small 3 × 3 or 4 × 4 lattice of cells brightens in a wave while a stopwatch counts tenths of a second beside the label. When `status` turns to `done` the wave fades into a green tick and the label reads "Done in" with the final time; on `error` it shows a red cross and "Failed after". Pick one of ten wave patterns or pass your own. Use the panel in the demo to switch status, grid and pattern.

<demo-lattice-loader>



</demo-lattice-loader>

## Installation

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

## Usage

```vue
<script setup lang="ts">
  import { ref } from 'vue';
  import LatticeLoader from '~/components/ui/lattice-loader/LatticeLoader.vue';
  import type { LatticeStatus } from '~/components/ui/lattice-loader/types';

  const status = ref<LatticeStatus>('working');
</script>

<template>
  <LatticeLoader :status="status" pattern="orbit" :grid="3" label="Thinking" />
</template>
```

A custom pattern gives each cell (row-major) the wave step it lights on; `null` leaves a hole:

```vue
<LatticeLoader
  :grid="3"
  :pattern="{ cells: [0, 1, 2, 1, null, 3, 2, 3, 4], loop: 7, scale: 1 }"
/>
```

Named patterns: `arrow`, `dots`, `orbit`, `ripple`, `snake`, `spiral` on the 3 × 3 grid, and `sweep`, `spin`, `rain`, `pulse`, `orbit`, `snake` on the 4 × 4 grid. A name with no layout for the grid falls back to `orbit` (3 × 3) or `sweep` (4 × 4).

## Props

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

<tbody>
  <tr>
    <td>
      <code>
        label
      </code>
    </td>
    
    <td>
      <code>
        string
      </code>
    </td>
    
    <td>
      <code>
        'Thinking'
      </code>
    </td>
    
    <td>
      Text while working.
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        done-label
      </code>
    </td>
    
    <td>
      <code>
        string
      </code>
    </td>
    
    <td>
      <code>
        'Done in'
      </code>
    </td>
    
    <td>
      Text once done; the time follows it.
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        error-label
      </code>
    </td>
    
    <td>
      <code>
        string
      </code>
    </td>
    
    <td>
      <code>
        'Failed after'
      </code>
    </td>
    
    <td>
      Text on error; the time follows it.
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        status
      </code>
    </td>
    
    <td>
      <code>
        'working' | 'done' | 'error'
      </code>
    </td>
    
    <td>
      <code>
        'working'
      </code>
    </td>
    
    <td>
      Working runs the wave and the clock. Done and error stop both and show a mark.
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        pattern
      </code>
    </td>
    
    <td>
      <code>
        LatticePatternName | LatticePattern
      </code>
    </td>
    
    <td>
      <code>
        'orbit'
      </code>
    </td>
    
    <td>
      A named wave or your own <code>
        { cells, loop, scale, lit }
      </code>
      
      .
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        grid
      </code>
    </td>
    
    <td>
      <code>
        3 | 4
      </code>
    </td>
    
    <td>
      <code>
        3
      </code>
    </td>
    
    <td>
      3 × 3 or 4 × 4 cells.
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        shape
      </code>
    </td>
    
    <td>
      <code>
        'square' | 'round'
      </code>
    </td>
    
    <td>
      <code>
        'round'
      </code>
    </td>
    
    <td>
      Square or round cells.
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        color
      </code>
    </td>
    
    <td>
      <code>
        string
      </code>
    </td>
    
    <td>
      <code>
        'currentColor'
      </code>
    </td>
    
    <td>
      Ink for the cells.
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        done-color
      </code>
    </td>
    
    <td>
      <code>
        string
      </code>
    </td>
    
    <td>
      <code>
        '#22c55e'
      </code>
    </td>
    
    <td>
      The tick on done.
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        error-color
      </code>
    </td>
    
    <td>
      <code>
        string
      </code>
    </td>
    
    <td>
      <code>
        '#ef4444'
      </code>
    </td>
    
    <td>
      The cross on error.
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        cell-size
      </code>
    </td>
    
    <td>
      <code>
        number
      </code>
    </td>
    
    <td>
      <code>
        6
      </code>
    </td>
    
    <td>
      Cell size in px.
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        gap
      </code>
    </td>
    
    <td>
      <code>
        number
      </code>
    </td>
    
    <td>
      <code>
        2
      </code>
    </td>
    
    <td>
      Gap between cells in px.
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        font-size
      </code>
    </td>
    
    <td>
      <code>
        number
      </code>
    </td>
    
    <td>
      <code>
        14
      </code>
    </td>
    
    <td>
      Text size in px.
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        step
      </code>
    </td>
    
    <td>
      <code>
        number
      </code>
    </td>
    
    <td>
      <code>
        90
      </code>
    </td>
    
    <td>
      Milliseconds between wave steps.
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        idle-opacity
      </code>
    </td>
    
    <td>
      <code>
        number
      </code>
    </td>
    
    <td>
      <code>
        0.15
      </code>
    </td>
    
    <td>
      Opacity of an unlit cell.
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        glow
      </code>
    </td>
    
    <td>
      <code>
        boolean
      </code>
    </td>
    
    <td>
      <code>
        false
      </code>
    </td>
    
    <td>
      A soft halo around each cell.
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        glow-color
      </code>
    </td>
    
    <td>
      <code>
        string
      </code>
    </td>
    
    <td>
      <code>
        ''
      </code>
    </td>
    
    <td>
      Halo colour. Empty uses the cell colour.
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        show-timer
      </code>
    </td>
    
    <td>
      <code>
        boolean
      </code>
    </td>
    
    <td>
      <code>
        true
      </code>
    </td>
    
    <td>
      Shows the stopwatch.
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        elapsed
      </code>
    </td>
    
    <td>
      <code>
        number
      </code>
    </td>
    
    <td>
      —
    </td>
    
    <td>
      Seconds to show instead of the internal clock.
    </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>

## Accessibility

- The root has `role="status"`. A visually hidden line announces "Thinking, in progress", then "Done in 2.4 seconds" or "Failed after 2.4 seconds".
- The lattice, label and timer are hidden from assistive tech so the clock does not chatter.
- With `prefers-reduced-motion`, all cells pulse together at a slower pace instead of running a wave, and the mark and label do not scale or blur.
- Ported from [React Bits](https://reactbits.dev/micro/lattice-loader) by David Haz.
