# Particles

> A drifting 3D field of particles with glow, twinkle, constellation lines and cursor interaction.

A 3D cloud of particles drawn with instanced raw WebGL2, so it stays crisp and fast with thousands of points. The field flies in from the distance, floats and slowly turns, and each particle can glow and twinkle. Move the cursor to tilt the field with parallax, or switch `hover-effect` to push particles away or pull them in. Click to send a burst of light rippling through them. Particles can be circles, squares, rings or sparkles, drift up like embers, down like snow or toward you like a starfield, blur into bokeh near the lens, and join into constellation lines. Pick a preset in the demo panel, or press refresh to replay the intro.

<demo-particles>



</demo-particles>

## Installation

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

## Usage

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

<template>
  <div class="relative h-125 w-full overflow-hidden">
    <Particles
      :particle-colors="['#ffffff']"
      :particle-count="200"
      :particle-spread="10"
      :speed="0.1"
      :particle-base-size="100"
      :glow="0.5"
      :twinkle="0.3"
      hover-effect="parallax"
      :click-burst="true"
    />
  </div>
</template>
```

The demo presets ship with the component: `particlesPreset('fireflies')` returns the props of the Classic, Constellation, Bokeh, Fireflies, Snow, Warp or Stardust preset.

## Props

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

<tbody>
  <tr>
    <td>
      <code>
        particle-count
      </code>
    </td>
    
    <td>
      <code>
        number
      </code>
    </td>
    
    <td>
      <code>
        200
      </code>
    </td>
    
    <td>
      How many particles there are (up to 20,000).
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        particle-spread
      </code>
    </td>
    
    <td>
      <code>
        number
      </code>
    </td>
    
    <td>
      <code>
        10
      </code>
    </td>
    
    <td>
      How far the particles spread out from the center.
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        speed
      </code>
    </td>
    
    <td>
      <code>
        number
      </code>
    </td>
    
    <td>
      <code>
        0.1
      </code>
    </td>
    
    <td>
      Speed of the floating motion, twinkle and rotation.
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        particle-colors
      </code>
    </td>
    
    <td>
      <code>
        string[]
      </code>
    </td>
    
    <td>
      <code>
        ['#ffffff']
      </code>
    </td>
    
    <td>
      Colors the particles are picked from.
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        particle-base-size
      </code>
    </td>
    
    <td>
      <code>
        number
      </code>
    </td>
    
    <td>
      <code>
        100
      </code>
    </td>
    
    <td>
      Base size of the particles. Nearer particles are drawn larger.
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        size-randomness
      </code>
    </td>
    
    <td>
      <code>
        number
      </code>
    </td>
    
    <td>
      <code>
        1
      </code>
    </td>
    
    <td>
      How much particle sizes vary. <code>
        0
      </code>
      
       draws every particle at the base size in px.
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        shape
      </code>
    </td>
    
    <td>
      <code>
        'circle' | 'square' | 'ring' | 'sparkle'
      </code>
    </td>
    
    <td>
      <code>
        'circle'
      </code>
    </td>
    
    <td>
      Shape of each particle.
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        glow
      </code>
    </td>
    
    <td>
      <code>
        number
      </code>
    </td>
    
    <td>
      <code>
        0.5
      </code>
    </td>
    
    <td>
      Soft glow around each particle.
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        twinkle
      </code>
    </td>
    
    <td>
      <code>
        number
      </code>
    </td>
    
    <td>
      <code>
        0.3
      </code>
    </td>
    
    <td>
      How much the particles flicker, from 0 to 1.
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        depth-of-field
      </code>
    </td>
    
    <td>
      <code>
        number
      </code>
    </td>
    
    <td>
      <code>
        0
      </code>
    </td>
    
    <td>
      Blurs the nearest particles into soft bokeh, like a camera lens.
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        connections
      </code>
    </td>
    
    <td>
      <code>
        boolean
      </code>
    </td>
    
    <td>
      <code>
        false
      </code>
    </td>
    
    <td>
      Joins nearby particles with thin lines, like a constellation.
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        connection-distance
      </code>
    </td>
    
    <td>
      <code>
        number
      </code>
    </td>
    
    <td>
      <code>
        110
      </code>
    </td>
    
    <td>
      How close particles need to be to connect, in px.
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        drift
      </code>
    </td>
    
    <td>
      <code>
        'none' | 'up' | 'down' | 'forward'
      </code>
    </td>
    
    <td>
      <code>
        'none'
      </code>
    </td>
    
    <td>
      Sends the particles drifting up like embers, down like snow, or toward you like a starfield.
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        drift-speed
      </code>
    </td>
    
    <td>
      <code>
        number
      </code>
    </td>
    
    <td>
      <code>
        1
      </code>
    </td>
    
    <td>
      How fast the particles drift.
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        move-particles-on-hover
      </code>
    </td>
    
    <td>
      <code>
        boolean
      </code>
    </td>
    
    <td>
      <code>
        true
      </code>
    </td>
    
    <td>
      Lets the cursor move the particles.
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        hover-effect
      </code>
    </td>
    
    <td>
      <code>
        'parallax' | 'repel' | 'attract'
      </code>
    </td>
    
    <td>
      <code>
        'parallax'
      </code>
    </td>
    
    <td>
      What the cursor does: tilt the whole field, push particles away, or pull them in.
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        particle-hover-factor
      </code>
    </td>
    
    <td>
      <code>
        number
      </code>
    </td>
    
    <td>
      <code>
        1
      </code>
    </td>
    
    <td>
      Strength of the hover effect.
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        hover-radius
      </code>
    </td>
    
    <td>
      <code>
        number
      </code>
    </td>
    
    <td>
      <code>
        140
      </code>
    </td>
    
    <td>
      Radius around the cursor that repel and attract reach, in px.
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        click-burst
      </code>
    </td>
    
    <td>
      <code>
        boolean
      </code>
    </td>
    
    <td>
      <code>
        true
      </code>
    </td>
    
    <td>
      Clicking sends a burst of light rippling through the particles.
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        alpha-particles
      </code>
    </td>
    
    <td>
      <code>
        boolean
      </code>
    </td>
    
    <td>
      <code>
        false
      </code>
    </td>
    
    <td>
      Draws softer, slightly see-through particles.
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        camera-distance
      </code>
    </td>
    
    <td>
      <code>
        number
      </code>
    </td>
    
    <td>
      <code>
        20
      </code>
    </td>
    
    <td>
      Distance from the camera to the particles. Lower values feel closer and deeper.
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        disable-rotation
      </code>
    </td>
    
    <td>
      <code>
        boolean
      </code>
    </td>
    
    <td>
      <code>
        false
      </code>
    </td>
    
    <td>
      Stops the slow rotation of the whole field.
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        variation
      </code>
    </td>
    
    <td>
      <code>
        number
      </code>
    </td>
    
    <td>
      <code>
        0
      </code>
    </td>
    
    <td>
      Picks a different particle layout.
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        intro
      </code>
    </td>
    
    <td>
      <code>
        boolean
      </code>
    </td>
    
    <td>
      <code>
        true
      </code>
    </td>
    
    <td>
      Flies the particles in from the distance on mount.
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        opacity
      </code>
    </td>
    
    <td>
      <code>
        number
      </code>
    </td>
    
    <td>
      <code>
        1
      </code>
    </td>
    
    <td>
      Opacity of the whole effect.
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        light-mode
      </code>
    </td>
    
    <td>
      <code>
        boolean
      </code>
    </td>
    
    <td>
      <code>
        false
      </code>
    </td>
    
    <td>
      Draws the particles as ink for light backgrounds.
    </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>
        pixel-ratio
      </code>
    </td>
    
    <td>
      <code>
        number
      </code>
    </td>
    
    <td>
      auto
    </td>
    
    <td>
      Maximum device pixel ratio. Defaults to the screen's, capped at 2.
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        class
      </code>
    </td>
    
    <td>
      <code>
        string
      </code>
    </td>
    
    <td>
      <code>
        ''
      </code>
    </td>
    
    <td>
      Extra classes merged on the container.
    </td>
  </tr>
</tbody>
</table>

## Accessibility

- The canvas is decorative and marked `aria-hidden="true"`. Put real content above it.
- Pointer listeners are passive and sit on `window`, so the field never takes focus or blocks clicks on content above it.
- With `prefers-reduced-motion: reduce` there is no intro, no floating, drift, cursor effect or click burst. The field is drawn and holds still.
- The render loop stops when the field is paused, offscreen or in a hidden tab.
- Ported from [React Bits](https://reactbits.dev/backgrounds/particles) by David Haz.
