Slide To Confirm React component for Tailwind CSS v4
v1.0.0Added in 1.0.0
A React slide to confirm control: drag the thumb to the end to approve a payment or risky action.
Drag the thumb along the track with a finger or the mouse: the fill grows behind it and the label fades as the thumb passes. Past the threshold the thumb grows a little, the fill deepens and the phone ticks; let go there (or flick hard past 60%) and it glides to the end and confirms, let go earlier and it springs home. A promise from onConfirm shows a spinner on the parked thumb, then a bouncing check with the fill covering the track, or a short shake, the thumb back home and the error text for 2 seconds. Tap the track (or click the thumb) and the thumb hops forward and the label lights up, to teach the gesture. Vertical swipes that start on the track still scroll the page. Keyboard: Tab to the thumb, Enter, Space or End glide it to the end and confirm, Left / Right preview the travel in 10% steps and it springs back after a moment, Home returns it. With a screen reader, activating the thumb (a double tap in VoiceOver or TalkBack) confirms, and loading, success and error are announced. In RTL the thumb starts on the right.
Slide To Confirm is a Pro React component in the React mobile components category, written in TypeScript for React 19 and Tailwind CSS v4. It installs as source with npx wingo-ui@latest add slide-to-confirm, together with Spinner, useControllableState, Haptics, Motion presets, Tones and 1 more and the npm packages lucide-react and motion.
Add to a project
Requirements: React 19 and Tailwind CSS v4, in Next.js (App Router or Pages), Vite or React Router. Installation guide · Next.js setup · Vite setup
npx wingo-ui@latest add slide-to-confirmSlide To Confirm is part of Pro, with 298 more Pro items: $8 a month or $150 once. 14-day refund before you download any Pro item. See plans
Usage
Import SlideToConfirm from @/components/ui/slide-to-confirm.
import { SlideToConfirm } from "@/components/ui/slide-to-confirm"
export function ConfirmDelivery({ orderId }: { orderId: string }) {
return (
<SlideToConfirm
label="Slide to confirm delivery"
labels={{ loading: "Confirming…", success: "Delivery confirmed", error: "Could not confirm. Try again." }}
onConfirm={() => fetch(`/api/orders/${orderId}/delivered`, { method: "POST" }).then((res) => {
if (!res.ok) throw new Error("failed")
})}
/>
)
}Props
labeldefault"Slide to confirm"stringThe track text and the thumb's accessible name. Keep it short, it truncates on narrow tracks.
variantdefault"soft""soft" | "solid" | "outline"soft: a tinted track with a toned thumb. solid: the track in the tone fill with a contrasting thumb, for the one hero action. outline: a hairline track in the tone border.
tonedefault"neutral""neutral" | "brand" | "success" | "warning" | "danger" | "info"Thumb and fill color from the design tokens. neutral is black in light mode and white in dark mode.
colordefault""stringAny CSS color. Replaces the tone; icons on the fill turn black or white by lightness.
sizedefault"md""sm" | "md" | "lg"Track height 48 / 56 / 64px, thumb 40 / 48 / 56px, label 14 / 15 / 16px. Every size is a comfortable touch target.
radiusdefault"full""none" | "sm" | "md" | "lg" | "full"Track radius 0 / 10 / 14 / 18px or a pill; the thumb and fill take the track radius minus their 4px inset.
shimmerdefaulttruebooleanA highlight that sweeps across the label while idle. Off when disabled, under reduced motion and off screen.
disableddefaultfalsebooleanDims the control and blocks dragging and keys. The thumb stays focusable with aria-disabled, so a screen reader still finds it.
defaultStatusdefault"idle""idle" | "loading" | "success" | "error"Starting status while uncontrolled. success parks the thumb at the end without calling onConfirm.
status"idle" | "loading" | "success" | "error"Controlled status for server-driven flows. Set it to "idle" to reset; set "success" and the thumb moves to the end without calling onConfirm.
onStatusChange(status: SlideToConfirmStatus) => voidFires with every status change: loading when a promise starts, success / error when it settles, idle on reset.
onConfirm() => (void | Promise<unknown>)Runs when the thumb reaches the end or on Enter. Return a promise to show loading, then success when it resolves or error when it rejects (a synchronous throw counts as a rejection). Never runs twice for one slide.
thresholddefault0.9numberShare of the travel past which a release confirms. Deliberately harder than other swipes: a flick counts only past 0.6. 1 means the very end.
resetAfterdefault0numberMilliseconds after success before it slides back to idle. 0 keeps it confirmed until you reset the status.
hapticsdefaulttruebooleanA medium tick when the thumb arms, success / error patterns on the outcome (through lib/haptics, phones only).
iconReactNodeThe thumb icon, a ChevronsRight by default. Unsized svgs follow the size (18 / 20 / 22px); mirrored in RTL.
successIconReactNodeShown on the thumb after success, a Check by default; pops in on a bouncy spring.
labelsPartial<SlideToConfirmLabels>Status texts: loading "Processing…", success "Confirmed", error "Something went wrong. Try again.", hint "Drag to the end, or press Enter" (the thumb's screen reader description). Defaults in DEFAULT_SLIDE_TO_CONFIRM_LABELS.
classNamesPartial<Record<"track" | "fill" | "label" | "thumb" | "icon" | "spinner" | "check", string>>Extra classes for the inner parts.
classNamestringClasses for the root, merged last. It is full width by default; cap it here, e.g. max-w-sm.
Parts
DEFAULT_SLIDE_TO_CONFIRM_LABELS
constantThe English status texts: loading, success, error and the screen reader hint for the thumb. Spread it and override what you translate.
Examples
Slide to pay
Brand tone for a checkout's one hero action; resets 2.5s after success.
Clock in
The solid variant with a success tone and custom icons.
Error path
A rejected promise shakes the track, sends the thumb home and shows the error for 2s.
Sizes and radius
48, 56 and 64px tracks; radius md instead of the default pill.
Outline on a card
A hairline track in the tone border, with the shimmer turned off.
Disabled with a reason
Dimmed and blocked, with the reason spelled out under it.
Controlled status
The status lives outside: reset it, or mark it done without calling onConfirm.
Files
- components/ui/slide-to-confirm.tsx
FAQ
Is the React Slide To Confirm component free?
The preview, props and docs are free; copying the source needs a Pro plan. See plans.
How do I install Slide To Confirm?
Run npx wingo-ui@latest add slide-to-confirm. It also adds the Wingo UI items it builds on (Spinner, useControllableState, Haptics, Motion presets, Tones and 1 more) and the npm packages lucide-react and motion. With shadcn, add the @wingo-ui registry with your API key, then run npx shadcn@latest add @wingo-ui/slide-to-confirm.
See also
More React mobile components
Articles using this component
- React Slide to Confirm: When It Beats a Confirm Dialog
Mobile UI in React8 min read