# Sling Button

> Send button you pull back like a slingshot and release to fire, with a stretching band, a power arc and a particle burst.

Pull the pad away from its seat. A band stretches behind it and an arc fills to show the load. Past the arm distance, let go and the pad snaps back through its seat and throws a burst of particles. A short pull springs back without sending. A plain tap, Enter or Space also sends.

<demo-sling-button>



</demo-sling-button>

## Installation

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

## Usage

```vue
<script setup lang="ts">
  import SlingButton from '~/components/ui/sling-button/SlingButton.vue';

  function send() {
    console.log('sent');
  }
</script>

<template>
  <SlingButton :arm-at="48" :max-pull="160" :particles="14" @send="send" />
</template>
```

## Props

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

<tbody>
  <tr>
    <td>
      <code>
        pad-color
      </code>
    </td>
    
    <td>
      <code>
        string
      </code>
    </td>
    
    <td>
      <code>
        '#f5f5f5'
      </code>
    </td>
    
    <td>
      The pad fill.
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        icon-color
      </code>
    </td>
    
    <td>
      <code>
        string
      </code>
    </td>
    
    <td>
      <code>
        '#18181b'
      </code>
    </td>
    
    <td>
      The pad content colour.
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        accent-color
      </code>
    </td>
    
    <td>
      <code>
        string
      </code>
    </td>
    
    <td>
      <code>
        '#f5f5f5'
      </code>
    </td>
    
    <td>
      The power arc, the loaded band and the particles.
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        well-color
      </code>
    </td>
    
    <td>
      <code>
        string
      </code>
    </td>
    
    <td>
      <code>
        '#27272a'
      </code>
    </td>
    
    <td>
      The seat the pad rests in.
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        band-color
      </code>
    </td>
    
    <td>
      <code>
        string
      </code>
    </td>
    
    <td>
      <code>
        '#52525b'
      </code>
    </td>
    
    <td>
      The band before it loads.
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        size
      </code>
    </td>
    
    <td>
      <code>
        number
      </code>
    </td>
    
    <td>
      <code>
        56
      </code>
    </td>
    
    <td>
      Pad diameter in pixels. Seat, hit area and particles follow.
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        stroke-width
      </code>
    </td>
    
    <td>
      <code>
        number
      </code>
    </td>
    
    <td>
      <code>
        3
      </code>
    </td>
    
    <td>
      Arc and band thickness in pixels.
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        arm-at
      </code>
    </td>
    
    <td>
      <code>
        number
      </code>
    </td>
    
    <td>
      <code>
        48
      </code>
    </td>
    
    <td>
      Pull distance in pixels that loads the send.
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        max-pull
      </code>
    </td>
    
    <td>
      <code>
        number
      </code>
    </td>
    
    <td>
      <code>
        160
      </code>
    </td>
    
    <td>
      How far the band can stretch before it stops giving.
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        launch-speed
      </code>
    </td>
    
    <td>
      <code>
        number
      </code>
    </td>
    
    <td>
      <code>
        2600
      </code>
    </td>
    
    <td>
      Speed the band adds on release, in px/s.
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        recoil
      </code>
    </td>
    
    <td>
      <code>
        number
      </code>
    </td>
    
    <td>
      <code>
        0.2
      </code>
    </td>
    
    <td>
      Bounce of the return spring. <code>
        0
      </code>
      
       stops dead.
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        flight
      </code>
    </td>
    
    <td>
      <code>
        number
      </code>
    </td>
    
    <td>
      <code>
        120
      </code>
    </td>
    
    <td>
      How far the lead particle flies, in pixels.
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        particles
      </code>
    </td>
    
    <td>
      <code>
        number
      </code>
    </td>
    
    <td>
      <code>
        14
      </code>
    </td>
    
    <td>
      How many particles a launch throws. <code>
        1
      </code>
      
       is one dot, <code>
        0
      </code>
      
       is none.
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        spread
      </code>
    </td>
    
    <td>
      <code>
        number
      </code>
    </td>
    
    <td>
      <code>
        60
      </code>
    </td>
    
    <td>
      The cone the burst fans across, in degrees.
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        axis
      </code>
    </td>
    
    <td>
      <code>
        'any' | 'horizontal' | 'vertical'
      </code>
    </td>
    
    <td>
      <code>
        'any'
      </code>
    </td>
    
    <td>
      Free pull, or one axis with a little give across it.
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        tap-sends
      </code>
    </td>
    
    <td>
      <code>
        boolean
      </code>
    </td>
    
    <td>
      <code>
        true
      </code>
    </td>
    
    <td>
      Whether a plain tap sends. Enter always does.
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        disabled
      </code>
    </td>
    
    <td>
      <code>
        boolean
      </code>
    </td>
    
    <td>
      <code>
        false
      </code>
    </td>
    
    <td>
      Dims the pad and ignores input.
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        aria-label
      </code>
    </td>
    
    <td>
      <code>
        string
      </code>
    </td>
    
    <td>
      <code>
        'Send'
      </code>
    </td>
    
    <td>
      Accessible name of the button.
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        class
      </code>
    </td>
    
    <td>
      <code>
        string
      </code>
    </td>
    
    <td>
      <code>
        ''
      </code>
    </td>
    
    <td>
      Extra classes for the root element.
    </td>
  </tr>
</tbody>
</table>

## Events and slots

<table>
<thead>
  <tr>
    <th>
      Name
    </th>
    
    <th>
      Payload
    </th>
    
    <th>
      Description
    </th>
  </tr>
</thead>

<tbody>
  <tr>
    <td>
      <code>
        send
      </code>
      
       event
    </td>
    
    <td>
      —
    </td>
    
    <td>
      Fires on a loaded release, on a tap when <code>
        tap-sends
      </code>
      
       is on, and on Enter or Space.
    </td>
  </tr>
  
  <tr>
    <td>
      default slot
    </td>
    
    <td>
      —
    </td>
    
    <td>
      Replaces the pad content. The default is an up arrow.
    </td>
  </tr>
</tbody>
</table>

## Accessibility

- The pad is a native `button`, so Enter and Space send.
- A visually hidden hint is linked with `aria-describedby`.
- Escape during a drag cancels it without sending.
- `disabled` sets `aria-disabled` and ignores input.
- With reduced motion, the band fades out instead of springing, and the seat flashes instead of throwing particles.
- Ported from [React Bits](https://reactbits.dev/micro/sling-button) by David Haz.
