zeroUI

Hold button

A hold-to-confirm button for React: a fill runs across it along the slant while it is held, for what should not happen by accident.

Install

terminal
# once per project: where @zeroui items come frompnpm dlx shadcn@latest registry add @zeroui=https://zeroui.catforest.dev/r/{name}.jsonpnpm dlx shadcn@latest add @zeroui/hold-button

Examples

Hold to scrap

Crates scrapped: 0

hold-button-scrap.tsx
import { useState } from "react";import { HoldButton } from "@/components/zero/hold-button";import { Kbd } from "@/components/zero/kbd";export default function HoldButtonScrap() {  const [scrapped, setScrapped] = useState(0);  return (    <div className="grid justify-items-start gap-4">      <div className="flex flex-wrap gap-3">        <HoldButton hotkey="x" onConfirm={() => setScrapped((n) => n + 1)}>          <Kbd>X</Kbd> Hold to scrap        </HoldButton>        <HoldButton variant="danger" duration={2000}>          Abandon the run        </HoldButton>      </div>      <p className="font-medium font-zero-text text-zero-sm text-zero-text-2">        Crates scrapped: <span className="text-zero-text">{scrapped}</span>      </p>    </div>  );}

Behaviour

Hold it with the pointer, Enter or Space, or its hotkey from anywhere on the page (not while typing in a field). Let go early and the fill drains back; hold it to the end and onConfirm fires and the button flashes the accent. The fill keeps its pace under reduced motion: it tells you how long to hold.

It is a Button with every Button variant and size, secondary by default. Screen readers are told to press and hold. Put a Kbd inside to show the key.

Props

HoldButton

PropTypeDefaultDescription
onConfirm() => void—Fired once the hold is complete.
durationnumber1200How long to hold, in ms.
hotkeystring—A key (KeyboardEvent.key) that holds it from anywhere.
variant / size / cutButton's"secondary"As Button.