# Cursor Grid

> A crisp grid whose cells light up and fade behind the cursor, with grid styles, tiles and click pulses.

A WebGL 2 grid that reacts to the cursor. Move the pointer over it and the cells near the cursor light up, hold for a moment, then fade. The grid lines brighten in a soft spotlight around the pointer. Click to send a ring of lit cells out from the click. Use the controls to try the presets: Minimal, Cell, Tiles, Marks, Dots, Dashed and Classic.

<demo-cursor-grid>



</demo-cursor-grid>

## Installation

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

## Usage

```vue
<script setup lang="ts">
  import CursorGrid from '~/components/ui/cursor-grid/CursorGrid.vue';
</script>

<template>
  <div class="relative h-125 w-full overflow-hidden rounded-lg bg-zinc-950">
    <CursorGrid
      color="#7dd3fc"
      highlight="cell"
      :cell-gap="4"
      :cell-radius="10"
      :fill-opacity="0.14"
      :grid-opacity="0.05"
      :fade-duration="1200"
    >
      <h2 class="grid size-full place-items-center text-3xl text-white">
        Hover me
      </h2>
    </CursorGrid>
  </div>
</template>
```

The grid fills its parent, so give the parent a size. Content in the default slot is drawn above the grid, and the grid keeps reacting to the cursor underneath it. Set `cell-gap` or `cell-radius` above 0 to draw lit cells as separate tiles. On a light page, set `light-mode` so the default colors are near black.

## Props

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

