Interactive Slide ActionSwipe to Unlock

Slide to Grow Tactile Slider

Smooth gesture swipe-to-grow slider button featuring dynamic laser channel reveal, spring damping, and physical knob transformation.

preview.tsx
Lets Grow!
Get Started
Completions:0
Hover or click to interact

Customizer

PRESETS & VARIATIONS

All Variants Preview

Drag knob or click channel to trigger animated slider unlock

Figma Silvertheme="silver"
Lets Grow!
Get Started
1:1 Figma Master design with blue illuminated channel
UI Pirate Magmatheme="uipirate"
Welcome!
Swipe to Unlock
Signature magma orange beam channel fill
Dark Obsidiantheme="dark"
Confirmed
Slide To Confirm
Stealth midnight chassis with crisp white knob laser
Cyberpunk Violettheme="cyberpunk"
Deployed!
Slide to Deploy
Ultraviolet channel illumination with neon glow
Neon Emeraldtheme="emerald"
Authorized
Swipe Access
Cyberpunk reactor green slider channel beam
Magma Flaretheme="orange"
Paid!
Pay $49
Warm golden orange sliding payment checkout pill

Installation & Setup

Install required peer dependencies for Framer Motion spring dragging:

npm install framer-motion clsx

Code & Integration

SlideGrowButton.tsx• Production Ready
"use client";

import React, { useState } from "react";
import { motion } from "framer-motion";

export type SlideGrowTheme = "silver" | "uipirate" | "dark" | "cyberpunk" | "emerald";
export type SlideGrowSize = "xs" | "sm" | "md" | "lg" | "xl";

export interface SlideGrowButtonProps {
  startLabel?: string;
  activeLabel?: string;
  theme?: SlideGrowTheme;
  size?: SlideGrowSize;
  onComplete?: () => void;
  className?: string;
}

export function SlideGrowButton({
  startLabel = "Get Started",
  activeLabel = "Lets Grow!",
  theme = "silver",
  size = "md",
  onComplete,
  className = "",
}: SlideGrowButtonProps) {
  const [isSlid, setIsSlid] = useState(false);

  const themeConfig = {
    silver: {
      bg: "bg-[#E6E8ED]",
      border: "border-white/80",
      channel: "bg-[#0077FF]",
      text: "text-[#333333]",
      slidText: "text-white",
    },
    uipirate: {
      bg: "bg-[#1C1815]",
      border: "border-orange-500/30",
      channel: "bg-[#FF5B04]",
      text: "text-[#F5F5F5]",
      slidText: "text-white",
    },
  }[theme as "silver" | "uipirate"] || {
    bg: "bg-[#E6E8ED]",
    border: "border-white/80",
    channel: "bg-[#0077FF]",
    text: "text-[#333333]",
    slidText: "text-white",
  };

  return (
    <div
      className={`relative inline-flex items-center select-none p-2 rounded-full ${themeConfig.bg} ${themeConfig.border} border shadow-xl ${className}`}
    >
      <div className="relative w-[230px] h-[52px] flex items-center justify-between px-6 rounded-full overflow-hidden">
        {/* Animated Slide Channel */}
        <motion.div
          animate={{ width: isSlid ? "100%" : "0%" }}
          transition={{ type: "spring", stiffness: 350, damping: 28 }}
          className={`absolute left-0 top-0 bottom-0 ${themeConfig.channel} rounded-full`}
        />

        {/* Text */}
        <span
          className={`relative z-10 font-bold text-sm transition-colors duration-200 ${
            isSlid ? themeConfig.slidText : themeConfig.text
          }`}
        >
          {isSlid ? activeLabel : startLabel}
        </span>

        {/* Drag / Click Slider Knob */}
        <motion.button
          type="button"
          onClick={() => {
            setIsSlid((s) => !s);
            if (!isSlid && onComplete) onComplete();
          }}
          animate={{ x: isSlid ? 0 : 0 }}
          className="relative z-10 w-10 h-10 rounded-full bg-white shadow-md flex items-center justify-center cursor-pointer focus:outline-none"
        >
          <svg
            className={`w-4 h-4 text-neutral-800 transition-transform duration-300 ${
              isSlid ? "rotate-180" : ""
            }`}
            fill="none"
            stroke="currentColor"
            viewBox="0 0 24 24"
          >
            <path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2.5} d="M9 5l7 7-7 7" />
          </svg>
        </motion.button>
      </div>
    </div>
  );
}

Component API Reference

PropTypeDefaultDescription
startLabelstring"Get Started"Initial label displayed in resting state
activeLabelstring"Lets Grow!"Active label revealed when slider completes
themeSlideGrowTheme"silver"Color scheme theme preset
size"xs" | "sm" | "md" | "lg" | "xl""md"Scale multiplier
onComplete() => voidundefinedCallback fired when slider is pulled to completion

Personalized Help

Struggling with gesture swipe sliders or interactive web controls? Let's talk about your product.

UI Pirate is a product design & development agency trusted by 50+ SaaS founders and enterprise teams across the US, UK & beyond. Tell us what you need.