# Particle Text

> Text assembles from drifting particles that scatter and reform on demand — gather, rain, spiral or scan intros, cursor repel and click bursts.

Text is sampled into a few thousand canvas particles that fly in and settle into the glyphs. Move the cursor through the text to push particles aside; click to blow them apart and watch them spring back. Particles light up in the highlight color while they are away from their spot.

<demo-particle-text>



</demo-particle-text>

## Installation

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

## Usage

```vue
<script setup lang="ts">
  import ParticleText from '~/components/ui/particle-text/ParticleText.vue';
</script>

<template>
  <div class="relative h-100 w-full">
    <ParticleText
      text="Future Interfaces"
      highlight-color="#ff5a36"
      intro="spiral"
      shape="circle"
      :pointer-repel="42"
      :click-burst="true"
    />
  </div>
</template>
```

The component fills its parent (minimum height 240px), so give the parent a real height.

## Props

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

<tbody>
  <tr>
    <td>
      <code>
        text
      </code>
    </td>
    
    <td>
      <code>
        string
      </code>
    </td>
    
    <td>
      <code>
        'nxui'
      </code>
    </td>
    
    <td>
      The words sampled into particle targets
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        color
      </code>
    </td>
    
    <td>
      <code>
        string
      </code>
    </td>
    
    <td>
      <code>
        'currentColor'
      </code>
    </td>
    
    <td>
      Particle color at rest. Follows the surrounding text color by default
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        highlight-color
      </code>
    </td>
    
    <td>
      <code>
        string
      </code>
    </td>
    
    <td>
      <code>
        '#ff5a36'
      </code>
    </td>
    
    <td>
      Color particles take on while they fly in or get pushed. Also colors the glow and the scan line
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        intro
      </code>
    </td>
    
    <td>
      <code>
        'gather' | 'rain' | 'spiral' | 'scan'
      </code>
    </td>
    
    <td>
      <code>
        'gather'
      </code>
    </td>
    
    <td>
      How the text forms: pull together, drop from above, swirl into place, or print behind a sweeping line
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        gather-duration
      </code>
    </td>
    
    <td>
      <code>
        number
      </code>
    </td>
    
    <td>
      <code>
        1600
      </code>
    </td>
    
    <td>
      Milliseconds for the intro to form the text
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        stagger
      </code>
    </td>
    
    <td>
      <code>
        number
      </code>
    </td>
    
    <td>
      <code>
        420
      </code>
    </td>
    
    <td>
      Maximum per-particle delay in milliseconds
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        scatter
      </code>
    </td>
    
    <td>
      <code>
        number
      </code>
    </td>
    
    <td>
      <code>
        180
      </code>
    </td>
    
    <td>
      How far particles begin from their spots in the gather and spiral intros
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        trigger
      </code>
    </td>
    
    <td>
      <code>
        'mount' | 'hover' | 'click'
      </code>
    </td>
    
    <td>
      <code>
        'mount'
      </code>
    </td>
    
    <td>
      When the intro plays again after the first formation: never, on hover, or on click
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        click-burst
      </code>
    </td>
    
    <td>
      <code>
        boolean
      </code>
    </td>
    
    <td>
      <code>
        true
      </code>
    </td>
    
    <td>
      Clicking blows particles away from the click point, then they spring back. Off while <code>
        trigger
      </code>
      
       is <code>
        click
      </code>
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        burst-strength
      </code>
    </td>
    
    <td>
      <code>
        number
      </code>
    </td>
    
    <td>
      <code>
        1
      </code>
    </td>
    
    <td>
      How hard and how wide a click burst pushes
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        pointer-repel
      </code>
    </td>
    
    <td>
      <code>
        number
      </code>
    </td>
    
    <td>
      <code>
        40
      </code>
    </td>
    
    <td>
      Strength of the cursor pushback
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        repel-radius
      </code>
    </td>
    
    <td>
      <code>
        number
      </code>
    </td>
    
    <td>
      <code>
        120
      </code>
    </td>
    
    <td>
      Cursor influence radius in pixels
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        idle-drift
      </code>
    </td>
    
    <td>
      <code>
        number
      </code>
    </td>
    
    <td>
      <code>
        0.7
      </code>
    </td>
    
    <td>
      Subtle resting motion after the text has formed
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        shape
      </code>
    </td>
    
    <td>
      <code>
        'circle' | 'square' | 'line'
      </code>
    </td>
    
    <td>
      <code>
        'circle'
      </code>
    </td>
    
    <td>
      How each particle is drawn. <code>
        line
      </code>
      
       strokes stretch along their motion and settle into an even hatch
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        highlight-mode
      </code>
    </td>
    
    <td>
      <code>
        'motion' | 'gradient'
      </code>
    </td>
    
    <td>
      <code>
        'motion'
      </code>
    </td>
    
    <td>
      <code>
        motion
      </code>
      
       lights particles while they are away from their spot; <code>
        gradient
      </code>
      
       blends the highlight left to right
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        particle-size
      </code>
    </td>
    
    <td>
      <code>
        number
      </code>
    </td>
    
    <td>
      <code>
        2
      </code>
    </td>
    
    <td>
      Rendered size of each particle in CSS pixels
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        density
      </code>
    </td>
    
    <td>
      <code>
        number
      </code>
    </td>
    
    <td>
      <code>
        4
      </code>
    </td>
    
    <td>
      Pixel sampling step for the glyph canvas. Lower values create more particles
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        glow
      </code>
    </td>
    
    <td>
      <code>
        boolean
      </code>
    </td>
    
    <td>
      <code>
        true
      </code>
    </td>
    
    <td>
      Soft bloom in the highlight color around highlighted particles
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        font-size
      </code>
    </td>
    
    <td>
      <code>
        number | string
      </code>
    </td>
    
    <td>
      <code>
        'clamp(3rem, 12vw, 8rem)'
      </code>
    </td>
    
    <td>
      Text size used for glyph sampling (px number or any CSS length). Shrinks to fit 92% of the width
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        font-weight
      </code>
    </td>
    
    <td>
      <code>
        number | string
      </code>
    </td>
    
    <td>
      <code>
        800
      </code>
    </td>
    
    <td>
      Font weight used for sampling
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        font-family
      </code>
    </td>
    
    <td>
      <code>
        string
      </code>
    </td>
    
    <td>
      <code>
        'inherit'
      </code>
    </td>
    
    <td>
      Font family used for sampling. <code>
        inherit
      </code>
      
       waits for the surrounding font before sampling
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        class
      </code>
    </td>
    
    <td>
      <code>
        string
      </code>
    </td>
    
    <td>
      <code>
        ''
      </code>
    </td>
    
    <td>
      Extra classes on the wrapper
    </td>
  </tr>
</tbody>
</table>

## Accessibility

- The canvas is `aria-hidden`; the text is rendered in a visually hidden span so screen readers read it.
- With `prefers-reduced-motion: reduce` the intro, bursts, repel and drift are skipped and the text renders in place.
- The animation loop sleeps when everything is at rest and pauses while the component is offscreen.
- Ported from [React Bits](https://reactbits.dev/text-animations/particle-text) by David Haz.
