# Slide Commit

> Slide-to-confirm handle that spins while your action runs, then unfurls into a done pill or shakes back on failure.

Drag the handle to the end of the track to confirm. The handle stretches as it travels and squashes if you push it back past the start. Return a promise from `on-confirm` and the handle shows a spinner until it settles. Success unfurls a done pill; a failure shakes the track, turns the handle red and springs it home.

<demo-slide-commit>



</demo-slide-commit>

## Installation

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

## Usage

```vue
<script setup lang="ts">
  import SlideCommit from '~/components/ui/slide-commit/SlideCommit.vue';

  function pay() {
    return fetch('/api/pay', { method: 'POST' });
  }
</script>

<template>
  <SlideCommit
    label="Slide to pay"
    done-label="Paid"
    error-label="Payment failed"
    :on-confirm="pay"
    @done="console.log('paid')"
  />
</template>
```

## Props

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

<tbody>
  <tr>
    <td>
      <code>
        label
      </code>
    </td>
    
    <td>
      <code>
        string
      </code>
    </td>
    
    <td>
      <code>
        'Slide to pay'
      </code>
    </td>
    
    <td>
      Track text, and the accessible name.
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        done-label
      </code>
    </td>
    
    <td>
      <code>
        string
      </code>
    </td>
    
    <td>
      <code>
        'Paid'
      </code>
    </td>
    
    <td>
      Pill text after success.
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        error-label
      </code>
    </td>
    
    <td>
      <code>
        string
      </code>
    </td>
    
    <td>
      <code>
        'Payment failed'
      </code>
    </td>
    
    <td>
      Track text after a failure.
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        on-confirm
      </code>
    </td>
    
    <td>
      <code>
        () => unknown
      </code>
    </td>
    
    <td>
      —
    </td>
    
    <td>
      Runs when the handle reaches the end. Return a promise to spin until it settles. A rejection or a throw fails.
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        track-color
      </code>
    </td>
    
    <td>
      <code>
        string
      </code>
    </td>
    
    <td>
      <code>
        '#262626'
      </code>
    </td>
    
    <td>
      Track fill.
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        handle-color
      </code>
    </td>
    
    <td>
      <code>
        string
      </code>
    </td>
    
    <td>
      <code>
        '#f5f5f5'
      </code>
    </td>
    
    <td>
      Handle fill. Text on it picks black or white for contrast.
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        success-color
      </code>
    </td>
    
    <td>
      <code>
        string
      </code>
    </td>
    
    <td>
      <code>
        '#22c55e'
      </code>
    </td>
    
    <td>
      Pill fill on success.
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        danger-color
      </code>
    </td>
    
    <td>
      <code>
        string
      </code>
    </td>
    
    <td>
      <code>
        '#e5484d'
      </code>
    </td>
    
    <td>
      Handle fill and error text on failure.
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        width
      </code>
    </td>
    
    <td>
      <code>
        number
      </code>
    </td>
    
    <td>
      <code>
        280
      </code>
    </td>
    
    <td>
      Width in pixels.
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        height
      </code>
    </td>
    
    <td>
      <code>
        number
      </code>
    </td>
    
    <td>
      <code>
        56
      </code>
    </td>
    
    <td>
      Height in pixels.
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        radius
      </code>
    </td>
    
    <td>
      <code>
        number
      </code>
    </td>
    
    <td>
      <code>
        28
      </code>
    </td>
    
    <td>
      Corner radius in pixels, capped at half the height.
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        speed
      </code>
    </td>
    
    <td>
      <code>
        number
      </code>
    </td>
    
    <td>
      <code>
        50
      </code>
    </td>
    
    <td>
      How quickly the handle travels on its springs, 0 to 100.
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        return-bounce
      </code>
    </td>
    
    <td>
      <code>
        number
      </code>
    </td>
    
    <td>
      <code>
        0.38
      </code>
    </td>
    
    <td>
      Bounce when the handle springs back home.
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        landing-dip
      </code>
    </td>
    
    <td>
      <code>
        number
      </code>
    </td>
    
    <td>
      <code>
        0.026
      </code>
    </td>
    
    <td>
      How far the track dips when the pill lands. <code>
        0
      </code>
      
       turns it off.
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        hold-ms
      </code>
    </td>
    
    <td>
      <code>
        number
      </code>
    </td>
    
    <td>
      <code>
        1500
      </code>
    </td>
    
    <td>
      How long the done pill stays before it resets, in ms. <code>
        0
      </code>
      
       keeps it.
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        disabled
      </code>
    </td>
    
    <td>
      <code>
        boolean
      </code>
    </td>
    
    <td>
      <code>
        false
      </code>
    </td>
    
    <td>
      Dims the slider and ignores input.
    </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>
        done
      </code>
      
       event
    </td>
    
    <td>
      —
    </td>
    
    <td>
      Fires when the action succeeds.
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        error
      </code>
      
       event
    </td>
    
    <td>
      <code>
        reason: unknown
      </code>
    </td>
    
    <td>
      Fires when <code>
        on-confirm
      </code>
      
       throws or rejects.
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        #icon
      </code>
      
       slot
    </td>
    
    <td>
      —
    </td>
    
    <td>
      Replaces the arrow on the handle.
    </td>
  </tr>
</tbody>
</table>

## Accessibility

- The handle is a focusable `role="slider"` that reports progress as 0 to 100 percent.
- Arrow Right or Up moves it a tenth of the way, and reaching the end confirms. End confirms at once. Arrow Left or Down moves back. Home or Escape returns it.
- While the action runs the handle sets `aria-busy`, and a polite live region announces Working, the done label, or the error label.
- With reduced motion, springs become short eases, the shake is skipped and the spinner breathes instead of turning.
- Ported from [React Bits](https://reactbits.dev/micro/slide-commit) by David Haz.
