# Crystalized Ball

> A WebGL glass ball with a crackling electric rim and glowing dust that swirls with the cursor.

A glass ball with an electric rim and glowing dust inside it. Move the cursor near the ball and the rim heats up and flares toward it, while the dust swirls in its wake and turns to follow. Click the ball to shake it.

<demo-crystalized-ball>



</demo-crystalized-ball>

## Installation

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

## Usage

```vue
<script setup lang="ts">
  import CrystalizedBall from '~/components/ui/crystalized-ball/CrystalizedBall.vue';
</script>

<template>
  <div class="relative h-125 w-full overflow-hidden">
    <CrystalizedBall
      preset="ember"
      theme="dark"
      :size="0.7"
      :particle-count="20000"
      motion="orbit"
    />
  </div>
</template>
```

A preset sets every value marked *from preset*, including the color. Pass any of those props to override the preset value. All the rim, glow, spark, haze and dust tones are derived from the one `color`.

## Props

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

<tbody>
  <tr>
    <td>
      <code>
        preset
      </code>
    </td>
    
    <td>
      <code>
        'plasma' | 'aurora' | 'nebula' | 'ember' | 'frost' | 'solar' | 'eclipse' | 'abyss'
      </code>
    </td>
    
    <td>
      <code>
        'plasma'
      </code>
    </td>
    
    <td>
      A complete starting look, color included
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        color
      </code>
    </td>
    
    <td>
      <code>
        string
      </code>
    </td>
    
    <td>
      from preset
    </td>
    
    <td>
      The one color of the ball. All other tones are derived from it
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        theme
      </code>
    </td>
    
    <td>
      <code>
        'dark' | 'light'
      </code>
    </td>
    
    <td>
      <code>
        'dark'
      </code>
    </td>
    
    <td>
      Dark renders the ball as emitted light. Light draws it in crisp ink with a white-hot rim core
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        size
      </code>
    </td>
    
    <td>
      <code>
        number
      </code>
    </td>
    
    <td>
      <code>
        0.7
      </code>
    </td>
    
    <td>
      Diameter as a fraction of the smaller side of the container
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        strands
      </code>
    </td>
    
    <td>
      <code>
        number
      </code>
    </td>
    
    <td>
      from preset
    </td>
    
    <td>
      Electric strands braided around the rim, 1 to 8
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        crackle
      </code>
    </td>
    
    <td>
      <code>
        number
      </code>
    </td>
    
    <td>
      from preset
    </td>
    
    <td>
      How far the strands bend and jitter
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        flares
      </code>
    </td>
    
    <td>
      <code>
        number
      </code>
    </td>
    
    <td>
      from preset
    </td>
    
    <td>
      How far the glow licks outward from the rim in slow, travelling flares
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        glow
      </code>
    </td>
    
    <td>
      <code>
        number
      </code>
    </td>
    
    <td>
      from preset
    </td>
    
    <td>
      Strength of the halo around the rim
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        sparks
      </code>
    </td>
    
    <td>
      <code>
        number
      </code>
    </td>
    
    <td>
      from preset
    </td>
    
    <td>
      How often small arcs discharge along the inside of the rim. <code>
        0
      </code>
      
       turns them off
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        particle-count
      </code>
    </td>
    
    <td>
      <code>
        number
      </code>
    </td>
    
    <td>
      from preset
    </td>
    
    <td>
      Number of dust particles, up to 40000
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        fill
      </code>
    </td>
    
    <td>
      <code>
        number
      </code>
    </td>
    
    <td>
      from preset
    </td>
    
    <td>
      How full the ball is. Low values pool the dust at the bottom, high values float it up
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        motion
      </code>
    </td>
    
    <td>
      <code>
        'rise' | 'fall' | 'drift' | 'orbit'
      </code>
    </td>
    
    <td>
      from preset
    </td>
    
    <td>
      Rise floats like embers, fall drifts down like snow, drift wanders, orbit loops in small circles
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        particle-shape
      </code>
    </td>
    
    <td>
      <code>
        'square' | 'round'
      </code>
    </td>
    
    <td>
      from preset
    </td>
    
    <td>
      Crisp square pixels or soft round dots
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        depth
      </code>
    </td>
    
    <td>
      <code>
        number
      </code>
    </td>
    
    <td>
      from preset
    </td>
    
    <td>
      Strength of the depth cues. Dust at the back gets smaller and dimmer
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        sway
      </code>
    </td>
    
    <td>
      <code>
        number
      </code>
    </td>
    
    <td>
      from preset
    </td>
    
    <td>
      How much the dust turns back and forth inside the glass
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        twinkle
      </code>
    </td>
    
    <td>
      <code>
        number
      </code>
    </td>
    
    <td>
      from preset
    </td>
    
    <td>
      How much the dust sparkles on and off
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        haze
      </code>
    </td>
    
    <td>
      <code>
        number
      </code>
    </td>
    
    <td>
      from preset
    </td>
    
    <td>
      Strength of the glow pooled under the dust and along the inside of the glass
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        speed
      </code>
    </td>
    
    <td>
      <code>
        number
      </code>
    </td>
    
    <td>
      <code>
        1
      </code>
    </td>
    
    <td>
      Animation speed of the rim, flares and sparks
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        dust-speed
      </code>
    </td>
    
    <td>
      <code>
        number
      </code>
    </td>
    
    <td>
      from preset
    </td>
    
    <td>
      Animation speed of the dust
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        interactive
      </code>
    </td>
    
    <td>
      <code>
        boolean
      </code>
    </td>
    
    <td>
      <code>
        true
      </code>
    </td>
    
    <td>
      Lets the cursor heat the rim, stir and turn the dust, and shake the ball on click
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        hover-strength
      </code>
    </td>
    
    <td>
      <code>
        number
      </code>
    </td>
    
    <td>
      <code>
        0.7
      </code>
    </td>
    
    <td>
      How strongly the ball reacts to the cursor, 0 to 1
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        intro
      </code>
    </td>
    
    <td>
      <code>
        boolean
      </code>
    </td>
    
    <td>
      <code>
        true
      </code>
    </td>
    
    <td>
      On mount the rim powers up and the dust lights up from the bottom
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        paused
      </code>
    </td>
    
    <td>
      <code>
        boolean
      </code>
    </td>
    
    <td>
      <code>
        false
      </code>
    </td>
    
    <td>
      Freezes the animation. The dust can still be stirred
    </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>
</tbody>
</table>

## Accessibility

- The canvas is decorative and marked `aria-hidden`. Add a visible caption or an `aria-label` on a parent if the ball carries meaning.
- With `prefers-reduced-motion: reduce` the ball renders one still frame, the intro is skipped and the cursor does not move it.
- The render loop stops while the ball is offscreen or idle (paused and settled), and the WebGL context is released on unmount.
- Needs WebGL 2. Without it the component renders an empty container.
- Ported from [React Bits](https://reactbits.dev/animations/crystalized-ball) by David Haz.
