Slide to confirm

Pro

A slide-to-confirm control. The thumb pulls a liquid fill behind it and makes the track swell. It snaps back on a spring if released early. Past the threshold, the track draws into the thumb and the chevron morphs into a success check, with pending and error states.

Live · keyboard ready

Emily Parker

Concert tickets

$240.00

From
Everyday debit ··4821
Arrives
Instantly
Drag the handle to the end, or hold Space or Enter.

Demo transfer. No money moves.

  • A checkout, transfer, or unlock step on a phone first surface, where a deliberate horizontal gesture prevents accidental taps.
  • A kiosk or field app action that needs a confirming gesture without a dialog.
  • Use hold-to-confirm for destructive actions on desktop surfaces where a press and hold is more natural.
  • Use a dialog when people need to read the consequences before confirming.
  • Use a regular button for routine, easily undone actions.

Installation

Pro source and install commands unlock with a Pro plan.

example.tsx
import { SlideToConfirm } from "@/components/arc/slide-to-confirm/slide-to-confirm"; export function SendMoney({ amount, send }: { amount: string; send: () => Promise<void> }) {  return <SlideToConfirm    label={`Slide to send ${amount}`}    pendingLabel="Sending"    confirmedLabel="Sent"    errorLabel="Not sent, slide to retry"    onConfirm={send}  />;}

SlideToConfirm

A slide to confirm control for payments, transfers, and other deliberate actions. The thumb pulls a liquid fill behind it: the fill lags, necks down between the thumb and its tail, and catches up, while the track swells around the pressed thumb. Pulling past the end stretches the track like a rubber band. Letting go early snaps the thumb back against a spring. Letting go past the threshold confirms: the track draws into the thumb, a spinner shows while a returned promise is pending, and the arrow morphs into a success check with the confirmed label beside it.

PropTypeDefaultDescription
labelstring"Slide to pay"The instruction and the action, drawn in the track and used as the slider name, for example “Slide to send $240”.
confirmedLabelstring"Paid"Shown beside the check and announced once the action succeeds.
pendingLabelstring"Processing"Shown beside the spinner and announced while a promise returned from onConfirm is pending.
errorLabelstring"Payment failed, slide to retry"Replaces the label in the danger color after the promise rejects, until the next slide.
onConfirm() => void | Promise<unknown>–Called once when the slide completes. Return a promise to show the pending, success, and error states; return nothing to go straight to success.
thresholdnumber0.9Fraction of the track the thumb must pass before letting go confirms. Below it the thumb springs back.
resetAfternumber–Milliseconds after success before the control expands back to its idle state. Leave it out to stay confirmed.
hintbooleantrueNudges the thumb a little every few seconds while idle and untouched, so people see that it moves. Off with reduced motion.
disabledbooleanfalseDims the control and ignores pointer and keyboard input.
accentstring–Color of the liquid fill. Defaults to the slider fill token, which follows the selected accent.
classNamestring–Extra class on the root element.
styleCSSProperties–Inline styles on the root element.
  • The control is a real role="slider" named by label, with aria-valuenow and aria-valuetext kept in step with the thumb, and a description that explains the gesture.
  • Arrow keys move the thumb in tenths, Page Up and Page Down in quarters, Home returns it, and End confirms. Holding Space or Enter glides the thumb to the end and confirms; letting go early springs it back.
  • A polite live region announces the pending, confirmed, and error labels. While pending or confirmed the slider is aria-disabled.
  • Success is never color alone: the arrow turns into a check and the confirmed label is written beside it. Errors replace the instruction with the error text.
  • Pointer focus draws no ring; keyboard focus shows Arc's shared focus ring. Keyboard focus tints the track instead.
  • One rAF loop integrates a handful of springs and writes SVG paths and transforms straight to the DOM, only when a value changed; React renders only on phase changes.
  • The thumb follows the finger on a stiff spring. The fill's tail follows the thumb on a softer spring, and a bridge between them thins as they pull apart, so fast drags stretch the liquid and it catches up when the thumb slows.
  • Pressing swells the thumb and pushes the track outward around it on an underdamped spring, so the edge wobbles slightly like a membrane. Speed stretches the thumb into an ellipse along the direction of travel.
  • Pulling past the end stretches the track on a rubber band curve. Letting go early returns the thumb on a spring with a small give, and the tail of the fill overtakes it and gets absorbed.
  • Confirming is one continuous movement: the track draws into the thumb from the left, the confirmed label slides in with the retreating edge, and the chevron's three points glide into a check as the circle turns to the success color.
  • An idle nudge every few seconds teaches the gesture. The loop sleeps once everything settles, and stops off screen and in hidden tabs. Reduced motion drops the liquid, the stretch, the nudge, and the morph, and shows each state immediately.
  • The SVG is measured and drawn in real pixels, so the track, hairline, and text stay crisp at any width.
  • Below 360px the track is 56px tall and the text drops to the small size; above it the track is 64px.
  • Vertical page scroll still works over the control on touch; only horizontal drags move the thumb.
  • About a dozen SVG elements. Paths are rebuilt from a few dozen points per frame only while something moves.
  • Written attributes are cached, so settled frames touch nothing.

Notes for AI

Give your coding assistant the Markdown reference instead of screenshots.

  • Use it where a stray tap must not count but the action is routine: sending money, paying, unlocking, starting a shift.
  • Put the object and amount in the label (“Slide to send $240”) and keep it short enough to fit beside the thumb at 390px.
  • Return the real request promise from onConfirm so the pending and error states tell the truth.

The full library index for assistants is at /llms.txt.