Skip to content

Slide to Confirm

Confirm a costly action with a deliberate gesture: drag the thumb to the end of the track.

import { SlideToConfirm } from '@youj/react'

Installation & usage

npm i @youj/react

For an app already set up with npx @youj/cli init, which installs the peers (@youj/core, @youj/motion, motion and Base UI) and wires the provider. New app? Start at Installation.

Use a Slide to Confirm for an action that is costly to trigger by mistake, such as a payment, a transfer or a deletion, where a dialog would interrupt more than it helps. For a lighter guard on a button, use hold on an Async Button.

'use client'

import { SlideToConfirm } from '@youj/react'

export function PayInvoice({ invoice }: { invoice: Invoice }) {
  return (
    <SlideToConfirm
      label={`Slide to pay ${invoice.total}`}
      confirmingLabel="Paying…"
      confirmedLabel="Paid"
      onConfirm={() => pay(invoice.id)}
    />
  )
}

onConfirm is awaited: resolve for success, reject or throw for an error. It runs once per confirmation, and a second confirm while it runs is ignored. Once confirmed the control stays confirmed; give it a new key to offer it again. It sizes to its container up to max-w-sm; pass a className to change that.

Reference

PropsonConfirm, label, confirmingLabel, confirmedLabel, errorLabel, size, tone…

Props

SlideToConfirm props
PropType
onConfirm() => unknown

The action, run once the thumb reaches the end. Return a promise to show its progress: the thumb spins until it resolves, then shows a check and stays confirmed. A rejection (or a throw) shows its message in the track, springs the thumb back and lets the person try again.

–
labelstring

The track's label and the thumb's name.

default "Slide to confirm"

"Slide to confirm"
confirmingLabelstring

Shown and announced while onConfirm runs.

default "Working…"

"Working…"
confirmedLabelstring

Shown and announced once confirmed.

default "Confirmed"

"Confirmed"
errorLabelstring | ((error: unknown) => string)

Shown in the track and announced assertively when onConfirm rejects. Default: the error's message, else "Something went wrong. Try again.". A function gets what it rejected with.

–
resetAfternumber

How long an error shows before the track returns to rest, in ms. Default: 3 × the deliberate token.

–
disabledboolean

Blocks the thumb and takes it out of the tab order.

default false

false
size'sm' | 'default' | 'lg'

sm | default | lg: 40, 48 or 56px tall.

default 'default'

'default'
tone'default' | 'danger'

default (the accent) or danger, for an action that deletes or can't be undone.

default 'default'

'default'
soundboolean

With sound on (YoujProvider’s sound), passing the end ticks and the outcome sounds. false keeps it silent.

default true

true
Other props pass through: extends ComponentProps<'div'>.

Data attributes

The root carries data-state (idle, confirming, confirmed or error), data-size (sm, default or lg) and data-tone (default or danger), plus data-dragging while the thumb is held and data-disabled when disabled. The thumb's position is --ui--slide, from 0 to 1.

MotionDrag, spring back, outcome · reduced motion

Motion

Motion tokens
MomentTokens
Dragthe thumb follows the pointer 1:1, never eased in time
no token

Spring backreleased short of 90%, the thumb returns to the start
spring.smooth

0.36s, bounce 0

0.36s, bounce 0
Snap to the endreleased past 90%, the thumb lands at the end
spring.snappy

0.2s, bounce 0

0.2s, bounce 0
Labelfades as the thumb passes; swaps to each state
duration.fastease.standard

140ms · cubic-bezier(0.2, 0, 0, 1)

140mscubic-bezier(0.2, 0, 0, 1)
Thumb markchevron, spinner, check or cross swap with a scale from 0.75 and a fade
duration.fastease.standard

140ms · cubic-bezier(0.2, 0, 0, 1)

140mscubic-bezier(0.2, 0, 0, 1)
Check landingthe check scales in on the spring
spring.smooth

0.36s, bounce 0

0.36s, bounce 0
Success fillthe track washes to the success fill, as an Async Button’s tint
duration.fastease.standard

140ms · cubic-bezier(0.2, 0, 0, 1)

140mscubic-bezier(0.2, 0, 0, 1)
Error holdbefore the track returns to rest, unless resetAfter is set
duration.deliberate

560ms · × 3

560ms× 3

Reduced motion

The thumb still follows the pointer, but it is back at the start, or at the end, at once. The thumb's marks swap at once, and the spinner holds a still quarter arc.

Reduced motion

Dragging works the same. The spring back and the snap are instant, the marks swap at once, and the spinner holds still.

AccessibilitySlider role, keyboard, announcements

Accessibility

  • The thumb is a slider (0 to 100) named by label and described by a hint: use the arrow keys or End to reach the end, then press Enter.
  • Arrow keys step by 10, Home and End jump to either end, and Enter at the end (90% or more) confirms. In right-to-left, the arrow keys follow the mirrored track. A thumb left short of the end goes back when it loses focus.
  • While confirming and once confirmed, the slider is read-only and its value text is the state's label. Confirming and confirmed are announced politely, an error assertively.
  • disabled takes the thumb out of the tab order and sets aria-disabled.