# Glare Hover

> A glossy light streak that sweeps across any element in the direction the cursor moves.

Wrap any element to give it a glossy glare. On hover the light enters from the side the pointer came in and sweeps out the other way when it leaves, while a thin rim glint catches the edge. Switch the mode to make the glare follow the cursor, shine on a timer, or sweep on click.

<demo-glare-hover>



</demo-glare-hover>

## Installation

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

## Usage

```vue
<script setup lang="ts">
  import GlareHover from '~/components/ui/glare-hover/GlareHover.vue';
</script>

<template>
  <GlareHover
    width="min(360px, 82vw)"
    border-radius="20px"
    variant="twin"
    :glare-angle="-60"
  >
    <img src="/sky.webp" alt="" class="block aspect-3/2 w-full object-cover" />
  </GlareHover>

  <GlareHover mode="loop" :interval="2.5" :glare-size="16" border-radius="12px">
    <button class="px-6 py-3">Get started</button>
  </GlareHover>
</template>
```

The glare is a rotated band painted with a 33-stop gradient, moved with transforms in one `requestAnimationFrame` loop that only runs while the light is moving.

## Props

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

<tbody>
  <tr>
    <td>
      <code>
        mode
      </code>
    </td>
    
    <td>
      <code>
        'hover' | 'follow' | 'loop' | 'click'
      </code>
    </td>
    
    <td>
      <code>
        'hover'
      </code>
    </td>
    
    <td>
      Sweep on hover, follow the cursor, shine on a timer, or sweep on click.
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        variant
      </code>
    </td>
    
    <td>
      <code>
        'streak' | 'twin' | 'sheen'
      </code>
    </td>
    
    <td>
      <code>
        'streak'
      </code>
    </td>
    
    <td>
      One bright streak, a double streak like glass, or a soft wide sheen.
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        glare-color
      </code>
    </td>
    
    <td>
      <code>
        string
      </code>
    </td>
    
    <td>
      <code>
        '#ffffff'
      </code>
    </td>
    
    <td>
      Color of the glare.
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        glare-opacity
      </code>
    </td>
    
    <td>
      <code>
        number
      </code>
    </td>
    
    <td>
      <code>
        0.5
      </code>
    </td>
    
    <td>
      Peak opacity of the glare, 0–1.
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        glare-angle
      </code>
    </td>
    
    <td>
      <code>
        number
      </code>
    </td>
    
    <td>
      <code>
        -45
      </code>
    </td>
    
    <td>
      Direction the glare travels, in degrees.
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        glare-size
      </code>
    </td>
    
    <td>
      <code>
        number
      </code>
    </td>
    
    <td>
      <code>
        30
      </code>
    </td>
    
    <td>
      Width of the glare as a percentage of the element's diagonal.
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        softness
      </code>
    </td>
    
    <td>
      <code>
        number
      </code>
    </td>
    
    <td>
      <code>
        0.6
      </code>
    </td>
    
    <td>
      How soft the edges of the glare are, 0–1.
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        blend-mode
      </code>
    </td>
    
    <td>
      <code>
        'screen' | 'normal' | 'overlay' | 'soft-light'
      </code>
    </td>
    
    <td>
      <code>
        'screen'
      </code>
    </td>
    
    <td>
      How the glare mixes with the content.
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        rim-glint
      </code>
    </td>
    
    <td>
      <code>
        boolean
      </code>
    </td>
    
    <td>
      <code>
        true
      </code>
    </td>
    
    <td>
      Lets the edge catch the light where the glare crosses it.
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        transition-duration
      </code>
    </td>
    
    <td>
      <code>
        number
      </code>
    </td>
    
    <td>
      <code>
        650
      </code>
    </td>
    
    <td>
      How long one sweep takes, in milliseconds.
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        interval
      </code>
    </td>
    
    <td>
      <code>
        number
      </code>
    </td>
    
    <td>
      <code>
        3
      </code>
    </td>
    
    <td>
      Seconds between sweeps in loop mode.
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        play-once
      </code>
    </td>
    
    <td>
      <code>
        boolean
      </code>
    </td>
    
    <td>
      <code>
        false
      </code>
    </td>
    
    <td>
      In hover mode, sweeps only on the way in instead of again on the way out.
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        intro
      </code>
    </td>
    
    <td>
      <code>
        boolean
      </code>
    </td>
    
    <td>
      <code>
        false
      </code>
    </td>
    
    <td>
      Sweeps once when the element first scrolls into view.
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        width
      </code>
    </td>
    
    <td>
      <code>
        string
      </code>
    </td>
    
    <td>
      <code>
        'auto'
      </code>
    </td>
    
    <td>
      CSS width of the wrapper.
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        height
      </code>
    </td>
    
    <td>
      <code>
        string
      </code>
    </td>
    
    <td>
      <code>
        'auto'
      </code>
    </td>
    
    <td>
      CSS height of the wrapper.
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        background
      </code>
    </td>
    
    <td>
      <code>
        string
      </code>
    </td>
    
    <td>
      <code>
        'transparent'
      </code>
    </td>
    
    <td>
      CSS background of the wrapper.
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        border-radius
      </code>
    </td>
    
    <td>
      <code>
        string
      </code>
    </td>
    
    <td>
      <code>
        '10px'
      </code>
    </td>
    
    <td>
      CSS border radius of the wrapper.
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        border-color
      </code>
    </td>
    
    <td>
      <code>
        string
      </code>
    </td>
    
    <td>
      <code>
        'transparent'
      </code>
    </td>
    
    <td>
      Color of the 1px border.
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        class
      </code>
    </td>
    
    <td>
      <code>
        string
      </code>
    </td>
    
    <td>
      <code>
        ''
      </code>
    </td>
    
    <td>
      Extra classes for the wrapper.
    </td>
  </tr>
</tbody>
</table>

## Slots

<table>
<thead>
  <tr>
    <th>
      Slot
    </th>
    
    <th>
      Description
    </th>
  </tr>
</thead>

<tbody>
  <tr>
    <td>
      <code>
        default
      </code>
    </td>
    
    <td>
      Content the glare sweeps across.
    </td>
  </tr>
</tbody>
</table>

## Accessibility

- The glare layer is `aria-hidden` and `pointer-events: none`, so it never blocks clicks or focus.
- Keyboard focus (`:focus-visible`) inside the wrapper also triggers a sweep.
- With `prefers-reduced-motion: reduce` no sweeps run and loop mode stops.
- Ported from [React Bits](https://reactbits.dev/animations/glare-hover) by David Haz.
