# Crosshair

> Crosshair cursor with live coordinates that locks onto links and buttons and measures them.

Two canvas-drawn lines follow the pointer with live x and y readouts at the edges. Hover a link, button or any `[data-crosshair-target]` element and the crosshair locks onto it with measuring brackets and its size; click to send out a pulse ring.

<demo-crosshair>



</demo-crosshair>

## Installation

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

## Usage

```vue
<script setup lang="ts">
  import { useTemplateRef } from 'vue';
  import Crosshair from '~/components/ui/crosshair/Crosshair.vue';

  const stage = useTemplateRef<HTMLElement>('stage');
</script>

<template>
  <!-- Scoped to one section: the container needs a non-static position -->
  <section ref="stage" class="relative h-110 overflow-hidden">
    <Crosshair :container="stage" target-effect="lock" :smoothing="0.35" />
    <h2 data-crosshair-target>Built to the pixel</h2>
    <button type="button">Get started</button>
  </section>

  <!-- Or across the whole viewport -->
  <Crosshair
    color="#22d3ee"
    line-style="dashed"
    blend-mode="difference"
    hide-cursor
  />
</template>
```

## Props

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

<tbody>
  <tr>
    <td>
      <code>
        color
      </code>
    </td>
    
    <td>
      <code>
        string
      </code>
    </td>
    
    <td>
      <code>
        '#ffffff'
      </code>
    </td>
    
    <td>
      Color of the lines, labels and brackets.
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        container
      </code>
    </td>
    
    <td>
      <code>
        HTMLElement | null
      </code>
    </td>
    
    <td>
      <code>
        null
      </code>
    </td>
    
    <td>
      Keeps the crosshair inside this element (needs a non-static position). Without it, it covers the viewport.
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        thickness
      </code>
    </td>
    
    <td>
      <code>
        number
      </code>
    </td>
    
    <td>
      <code>
        1
      </code>
    </td>
    
    <td>
      Line thickness in px.
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        opacity
      </code>
    </td>
    
    <td>
      <code>
        number
      </code>
    </td>
    
    <td>
      <code>
        0.85
      </code>
    </td>
    
    <td>
      Opacity of everything the crosshair draws.
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        line-style
      </code>
    </td>
    
    <td>
      <code>
        'solid' | 'dashed' | 'dotted'
      </code>
    </td>
    
    <td>
      <code>
        'solid'
      </code>
    </td>
    
    <td>
      Stroke style of the two lines.
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        gap
      </code>
    </td>
    
    <td>
      <code>
        number
      </code>
    </td>
    
    <td>
      <code>
        0
      </code>
    </td>
    
    <td>
      Empty space in px around the pointer where the lines would cross.
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        fade
      </code>
    </td>
    
    <td>
      <code>
        number
      </code>
    </td>
    
    <td>
      <code>
        0
      </code>
    </td>
    
    <td>
      How much the lines fade toward the edges, from 0 to 1.
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        smoothing
      </code>
    </td>
    
    <td>
      <code>
        number
      </code>
    </td>
    
    <td>
      <code>
        0.35
      </code>
    </td>
    
    <td>
      How far the lines trail behind the pointer. 0 sticks to it.
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        show-coordinates
      </code>
    </td>
    
    <td>
      <code>
        boolean
      </code>
    </td>
    
    <td>
      <code>
        true
      </code>
    </td>
    
    <td>
      Shows the pointer position at the edges and the size of a locked target.
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        target-effect
      </code>
    </td>
    
    <td>
      <code>
        'lock' | 'glitch' | 'none'
      </code>
    </td>
    
    <td>
      <code>
        'lock'
      </code>
    </td>
    
    <td>
      Lock frames a target with corner brackets and measures it; glitch shakes the lines like a bad signal.
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        target-selector
      </code>
    </td>
    
    <td>
      <code>
        string
      </code>
    </td>
    
    <td>
      <code>
        'a, button, [data-crosshair-target]'
      </code>
    </td>
    
    <td>
      CSS selector for the elements the crosshair reacts to.
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        click-pulse
      </code>
    </td>
    
    <td>
      <code>
        boolean
      </code>
    </td>
    
    <td>
      <code>
        true
      </code>
    </td>
    
    <td>
      Sends a ring out from the pointer on every click or tap.
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        hide-cursor
      </code>
    </td>
    
    <td>
      <code>
        boolean
      </code>
    </td>
    
    <td>
      <code>
        false
      </code>
    </td>
    
    <td>
      Hides the system cursor inside the area and marks the pointer with a dot instead.
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        blend-mode
      </code>
    </td>
    
    <td>
      <code>
        'normal' | 'difference'
      </code>
    </td>
    
    <td>
      <code>
        'normal'
      </code>
    </td>
    
    <td>
      Difference inverts whatever is under the lines so they stay visible on any background.
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        class
      </code>
    </td>
    
    <td>
      <code>
        string
      </code>
    </td>
    
    <td>
      <code>
        ''
      </code>
    </td>
    
    <td>
      Extra classes for the canvas.
    </td>
  </tr>
</tbody>
</table>

## Accessibility

- The overlay is a decorative `<canvas aria-hidden="true">` with `pointer-events: none`, so it never blocks clicks, focus or text selection.
- `hide-cursor` only hides the system cursor while the pointer is inside the area and always draws a replacement dot; leave it off for general content.
- With `prefers-reduced-motion: reduce` the lines snap to the pointer with no easing, and glitch shake and click rings are off.
- The render loop only runs while something is moving and stops when the pointer leaves.
- Ported from [React Bits](https://reactbits.dev/animations/crosshair) by David Haz.
