# Hold Button

> Hold-to-confirm button whose liquid fill rises while pressed and snaps back if you let go.

A press-and-hold confirm button. Hold it with the mouse, a finger, Space or Enter: a liquid fill with a moving wave crest sweeps across at constant speed, the glow charges, and when the fill completes the label blurs into the done state and `hold` fires. Let go early, drag away or press Escape and the fill snaps back.

<demo-hold-button>



</demo-hold-button>

## Installation

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

## Usage

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

  function onHold() {
    console.log('confirmed');
  }
</script>

<template>
  <HoldButton
    icon="lucide:trash-2"
    done-icon="lucide:check"
    done-label="Deleted"
    fill-color="#5227FF"
    :hold-time="2000"
    @hold="onHold"
  >
    Hold to delete
  </HoldButton>
</template>
```

## Props

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

<tbody>
  <tr>
    <td>
      <code>
        done-label
      </code>
    </td>
    
    <td>
      <code>
        string
      </code>
    </td>
    
    <td>
      <code>
        'Deleted'
      </code>
    </td>
    
    <td>
      Label that blurs in when the hold completes
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        icon
      </code>
    </td>
    
    <td>
      <code>
        string
      </code>
    </td>
    
    <td>
      —
    </td>
    
    <td>
      Iconify name shown before the idle label
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        done-icon
      </code>
    </td>
    
    <td>
      <code>
        string
      </code>
    </td>
    
    <td>
      —
    </td>
    
    <td>
      Iconify name shown before the done label
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        background-color
      </code>
    </td>
    
    <td>
      <code>
        string
      </code>
    </td>
    
    <td>
      <code>
        '#27272a'
      </code>
    </td>
    
    <td>
      Button body colour
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        fill-color
      </code>
    </td>
    
    <td>
      <code>
        string
      </code>
    </td>
    
    <td>
      <code>
        '#5227FF'
      </code>
    </td>
    
    <td>
      Colour of the fill, its wave, the glow and the focus ring
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        text-color
      </code>
    </td>
    
    <td>
      <code>
        string
      </code>
    </td>
    
    <td>
      <code>
        '#f5f5f5'
      </code>
    </td>
    
    <td>
      Label colour outside the fill
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        fill-text-color
      </code>
    </td>
    
    <td>
      <code>
        string
      </code>
    </td>
    
    <td>
      <code>
        '#ffffff'
      </code>
    </td>
    
    <td>
      Label colour inside the fill; the ink inverts as the edge moves
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        size
      </code>
    </td>
    
    <td>
      <code>
        'sm' | 'md' | 'lg'
      </code>
    </td>
    
    <td>
      <code>
        'md'
      </code>
    </td>
    
    <td>
      Height, padding and font size preset
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        radius
      </code>
    </td>
    
    <td>
      <code>
        number
      </code>
    </td>
    
    <td>
      <code>
        14
      </code>
    </td>
    
    <td>
      Corner radius in pixels
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        fill-direction
      </code>
    </td>
    
    <td>
      <code>
        'right' | 'up'
      </code>
    </td>
    
    <td>
      <code>
        'right'
      </code>
    </td>
    
    <td>
      Sweep left to right, or rise from the bottom
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        hold-time
      </code>
    </td>
    
    <td>
      <code>
        number
      </code>
    </td>
    
    <td>
      <code>
        2000
      </code>
    </td>
    
    <td>
      How long the press must last, in ms
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        release-time
      </code>
    </td>
    
    <td>
      <code>
        number
      </code>
    </td>
    
    <td>
      <code>
        200
      </code>
    </td>
    
    <td>
      How fast the fill snaps back on early release or reset, in ms
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        press-scale
      </code>
    </td>
    
    <td>
      <code>
        number
      </code>
    </td>
    
    <td>
      <code>
        0.97
      </code>
    </td>
    
    <td>
      Squash while a pointer holds it. <code>
        1
      </code>
      
       disables it
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        wave
      </code>
    </td>
    
    <td>
      <code>
        boolean
      </code>
    </td>
    
    <td>
      <code>
        true
      </code>
    </td>
    
    <td>
      Scrolling meniscus on the leading edge of the fill
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        wave-amplitude
      </code>
    </td>
    
    <td>
      <code>
        number
      </code>
    </td>
    
    <td>
      <code>
        6
      </code>
    </td>
    
    <td>
      Height of the wave crests in pixels
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        glow
      </code>
    </td>
    
    <td>
      <code>
        boolean
      </code>
    </td>
    
    <td>
      <code>
        true
      </code>
    </td>
    
    <td>
      Glow that charges with the hold and pulses on completion
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        reset-after
      </code>
    </td>
    
    <td>
      <code>
        number
      </code>
    </td>
    
    <td>
      <code>
        1200
      </code>
    </td>
    
    <td>
      Ms the done state stays before resetting. <code>
        0
      </code>
      
       keeps it done
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        disabled
      </code>
    </td>
    
    <td>
      <code>
        boolean
      </code>
    </td>
    
    <td>
      <code>
        false
      </code>
    </td>
    
    <td>
      Dims the button 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 button
    </td>
  </tr>
</tbody>
</table>

## Events

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

<tbody>
  <tr>
    <td>
      <code>
        hold
      </code>
    </td>
    
    <td>
      —
    </td>
    
    <td>
      Fired once, on the frame the fill completes
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        tap
      </code>
    </td>
    
    <td>
      —
    </td>
    
    <td>
      Fired on a release under 250ms that did not drift off
    </td>
  </tr>
</tbody>
</table>

## Slots

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

<tbody>
  <tr>
    <td>
      <code>
        default
      </code>
    </td>
    
    <td>
      Idle label (defaults to “Hold to delete”)
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        done
      </code>
    </td>
    
    <td>
      Done label; overrides <code>
        done-label
      </code>
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        icon
      </code>
    </td>
    
    <td>
      Idle icon; overrides the <code>
        icon
      </code>
      
       prop
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        done-icon
      </code>
    </td>
    
    <td>
      Done icon; overrides the <code>
        done-icon
      </code>
      
       prop
    </td>
  </tr>
</tbody>
</table>

## Accessibility

- Native `<button>`; Space and Enter start the hold, releasing the key ends it and Escape cancels a keyboard hold.
- A visually hidden hint (“Press and hold for 2 seconds to confirm”) is linked with `aria-describedby`.
- The hold cancels if the window loses focus or the tab is hidden.
- With `prefers-reduced-motion`, the sweep, wave and pulse are replaced by a plain cross-fade of the fill.
- Ported from [React Bits](https://reactbits.dev/micro/hold-button) by David Haz.
