# Light Rays

Volumetric shafts of light pour in from any edge or corner, with a soft glow at the source and a slow haze drifting through the beam. The light cools toward blue as it travels. Move the pointer and the beam turns toward it while your cursor casts a soft shadow down the rays. Click anywhere over it to send a wave of light down the beam. The rays grow out from the source on mount, and `light-mode` prints the light as colored ink so it sits on pale pages. It renders on raw WebGL2 with a pixel budget, so it stays cheap on large screens.

<demo-light-rays>



</demo-light-rays>

## Installation

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

## Usage

```vue
<script setup lang="ts">
  import LightRays from '~/components/ui/light-rays/LightRays.vue';
</script>

<template>
  <div class="relative h-125 w-full overflow-hidden">
    <LightRays
      rays-origin="top-center"
      rays-color="#ffffff"
      :light-spread="0.5"
      :ray-length="3"
      :haze="0.25"
    />
  </div>
</template>
```

## Props

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

<tbody>
  <tr>
    <td>
      <code>
        rays-origin
      </code>
    </td>
    
    <td>
      <code>
        RaysOrigin
      </code>
    </td>
    
    <td>
      <code>
        'top-center'
      </code>
    </td>
    
    <td>
      Where the light comes from: <code>
        top-center
      </code>
      
      , <code>
        top-left
      </code>
      
      , <code>
        top-right
      </code>
      
      , <code>
        left
      </code>
      
      , <code>
        right
      </code>
      
      , <code>
        bottom-center
      </code>
      
      , <code>
        bottom-left
      </code>
      
      , <code>
        bottom-right
      </code>
      
      .
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        rays-color
      </code>
    </td>
    
    <td>
      <code>
        string
      </code>
    </td>
    
    <td>
      <code>
        '#ffffff'
      </code>
    </td>
    
    <td>
      Color of the light (hex or <code>
        rgb()
      </code>
      
      ).
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        rays-speed
      </code>
    </td>
    
    <td>
      <code>
        number
      </code>
    </td>
    
    <td>
      <code>
        1
      </code>
    </td>
    
    <td>
      Animation speed. 0 freezes the rays.
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        light-spread
      </code>
    </td>
    
    <td>
      <code>
        number
      </code>
    </td>
    
    <td>
      <code>
        0.5
      </code>
    </td>
    
    <td>
      How wide the beam opens. Lower values give a tight spotlight.
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        ray-length
      </code>
    </td>
    
    <td>
      <code>
        number
      </code>
    </td>
    
    <td>
      <code>
        3
      </code>
    </td>
    
    <td>
      How far the rays reach, in container widths.
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        ray-density
      </code>
    </td>
    
    <td>
      <code>
        number
      </code>
    </td>
    
    <td>
      <code>
        1
      </code>
    </td>
    
    <td>
      How many separate shafts the beam splits into.
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        tilt
      </code>
    </td>
    
    <td>
      <code>
        number
      </code>
    </td>
    
    <td>
      <code>
        0
      </code>
    </td>
    
    <td>
      Turns the beam by this many degrees.
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        ray-sharpness
      </code>
    </td>
    
    <td>
      <code>
        number
      </code>
    </td>
    
    <td>
      <code>
        0.35
      </code>
    </td>
    
    <td>
      How crisp the edges of the shafts are, from 0 to 1.
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        glow
      </code>
    </td>
    
    <td>
      <code>
        number
      </code>
    </td>
    
    <td>
      <code>
        0.6
      </code>
    </td>
    
    <td>
      Brightness of the glow around the light source.
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        haze
      </code>
    </td>
    
    <td>
      <code>
        number
      </code>
    </td>
    
    <td>
      <code>
        0.25
      </code>
    </td>
    
    <td>
      Drifting haze that breaks the shafts up, like dust in the air, from 0 to 1.
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        atmosphere
      </code>
    </td>
    
    <td>
      <code>
        number
      </code>
    </td>
    
    <td>
      <code>
        1
      </code>
    </td>
    
    <td>
      How much the light cools toward blue as it travels away from the source, from 0 to 1.
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        intensity
      </code>
    </td>
    
    <td>
      <code>
        number
      </code>
    </td>
    
    <td>
      <code>
        1
      </code>
    </td>
    
    <td>
      Overall brightness of the light.
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        pulsating
      </code>
    </td>
    
    <td>
      <code>
        boolean
      </code>
    </td>
    
    <td>
      <code>
        false
      </code>
    </td>
    
    <td>
      The rays slowly breathe brighter and dimmer.
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        fade-distance
      </code>
    </td>
    
    <td>
      <code>
        number
      </code>
    </td>
    
    <td>
      <code>
        1
      </code>
    </td>
    
    <td>
      How far the rays travel before they dim, in container widths.
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        saturation
      </code>
    </td>
    
    <td>
      <code>
        number
      </code>
    </td>
    
    <td>
      <code>
        1
      </code>
    </td>
    
    <td>
      Color saturation of the light.
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        follow-mouse
      </code>
    </td>
    
    <td>
      <code>
        boolean
      </code>
    </td>
    
    <td>
      <code>
        true
      </code>
    </td>
    
    <td>
      The beam turns toward the cursor.
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        mouse-influence
      </code>
    </td>
    
    <td>
      <code>
        number
      </code>
    </td>
    
    <td>
      <code>
        0.1
      </code>
    </td>
    
    <td>
      How far the beam turns toward the cursor, from 0 to 1.
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        cursor-shadow
      </code>
    </td>
    
    <td>
      <code>
        boolean
      </code>
    </td>
    
    <td>
      <code>
        true
      </code>
    </td>
    
    <td>
      The cursor blocks the light and casts a soft shadow down the rays.
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        click-pulse
      </code>
    </td>
    
    <td>
      <code>
        boolean
      </code>
    </td>
    
    <td>
      <code>
        true
      </code>
    </td>
    
    <td>
      Clicking sends a wave of light down the rays.
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        noise-amount
      </code>
    </td>
    
    <td>
      <code>
        number
      </code>
    </td>
    
    <td>
      <code>
        0
      </code>
    </td>
    
    <td>
      Film grain over the rays, from 0 to 1.
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        distortion
      </code>
    </td>
    
    <td>
      <code>
        number
      </code>
    </td>
    
    <td>
      <code>
        0
      </code>
    </td>
    
    <td>
      Makes the rays waver as if seen through heat.
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        intro
      </code>
    </td>
    
    <td>
      <code>
        boolean
      </code>
    </td>
    
    <td>
      <code>
        true
      </code>
    </td>
    
    <td>
      The rays grow out from the source on mount.
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        light-mode
      </code>
    </td>
    
    <td>
      <code>
        boolean
      </code>
    </td>
    
    <td>
      <code>
        false
      </code>
    </td>
    
    <td>
      Prints the light as soft colored ink so it sits on light pages.
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        opacity
      </code>
    </td>
    
    <td>
      <code>
        number
      </code>
    </td>
    
    <td>
      <code>
        1
      </code>
    </td>
    
    <td>
      Overall opacity, from 0 to 1.
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        max-device-pixel-ratio
      </code>
    </td>
    
    <td>
      <code>
        number
      </code>
    </td>
    
    <td>
      <code>
        2
      </code>
    </td>
    
    <td>
      Highest pixel ratio the canvas renders at.
    </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"`) and the container has `pointer-events: none`, so it never blocks content placed above it. Pointer tracking listens on the window.
- With `prefers-reduced-motion: reduce`, the intro, cursor shadow and click waves are skipped and the rays drift at 35% speed.
- Rendering pauses when the component is offscreen, the tab is hidden, or nothing is moving (`rays-speed` 0 and the pointer at rest).
- A lost WebGL context is restored automatically.
- Ported from [React Bits](https://reactbits.dev/backgrounds/light-rays) by David Haz.
