# Cubes

> A grid of outlined 3D cubes that turn to face the cursor, spin when swept and ripple on click, drawn with instanced WebGL2.

A grid of outlined 3D cubes on springs. Cubes near the cursor turn to face it, a fast sweep spins the cubes it passes over, and a click sends a ripple through the grid that lights up their edges. On mount the cubes tumble into place from the center, and while the cursor is away a gentle wave drifts across the grid. Everything is one instanced WebGL2 draw, and the loop sleeps when the cubes settle.

<demo-cubes>



</demo-cubes>

## Installation

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

## Usage

The grid fills its parent and stays square, centered on the shorter side.

```vue
<script setup lang="ts">
  import Cubes from '~/components/ui/cubes/Cubes.vue';
</script>

<template>
  <div class="relative h-150 w-full">
    <Cubes
      :grid-size="10"
      :gap="0.18"
      face-color="#120F17"
      edge-color="#ffffff"
      edge-style="dashed"
      :max-angle="45"
      :radius="3"
      ripple-color="#ffffff"
    />
  </div>
</template>
```

## Props

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

<tbody>
  <tr>
    <td>
      <code>
        grid-size
      </code>
    </td>
    
    <td>
      <code>
        number
      </code>
    </td>
    
    <td>
      <code>
        10
      </code>
    </td>
    
    <td>
      Number of cubes on each side of the grid (1 to 40).
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        gap
      </code>
    </td>
    
    <td>
      <code>
        number
      </code>
    </td>
    
    <td>
      <code>
        0.18
      </code>
    </td>
    
    <td>
      Space between cubes, as a fraction of a cell.
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        face-color
      </code>
    </td>
    
    <td>
      <code>
        string
      </code>
    </td>
    
    <td>
      <code>
        '#120F17'
      </code>
    </td>
    
    <td>
      Color of the cube faces. Match it to your page background for a clean cut-out.
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        edge-color
      </code>
    </td>
    
    <td>
      <code>
        string
      </code>
    </td>
    
    <td>
      <code>
        '#ffffff'
      </code>
    </td>
    
    <td>
      Color of the cube outlines.
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        edge-width
      </code>
    </td>
    
    <td>
      <code>
        number
      </code>
    </td>
    
    <td>
      <code>
        1
      </code>
    </td>
    
    <td>
      Width of the outlines in px.
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        edge-style
      </code>
    </td>
    
    <td>
      <code>
        'solid' | 'dashed' | 'dotted' | 'none'
      </code>
    </td>
    
    <td>
      <code>
        'solid'
      </code>
    </td>
    
    <td>
      How the cube outlines are drawn.
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        face-opacity
      </code>
    </td>
    
    <td>
      <code>
        number
      </code>
    </td>
    
    <td>
      <code>
        1
      </code>
    </td>
    
    <td>
      Opacity of the faces, from 0 for see-through wireframes to 1 for solid cubes.
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        shading
      </code>
    </td>
    
    <td>
      <code>
        number
      </code>
    </td>
    
    <td>
      <code>
        0.6
      </code>
    </td>
    
    <td>
      How much the sides of turned cubes pick up light, so they read as solid shapes.
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        max-angle
      </code>
    </td>
    
    <td>
      <code>
        number
      </code>
    </td>
    
    <td>
      <code>
        45
      </code>
    </td>
    
    <td>
      How far cubes turn to face the cursor, in degrees.
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        radius
      </code>
    </td>
    
    <td>
      <code>
        number
      </code>
    </td>
    
    <td>
      <code>
        3
      </code>
    </td>
    
    <td>
      How far the cursor reaches, in cubes.
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        speed
      </code>
    </td>
    
    <td>
      <code>
        number
      </code>
    </td>
    
    <td>
      <code>
        1
      </code>
    </td>
    
    <td>
      How quickly cubes respond.
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        bounce
      </code>
    </td>
    
    <td>
      <code>
        number
      </code>
    </td>
    
    <td>
      <code>
        0.4
      </code>
    </td>
    
    <td>
      How much cubes overshoot and wobble as they settle, from 0 to 1.
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        brush
      </code>
    </td>
    
    <td>
      <code>
        number
      </code>
    </td>
    
    <td>
      <code>
        1
      </code>
    </td>
    
    <td>
      How strongly fast cursor sweeps spin the cubes they pass over.
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        perspective
      </code>
    </td>
    
    <td>
      <code>
        number
      </code>
    </td>
    
    <td>
      <code>
        0
      </code>
    </td>
    
    <td>
      Camera perspective, from 0 for a flat front view to 1 for strong depth.
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        auto-animate
      </code>
    </td>
    
    <td>
      <code>
        boolean
      </code>
    </td>
    
    <td>
      <code>
        true
      </code>
    </td>
    
    <td>
      Drifts a gentle wave across the grid while the cursor is away.
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        ripple-on-click
      </code>
    </td>
    
    <td>
      <code>
        boolean
      </code>
    </td>
    
    <td>
      <code>
        true
      </code>
    </td>
    
    <td>
      Clicking sends a ripple through the cubes that lights up their edges.
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        ripple-color
      </code>
    </td>
    
    <td>
      <code>
        string
      </code>
    </td>
    
    <td>
      <code>
        '#ffffff'
      </code>
    </td>
    
    <td>
      Color the ripple lights the cubes with.
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        ripple-speed
      </code>
    </td>
    
    <td>
      <code>
        number
      </code>
    </td>
    
    <td>
      <code>
        1
      </code>
    </td>
    
    <td>
      Speed of the ripple.
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        intro
      </code>
    </td>
    
    <td>
      <code>
        boolean
      </code>
    </td>
    
    <td>
      <code>
        true
      </code>
    </td>
    
    <td>
      Cubes tumble into place from the center on mount.
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        paused
      </code>
    </td>
    
    <td>
      <code>
        boolean
      </code>
    </td>
    
    <td>
      <code>
        false
      </code>
    </td>
    
    <td>
      Freezes the animation.
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        dpr
      </code>
    </td>
    
    <td>
      <code>
        number
      </code>
    </td>
    
    <td>
      auto
    </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 container.
    </td>
  </tr>
</tbody>
</table>

## Accessibility

- The canvas is decorative (`aria-hidden="true"`). Put any meaningful content in regular markup next to or over it.
- With `prefers-reduced-motion: reduce` there is no intro, no idle wave, no sweep spin and no ripple; cubes still turn toward the cursor, without spring wobble.
- `touch-action: pan-y` keeps vertical page scrolling on touch screens. The loop stops when the cubes settle, when the grid is offscreen and when the tab is hidden.
- Ported from [React Bits](https://reactbits.dev/animations/cubes) by David Haz.
