shadcn.io is not affiliated with official shadcn/ui
Drag the handle along the track. The fill follows it and the label fades. Let go past threshold, 90% of the way by default, and onConfirm runs, the handle shows a check, and it slides back after a moment. Let go earlier and it slides back with nothing done.
Use it for high-stakes actions on touch screens, such as paying, sending to everyone or deleting, where a tap is too easy to make by accident. On a desktop page a Long Press Button or a confirmation dialog is often simpler. It wraps the Button, so variant works as usual and size sets the track's height; the handle is as tall as the track. Dragging writes one CSS variable, the progress from 0 to 1, and the handle and the fill follow it with a CSS translate while the label fades, with no animation library. The handle follows the finger even with reduced motion, but the slide back is a jump instead of a glide.
Installation
Usage
import {
SlideToConfirmButton,
} from "@/components/ui/slide-to-confirm-button";<SlideToConfirmButton onConfirm={pay}>Slide to pay</SlideToConfirmButton>Demos
Threshold
threshold is how much of the track the handle has to cross, from 0 to 1. Half the track is enough to unlock; 1 asks for the whole way, for something you'd rather people think about.
Destructive
The track takes any variant and size: the handle is drawn in the label's color, so it matches, and it's as tall as the track. Here a wider, taller track (className="w-72", size="xl") deletes files, and resetDelay keeps the handle at the end for 1.5 seconds so the result has time to register.
Accessibility
It's a button named by its label, such as Slide to pay $24.00. Dragging isn't the only way in: Enter and Space confirm it, and so does a screen reader's activate command, with the handle sliding across to show it. A mouse click on the track does nothing, so the gesture stays deliberate for pointers. The handle and its icons are hidden from assistive tech.
- Enter
- Confirm.
- Space
- Confirm.
FAQ
How do I change the words on the track?
Pass them as children: <SlideToConfirmButton>Slide to send</SlideToConfirmButton>. The default is Slide to confirm. The label is also the button's accessible name.
How far does someone have to slide?
90% of the track by default. Set threshold between 0 and 1: lower is easier, 1 needs the full length. The Threshold demo shows 0.5 and 1.
Can keyboard and screen reader users confirm it?
Yes. Enter, Space and a screen reader's activation confirm it without dragging, and the handle slides across to show it. The button tells them apart from a mouse click because their click has no pointer behind it (its detail is 0).
What happens after it confirms?
The handle moves to the end and shows a check, rests there for resetDelay (800 milliseconds by default), then slides back. Navigate or show a message from onConfirm. The track has data-state="confirmed" while it rests, for styling.
How do I make the track wider or narrower?
Pass a width in className, such as w-72; the default is w-64, and it never grows past its container. The height follows size. Keep it wide enough that the threshold can't be crossed by accident.
API Reference
SlideToConfirmButton
data-slot="slide-to-confirm-button-track"
children?ReactNode
The label on the track; it fades as the handle crosses it.
- Default
"Slide to confirm"
clickEffect?boolean
Shrink a little on press, as the Button does. Off, so the track holds still under a drag.
- Default
false
focusableWhenDisabled?boolean
Whether the button should be focusable when disabled.
- Default
false
nativeButton?boolean
Whether the component renders a native <button> element when replacing it
via the render prop.
Set to false if the rendered element is not a button (for example, <div>).
- Default
true
onConfirm?() → void
Called when the handle is let go past threshold, or when the button
is pressed with Enter or Space. A click on the track doesn't confirm.
- Returns
void
resetDelay?number
How long the handle rests at the end after confirming, in milliseconds, before it slides back.
- Default
800
threshold?number
How much of the track the handle has to cross to confirm, from 0 to 1. Let go before it and the handle slides back.
- Default
0.9
render?ReactElement | ((props: object, state: object) => ReactElement)
Replace the host element or compose it with another component.
- Type
ReactElement | ((props: object, state: object) => ReactElement)
className?string
Merged with the part's classes.
data-state?string
"confirmed" when confirmed is true, otherwise "idle".
--slide-to-confirm-button-progressstring
How far the handle is, 0 to 1 (set while dragging).
Related
- Pro
Long Press Button
ControlsHold to confirm, no drag needed
Countdown Button
Progress & resultsA timed confirm with an undo window
- Pro
Success Button
Progress & resultsA checkmark once the action lands
- Pro
Shake Button
Motion & feedbackSay no when the action fails
- Pro
Pill Button
SurfacesThe same pill shape, one tap
Magnetic Button
Motion & feedbackAnother button that follows the pointer