<tbody>
  <tr>
    <td>
      <code>
        color
      </code>
    </td>
    
    <td>
      <code>
        string
      </code>
    </td>
    
    <td>
      <code>
        '#ffffff'
      </code>
    </td>
    
    <td>
      Color of lit cells and pulses. Defaults to near black in light mode.
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        grid-color
      </code>
    </td>
    
    <td>
      <code>
        string
      </code>
    </td>
    
    <td>
      <code>
        '#ffffff'
      </code>
    </td>
    
    <td>
      Color of the grid lines. Defaults to near black in light mode.
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        cell-size
      </code>
    </td>
    
    <td>
      <code>
        number
      </code>
    </td>
    
    <td>
      <code>
        60
      </code>
    </td>
    
    <td>
      Size of each grid cell, in px.
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        highlight
      </code>
    </td>
    
    <td>
      <code>
        'area' | 'cell'
      </code>
    </td>
    
    <td>
      <code>
        'area'
      </code>
    </td>
    
    <td>
      Light every cell within the radius around the cursor, or only the cell under it.
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        grid-style
      </code>
    </td>
    
    <td>
      <code>
        'lines' | 'dashed' | 'dots' | 'crosses'
      </code>
    </td>
    
    <td>
      <code>
        'lines'
      </code>
    </td>
    
    <td>
      How the grid is drawn: solid lines, dashed lines, dots or plus marks where the lines meet.
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        radius
      </code>
    </td>
    
    <td>
      <code>
        number
      </code>
    </td>
    
    <td>
      <code>
        140
      </code>
    </td>
    
    <td>
      Reach of the cursor, in px, for both the lit area and the spotlight.
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        falloff
      </code>
    </td>
    
    <td>
      <code>
        'smooth' | 'linear' | 'sharp'
      </code>
    </td>
    
    <td>
      <code>
        'smooth'
      </code>
    </td>
    
    <td>
      How quickly cells dim toward the edge of the radius.
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        hold-time
      </code>
    </td>
    
    <td>
      <code>
        number
      </code>
    </td>
    
    <td>
      <code>
        400
      </code>
    </td>
    
    <td>
      How long a cell stays lit before fading, in ms.
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        fade-duration
      </code>
    </td>
    
    <td>
      <code>
        number
      </code>
    </td>
    
    <td>
      <code>
        800
      </code>
    </td>
    
    <td>
      How long a lit cell takes to fade out, in ms.
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        line-width
      </code>
    </td>
    
    <td>
      <code>
        number
      </code>
    </td>
    
    <td>
      <code>
        1
      </code>
    </td>
    
    <td>
      Width of the grid lines, in px.
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        max-opacity
      </code>
    </td>
    
    <td>
      <code>
        number
      </code>
    </td>
    
    <td>
      <code>
        1
      </code>
    </td>
    
    <td>
      Brightness of a fully lit cell outline.
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        fill-opacity
      </code>
    </td>
    
    <td>
      <code>
        number
      </code>
    </td>
    
    <td>
      <code>
        0.06
      </code>
    </td>
    
    <td>
      Soft fill inside lit cells.
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        grid-opacity
      </code>
    </td>
    
    <td>
      <code>
        number
      </code>
    </td>
    
    <td>
      <code>
        0.08
      </code>
    </td>
    
    <td>
      Opacity of the grid lines at rest. <code>
        0
      </code>
      
       shows only lit cells.
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        spotlight
      </code>
    </td>
    
    <td>
      <code>
        number
      </code>
    </td>
    
    <td>
      <code>
        0.6
      </code>
    </td>
    
    <td>
      How much the grid lines brighten around the cursor, from 0 to 1.
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        cell-gap
      </code>
    </td>
    
    <td>
      <code>
        number
      </code>
    </td>
    
    <td>
      <code>
        0
      </code>
    </td>
    
    <td>
      Inset of lit cells, in px. Above 0, lit cells become separate tiles.
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        cell-radius
      </code>
    </td>
    
    <td>
      <code>
        number
      </code>
    </td>
    
    <td>
      <code>
        0
      </code>
    </td>
    
    <td>
      Corner radius of lit tiles, in px.
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        click-pulse
      </code>
    </td>
    
    <td>
      <code>
        boolean
      </code>
    </td>
    
    <td>
      <code>
        true
      </code>
    </td>
    
    <td>
      Clicking sends a ring of lit cells out from the click.
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        pulse-speed
      </code>
    </td>
    
    <td>
      <code>
        number
      </code>
    </td>
    
    <td>
      <code>
        600
      </code>
    </td>
    
    <td>
      Speed of the click ring, in px per second.
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        ambient
      </code>
    </td>
    
    <td>
      <code>
        number
      </code>
    </td>
    
    <td>
      <code>
        0
      </code>
    </td>
    
    <td>
      Lets random cells glow softly on their own, from 0 to 1.
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        edge-fade
      </code>
    </td>
    
    <td>
      <code>
        number
      </code>
    </td>
    
    <td>
      <code>
        0.2
      </code>
    </td>
    
    <td>
      Fades the grid out toward the edges, from 0 to 0.5.
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        intro
      </code>
    </td>
    
    <td>
      <code>
        boolean
      </code>
    </td>
    
    <td>
      <code>
        true
      </code>
    </td>
    
    <td>
      Draws the grid out from the center with a pulse on mount.
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        light-mode
      </code>
    </td>
    
    <td>
      <code>
        boolean
      </code>
    </td>
    
    <td>
      <code>
        false
      </code>
    </td>
    
    <td>
      Uses near black lines and cells by default, for light pages.
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        dpr
      </code>
    </td>
    
    <td>
      <code>
        number
      </code>
    </td>
    
    <td>
      <code>
        auto
      </code>
    </td>
    
    <td>
      Maximum device pixel ratio, capped at 2.
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        class
      </code>
    </td>
    
    <td>
      <code>
        string
      </code>
    </td>
    
    <td>
      <code>
        ''
      </code>
    </td>
    
    <td>
      Extra classes for the root element.
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        style
      </code>
    </td>
    
    <td>
      <code>
        StyleValue
      </code>
    </td>
    
    <td>
      <code>
        -
      </code>
    </td>
    
    <td>
      Inline styles for the root element.
    </td>
  </tr>
</tbody>
</table>

## Slots

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

<tbody>
  <tr>
    <td>
      <code>
        default
      </code>
    </td>
    
    <td>
      Content drawn above the grid. The grid keeps reacting to the cursor underneath it.
    </td>
  </tr>
</tbody>
</table>

## Accessibility

- The canvas is decorative and has `aria-hidden="true"`. Slot content stays in the normal reading order.
- With `prefers-reduced-motion: reduce`, the intro, the click pulses and the ambient glow are off. Cells still light under the cursor.
- The render loop sleeps when nothing moves, and stops while the grid is offscreen or the tab is hidden. The WebGL 2 context is released on unmount.
- The component needs WebGL 2. Without it, only the slot content renders.
- Ported from [React Bits](https://reactbits.dev/animations/cursor-grid) by David Haz.
