Button
ComponentsInteractive element.
Primary Button
Install this package in your project before importing the animated component.
npm i framer-motion lucide-react <button class="h-10 px-4 py-2 rounded-md font-medium transition-colors hover:opacity-90 bg-primary text-primary-foreground">Primary</button> <button className="h-10 px-4 py-2 rounded-md font-medium transition-colors hover:opacity-90 bg-primary text-primary-foreground">Primary</button> "use client";
import React, { useState } from "react";
interface BtnPrimaryProps extends React.ButtonHTMLAttributes<HTMLButtonElement> {
children?: React.ReactNode;
isLoading?: boolean;
}
export default function BtnPrimary({
children = "Click Me",
isLoading: initialLoading = false,
className = "",
...props
}: BtnPrimaryProps) {
const [loading, setLoading] = useState(initialLoading);
const [clicked, setClicked] = useState(false);
const handleClick = (e: React.MouseEvent<HTMLButtonElement>) => {
setClicked(true);
setTimeout(() => setClicked(false), 300);
props.onClick?.(e);
};
return (
<button
{...props}
onClick={handleClick}
className={`inline-flex items-center justify-center gap-2 px-5 py-2.5 rounded-xl font-semibold text-xs transition-all active:scale-95 disabled:opacity-50 disabled:pointer-events-none ${
clicked ? "ring-2 ring-primary/40 ring-offset-2 ring-offset-background" : ""
} ${className || "bg-primary text-primary-foreground hover:bg-primary/90 shadow-sm"}`}
>
{loading && (
<svg className="animate-spin h-3.5 w-3.5" viewBox="0 0 24 24" fill="none">
<circle className="opacity-25" cx="12" cy="12" r="10" stroke="currentColor" strokeWidth="4" />
<path className="opacity-75" fill="currentColor" d="M4 12a8 8 0 018-8v8H4z" />
</svg>
)}
<span>{children}</span>
</button>
);
} "use client";
import React from "react";
import { motion } from "framer-motion";
export default function AnimatedBtnPrimary() {
return (
<motion.button
whileHover={{ scale: 1.04 }}
whileTap={{ scale: 0.96 }}
transition={{ type: "spring", stiffness: 400, damping: 20 }}
className="inline-flex items-center justify-center gap-2 px-6 py-3 rounded-xl bg-primary text-primary-foreground font-semibold text-xs shadow-md hover:bg-primary/90 transition-colors"
>
<span>Interactive Motion Button</span>
<motion.span
animate={{ x: [0, 4, 0] }}
transition={{ repeat: Infinity, duration: 1.5, ease: "easeInOut" }}
>
→
</motion.span>
</motion.button>
);
} Secondary Button
Install this package in your project before importing the animated component.
npm i framer-motion lucide-react <button class="h-10 px-4 py-2 rounded-md font-medium transition-colors hover:opacity-90 bg-muted text-muted-foreground">Secondary</button> <button className="h-10 px-4 py-2 rounded-md font-medium transition-colors hover:opacity-90 bg-muted text-muted-foreground">Secondary</button> "use client";
import React, { useState } from "react";
interface BtnSecondaryProps extends React.ButtonHTMLAttributes<HTMLButtonElement> {
children?: React.ReactNode;
isLoading?: boolean;
}
export default function BtnSecondary({
children = "Click Me",
isLoading: initialLoading = false,
className = "",
...props
}: BtnSecondaryProps) {
const [loading, setLoading] = useState(initialLoading);
const [clicked, setClicked] = useState(false);
const handleClick = (e: React.MouseEvent<HTMLButtonElement>) => {
setClicked(true);
setTimeout(() => setClicked(false), 300);
props.onClick?.(e);
};
return (
<button
{...props}
onClick={handleClick}
className={`inline-flex items-center justify-center gap-2 px-5 py-2.5 rounded-xl font-semibold text-xs transition-all active:scale-95 disabled:opacity-50 disabled:pointer-events-none ${
clicked ? "ring-2 ring-primary/40 ring-offset-2 ring-offset-background" : ""
} ${className || "bg-primary text-primary-foreground hover:bg-primary/90 shadow-sm"}`}
>
{loading && (
<svg className="animate-spin h-3.5 w-3.5" viewBox="0 0 24 24" fill="none">
<circle className="opacity-25" cx="12" cy="12" r="10" stroke="currentColor" strokeWidth="4" />
<path className="opacity-75" fill="currentColor" d="M4 12a8 8 0 018-8v8H4z" />
</svg>
)}
<span>{children}</span>
</button>
);
} "use client";
import React from "react";
import { motion } from "framer-motion";
export default function AnimatedBtnSecondary() {
return (
<motion.button
whileHover={{ scale: 1.04 }}
whileTap={{ scale: 0.96 }}
transition={{ type: "spring", stiffness: 400, damping: 20 }}
className="inline-flex items-center justify-center gap-2 px-6 py-3 rounded-xl bg-primary text-primary-foreground font-semibold text-xs shadow-md hover:bg-primary/90 transition-colors"
>
<span>Interactive Motion Button</span>
<motion.span
animate={{ x: [0, 4, 0] }}
transition={{ repeat: Infinity, duration: 1.5, ease: "easeInOut" }}
>
→
</motion.span>
</motion.button>
);
} Destructive Button
Install this package in your project before importing the animated component.
npm i framer-motion lucide-react <button class="h-10 px-4 py-2 rounded-md font-medium transition-colors hover:opacity-90 bg-red-500 text-white">Destructive</button> <button className="h-10 px-4 py-2 rounded-md font-medium transition-colors hover:opacity-90 bg-red-500 text-white">Destructive</button> "use client";
import React, { useState } from "react";
interface BtnDestructiveProps extends React.ButtonHTMLAttributes<HTMLButtonElement> {
children?: React.ReactNode;
isLoading?: boolean;
}
export default function BtnDestructive({
children = "Click Me",
isLoading: initialLoading = false,
className = "",
...props
}: BtnDestructiveProps) {
const [loading, setLoading] = useState(initialLoading);
const [clicked, setClicked] = useState(false);
const handleClick = (e: React.MouseEvent<HTMLButtonElement>) => {
setClicked(true);
setTimeout(() => setClicked(false), 300);
props.onClick?.(e);
};
return (
<button
{...props}
onClick={handleClick}
className={`inline-flex items-center justify-center gap-2 px-5 py-2.5 rounded-xl font-semibold text-xs transition-all active:scale-95 disabled:opacity-50 disabled:pointer-events-none ${
clicked ? "ring-2 ring-primary/40 ring-offset-2 ring-offset-background" : ""
} ${className || "bg-primary text-primary-foreground hover:bg-primary/90 shadow-sm"}`}
>
{loading && (
<svg className="animate-spin h-3.5 w-3.5" viewBox="0 0 24 24" fill="none">
<circle className="opacity-25" cx="12" cy="12" r="10" stroke="currentColor" strokeWidth="4" />
<path className="opacity-75" fill="currentColor" d="M4 12a8 8 0 018-8v8H4z" />
</svg>
)}
<span>{children}</span>
</button>
);
} "use client";
import React from "react";
import { motion } from "framer-motion";
export default function AnimatedBtnDestructive() {
return (
<motion.button
whileHover={{ scale: 1.04 }}
whileTap={{ scale: 0.96 }}
transition={{ type: "spring", stiffness: 400, damping: 20 }}
className="inline-flex items-center justify-center gap-2 px-6 py-3 rounded-xl bg-primary text-primary-foreground font-semibold text-xs shadow-md hover:bg-primary/90 transition-colors"
>
<span>Interactive Motion Button</span>
<motion.span
animate={{ x: [0, 4, 0] }}
transition={{ repeat: Infinity, duration: 1.5, ease: "easeInOut" }}
>
→
</motion.span>
</motion.button>
);
} Success Button
Install this package in your project before importing the animated component.
npm i framer-motion lucide-react <button class="h-10 px-4 py-2 rounded-md font-medium transition-colors hover:opacity-90 bg-green-500 text-white">Success</button> <button className="h-10 px-4 py-2 rounded-md font-medium transition-colors hover:opacity-90 bg-green-500 text-white">Success</button> "use client";
import React, { useState } from "react";
interface BtnSuccessProps extends React.ButtonHTMLAttributes<HTMLButtonElement> {
children?: React.ReactNode;
isLoading?: boolean;
}
export default function BtnSuccess({
children = "Click Me",
isLoading: initialLoading = false,
className = "",
...props
}: BtnSuccessProps) {
const [loading, setLoading] = useState(initialLoading);
const [clicked, setClicked] = useState(false);
const handleClick = (e: React.MouseEvent<HTMLButtonElement>) => {
setClicked(true);
setTimeout(() => setClicked(false), 300);
props.onClick?.(e);
};
return (
<button
{...props}
onClick={handleClick}
className={`inline-flex items-center justify-center gap-2 px-5 py-2.5 rounded-xl font-semibold text-xs transition-all active:scale-95 disabled:opacity-50 disabled:pointer-events-none ${
clicked ? "ring-2 ring-primary/40 ring-offset-2 ring-offset-background" : ""
} ${className || "bg-primary text-primary-foreground hover:bg-primary/90 shadow-sm"}`}
>
{loading && (
<svg className="animate-spin h-3.5 w-3.5" viewBox="0 0 24 24" fill="none">
<circle className="opacity-25" cx="12" cy="12" r="10" stroke="currentColor" strokeWidth="4" />
<path className="opacity-75" fill="currentColor" d="M4 12a8 8 0 018-8v8H4z" />
</svg>
)}
<span>{children}</span>
</button>
);
} "use client";
import React from "react";
import { motion } from "framer-motion";
export default function AnimatedBtnSuccess() {
return (
<motion.button
whileHover={{ scale: 1.04 }}
whileTap={{ scale: 0.96 }}
transition={{ type: "spring", stiffness: 400, damping: 20 }}
className="inline-flex items-center justify-center gap-2 px-6 py-3 rounded-xl bg-primary text-primary-foreground font-semibold text-xs shadow-md hover:bg-primary/90 transition-colors"
>
<span>Interactive Motion Button</span>
<motion.span
animate={{ x: [0, 4, 0] }}
transition={{ repeat: Infinity, duration: 1.5, ease: "easeInOut" }}
>
→
</motion.span>
</motion.button>
);
} Warning Button
Install this package in your project before importing the animated component.
npm i framer-motion lucide-react <button class="h-10 px-4 py-2 rounded-md font-medium transition-colors hover:opacity-90 bg-yellow-500 text-white">Warning</button> <button className="h-10 px-4 py-2 rounded-md font-medium transition-colors hover:opacity-90 bg-yellow-500 text-white">Warning</button> "use client";
import React, { useState } from "react";
interface BtnWarningProps extends React.ButtonHTMLAttributes<HTMLButtonElement> {
children?: React.ReactNode;
isLoading?: boolean;
}
export default function BtnWarning({
children = "Click Me",
isLoading: initialLoading = false,
className = "",
...props
}: BtnWarningProps) {
const [loading, setLoading] = useState(initialLoading);
const [clicked, setClicked] = useState(false);
const handleClick = (e: React.MouseEvent<HTMLButtonElement>) => {
setClicked(true);
setTimeout(() => setClicked(false), 300);
props.onClick?.(e);
};
return (
<button
{...props}
onClick={handleClick}
className={`inline-flex items-center justify-center gap-2 px-5 py-2.5 rounded-xl font-semibold text-xs transition-all active:scale-95 disabled:opacity-50 disabled:pointer-events-none ${
clicked ? "ring-2 ring-primary/40 ring-offset-2 ring-offset-background" : ""
} ${className || "bg-primary text-primary-foreground hover:bg-primary/90 shadow-sm"}`}
>
{loading && (
<svg className="animate-spin h-3.5 w-3.5" viewBox="0 0 24 24" fill="none">
<circle className="opacity-25" cx="12" cy="12" r="10" stroke="currentColor" strokeWidth="4" />
<path className="opacity-75" fill="currentColor" d="M4 12a8 8 0 018-8v8H4z" />
</svg>
)}
<span>{children}</span>
</button>
);
} "use client";
import React from "react";
import { motion } from "framer-motion";
export default function AnimatedBtnWarning() {
return (
<motion.button
whileHover={{ scale: 1.04 }}
whileTap={{ scale: 0.96 }}
transition={{ type: "spring", stiffness: 400, damping: 20 }}
className="inline-flex items-center justify-center gap-2 px-6 py-3 rounded-xl bg-primary text-primary-foreground font-semibold text-xs shadow-md hover:bg-primary/90 transition-colors"
>
<span>Interactive Motion Button</span>
<motion.span
animate={{ x: [0, 4, 0] }}
transition={{ repeat: Infinity, duration: 1.5, ease: "easeInOut" }}
>
→
</motion.span>
</motion.button>
);
} Info Button
Install this package in your project before importing the animated component.
npm i framer-motion lucide-react <button class="h-10 px-4 py-2 rounded-md font-medium transition-colors hover:opacity-90 bg-blue-500 text-white">Info</button> <button className="h-10 px-4 py-2 rounded-md font-medium transition-colors hover:opacity-90 bg-blue-500 text-white">Info</button> "use client";
import React, { useState } from "react";
interface BtnInfoProps extends React.ButtonHTMLAttributes<HTMLButtonElement> {
children?: React.ReactNode;
isLoading?: boolean;
}
export default function BtnInfo({
children = "Click Me",
isLoading: initialLoading = false,
className = "",
...props
}: BtnInfoProps) {
const [loading, setLoading] = useState(initialLoading);
const [clicked, setClicked] = useState(false);
const handleClick = (e: React.MouseEvent<HTMLButtonElement>) => {
setClicked(true);
setTimeout(() => setClicked(false), 300);
props.onClick?.(e);
};
return (
<button
{...props}
onClick={handleClick}
className={`inline-flex items-center justify-center gap-2 px-5 py-2.5 rounded-xl font-semibold text-xs transition-all active:scale-95 disabled:opacity-50 disabled:pointer-events-none ${
clicked ? "ring-2 ring-primary/40 ring-offset-2 ring-offset-background" : ""
} ${className || "bg-primary text-primary-foreground hover:bg-primary/90 shadow-sm"}`}
>
{loading && (
<svg className="animate-spin h-3.5 w-3.5" viewBox="0 0 24 24" fill="none">
<circle className="opacity-25" cx="12" cy="12" r="10" stroke="currentColor" strokeWidth="4" />
<path className="opacity-75" fill="currentColor" d="M4 12a8 8 0 018-8v8H4z" />
</svg>
)}
<span>{children}</span>
</button>
);
} "use client";
import React from "react";
import { motion } from "framer-motion";
export default function AnimatedBtnInfo() {
return (
<motion.button
whileHover={{ scale: 1.04 }}
whileTap={{ scale: 0.96 }}
transition={{ type: "spring", stiffness: 400, damping: 20 }}
className="inline-flex items-center justify-center gap-2 px-6 py-3 rounded-xl bg-primary text-primary-foreground font-semibold text-xs shadow-md hover:bg-primary/90 transition-colors"
>
<span>Interactive Motion Button</span>
<motion.span
animate={{ x: [0, 4, 0] }}
transition={{ repeat: Infinity, duration: 1.5, ease: "easeInOut" }}
>
→
</motion.span>
</motion.button>
);
} Purple Button
Install this package in your project before importing the animated component.
npm i framer-motion lucide-react <button class="h-10 px-4 py-2 rounded-md font-medium transition-colors hover:opacity-90 bg-purple-500 text-white">Purple</button> <button className="h-10 px-4 py-2 rounded-md font-medium transition-colors hover:opacity-90 bg-purple-500 text-white">Purple</button> "use client";
import React, { useState } from "react";
interface BtnPurpleProps extends React.ButtonHTMLAttributes<HTMLButtonElement> {
children?: React.ReactNode;
isLoading?: boolean;
}
export default function BtnPurple({
children = "Click Me",
isLoading: initialLoading = false,
className = "",
...props
}: BtnPurpleProps) {
const [loading, setLoading] = useState(initialLoading);
const [clicked, setClicked] = useState(false);
const handleClick = (e: React.MouseEvent<HTMLButtonElement>) => {
setClicked(true);
setTimeout(() => setClicked(false), 300);
props.onClick?.(e);
};
return (
<button
{...props}
onClick={handleClick}
className={`inline-flex items-center justify-center gap-2 px-5 py-2.5 rounded-xl font-semibold text-xs transition-all active:scale-95 disabled:opacity-50 disabled:pointer-events-none ${
clicked ? "ring-2 ring-primary/40 ring-offset-2 ring-offset-background" : ""
} ${className || "bg-primary text-primary-foreground hover:bg-primary/90 shadow-sm"}`}
>
{loading && (
<svg className="animate-spin h-3.5 w-3.5" viewBox="0 0 24 24" fill="none">
<circle className="opacity-25" cx="12" cy="12" r="10" stroke="currentColor" strokeWidth="4" />
<path className="opacity-75" fill="currentColor" d="M4 12a8 8 0 018-8v8H4z" />
</svg>
)}
<span>{children}</span>
</button>
);
} "use client";
import React from "react";
import { motion } from "framer-motion";
export default function AnimatedBtnPurple() {
return (
<motion.button
whileHover={{ scale: 1.04 }}
whileTap={{ scale: 0.96 }}
transition={{ type: "spring", stiffness: 400, damping: 20 }}
className="inline-flex items-center justify-center gap-2 px-6 py-3 rounded-xl bg-primary text-primary-foreground font-semibold text-xs shadow-md hover:bg-primary/90 transition-colors"
>
<span>Interactive Motion Button</span>
<motion.span
animate={{ x: [0, 4, 0] }}
transition={{ repeat: Infinity, duration: 1.5, ease: "easeInOut" }}
>
→
</motion.span>
</motion.button>
);
} Orange Button
Install this package in your project before importing the animated component.
npm i framer-motion lucide-react <button class="h-10 px-4 py-2 rounded-md font-medium transition-colors hover:opacity-90 bg-orange-500 text-white">Orange</button> <button className="h-10 px-4 py-2 rounded-md font-medium transition-colors hover:opacity-90 bg-orange-500 text-white">Orange</button> "use client";
import React, { useState } from "react";
interface BtnOrangeProps extends React.ButtonHTMLAttributes<HTMLButtonElement> {
children?: React.ReactNode;
isLoading?: boolean;
}
export default function BtnOrange({
children = "Click Me",
isLoading: initialLoading = false,
className = "",
...props
}: BtnOrangeProps) {
const [loading, setLoading] = useState(initialLoading);
const [clicked, setClicked] = useState(false);
const handleClick = (e: React.MouseEvent<HTMLButtonElement>) => {
setClicked(true);
setTimeout(() => setClicked(false), 300);
props.onClick?.(e);
};
return (
<button
{...props}
onClick={handleClick}
className={`inline-flex items-center justify-center gap-2 px-5 py-2.5 rounded-xl font-semibold text-xs transition-all active:scale-95 disabled:opacity-50 disabled:pointer-events-none ${
clicked ? "ring-2 ring-primary/40 ring-offset-2 ring-offset-background" : ""
} ${className || "bg-primary text-primary-foreground hover:bg-primary/90 shadow-sm"}`}
>
{loading && (
<svg className="animate-spin h-3.5 w-3.5" viewBox="0 0 24 24" fill="none">
<circle className="opacity-25" cx="12" cy="12" r="10" stroke="currentColor" strokeWidth="4" />
<path className="opacity-75" fill="currentColor" d="M4 12a8 8 0 018-8v8H4z" />
</svg>
)}
<span>{children}</span>
</button>
);
} "use client";
import React from "react";
import { motion } from "framer-motion";
export default function AnimatedBtnOrange() {
return (
<motion.button
whileHover={{ scale: 1.04 }}
whileTap={{ scale: 0.96 }}
transition={{ type: "spring", stiffness: 400, damping: 20 }}
className="inline-flex items-center justify-center gap-2 px-6 py-3 rounded-xl bg-primary text-primary-foreground font-semibold text-xs shadow-md hover:bg-primary/90 transition-colors"
>
<span>Interactive Motion Button</span>
<motion.span
animate={{ x: [0, 4, 0] }}
transition={{ repeat: Infinity, duration: 1.5, ease: "easeInOut" }}
>
→
</motion.span>
</motion.button>
);
} Pink Button
6-Digit Verification Code
Type digits to auto-advance, backspace to reverse
Install this package in your project before importing the animated component.
npm i framer-motion lucide-react <button class="h-10 px-4 py-2 rounded-md font-medium transition-colors hover:opacity-90 bg-pink-500 text-white">Pink</button> <button className="h-10 px-4 py-2 rounded-md font-medium transition-colors hover:opacity-90 bg-pink-500 text-white">Pink</button> "use client";
import React, { useState } from "react";
interface BtnPinkProps extends React.ButtonHTMLAttributes<HTMLButtonElement> {
children?: React.ReactNode;
isLoading?: boolean;
}
export default function BtnPink({
children = "Click Me",
isLoading: initialLoading = false,
className = "",
...props
}: BtnPinkProps) {
const [loading, setLoading] = useState(initialLoading);
const [clicked, setClicked] = useState(false);
const handleClick = (e: React.MouseEvent<HTMLButtonElement>) => {
setClicked(true);
setTimeout(() => setClicked(false), 300);
props.onClick?.(e);
};
return (
<button
{...props}
onClick={handleClick}
className={`inline-flex items-center justify-center gap-2 px-5 py-2.5 rounded-xl font-semibold text-xs transition-all active:scale-95 disabled:opacity-50 disabled:pointer-events-none ${
clicked ? "ring-2 ring-primary/40 ring-offset-2 ring-offset-background" : ""
} ${className || "bg-primary text-primary-foreground hover:bg-primary/90 shadow-sm"}`}
>
{loading && (
<svg className="animate-spin h-3.5 w-3.5" viewBox="0 0 24 24" fill="none">
<circle className="opacity-25" cx="12" cy="12" r="10" stroke="currentColor" strokeWidth="4" />
<path className="opacity-75" fill="currentColor" d="M4 12a8 8 0 018-8v8H4z" />
</svg>
)}
<span>{children}</span>
</button>
);
} "use client";
import React from "react";
import { motion } from "framer-motion";
export default function AnimatedBtnPink() {
return (
<motion.button
whileHover={{ scale: 1.04 }}
whileTap={{ scale: 0.96 }}
transition={{ type: "spring", stiffness: 400, damping: 20 }}
className="inline-flex items-center justify-center gap-2 px-6 py-3 rounded-xl bg-primary text-primary-foreground font-semibold text-xs shadow-md hover:bg-primary/90 transition-colors"
>
<span>Interactive Motion Button</span>
<motion.span
animate={{ x: [0, 4, 0] }}
transition={{ repeat: Infinity, duration: 1.5, ease: "easeInOut" }}
>
→
</motion.span>
</motion.button>
);
} Teal Button
Install this package in your project before importing the animated component.
npm i framer-motion lucide-react <button class="h-10 px-4 py-2 rounded-md font-medium transition-colors hover:opacity-90 bg-teal-500 text-white">Teal</button> <button className="h-10 px-4 py-2 rounded-md font-medium transition-colors hover:opacity-90 bg-teal-500 text-white">Teal</button> "use client";
import React, { useState } from "react";
interface BtnTealProps extends React.ButtonHTMLAttributes<HTMLButtonElement> {
children?: React.ReactNode;
isLoading?: boolean;
}
export default function BtnTeal({
children = "Click Me",
isLoading: initialLoading = false,
className = "",
...props
}: BtnTealProps) {
const [loading, setLoading] = useState(initialLoading);
const [clicked, setClicked] = useState(false);
const handleClick = (e: React.MouseEvent<HTMLButtonElement>) => {
setClicked(true);
setTimeout(() => setClicked(false), 300);
props.onClick?.(e);
};
return (
<button
{...props}
onClick={handleClick}
className={`inline-flex items-center justify-center gap-2 px-5 py-2.5 rounded-xl font-semibold text-xs transition-all active:scale-95 disabled:opacity-50 disabled:pointer-events-none ${
clicked ? "ring-2 ring-primary/40 ring-offset-2 ring-offset-background" : ""
} ${className || "bg-primary text-primary-foreground hover:bg-primary/90 shadow-sm"}`}
>
{loading && (
<svg className="animate-spin h-3.5 w-3.5" viewBox="0 0 24 24" fill="none">
<circle className="opacity-25" cx="12" cy="12" r="10" stroke="currentColor" strokeWidth="4" />
<path className="opacity-75" fill="currentColor" d="M4 12a8 8 0 018-8v8H4z" />
</svg>
)}
<span>{children}</span>
</button>
);
} "use client";
import React from "react";
import { motion } from "framer-motion";
export default function AnimatedBtnTeal() {
return (
<motion.button
whileHover={{ scale: 1.04 }}
whileTap={{ scale: 0.96 }}
transition={{ type: "spring", stiffness: 400, damping: 20 }}
className="inline-flex items-center justify-center gap-2 px-6 py-3 rounded-xl bg-primary text-primary-foreground font-semibold text-xs shadow-md hover:bg-primary/90 transition-colors"
>
<span>Interactive Motion Button</span>
<motion.span
animate={{ x: [0, 4, 0] }}
transition={{ repeat: Infinity, duration: 1.5, ease: "easeInOut" }}
>
→
</motion.span>
</motion.button>
);
} Primary Outline Button
Install this package in your project before importing the animated component.
npm i framer-motion lucide-react <button class="h-10 px-4 py-2 border bg-transparent rounded-md font-medium hover:bg-accent hover:text-accent-foreground border-primary text-primary">Primary Outline</button> <button className="h-10 px-4 py-2 border bg-transparent rounded-md font-medium hover:bg-accent hover:text-accent-foreground border-primary text-primary">Primary Outline</button> "use client";
import React, { useState } from "react";
interface BtnOutlinePrimaryProps extends React.ButtonHTMLAttributes<HTMLButtonElement> {
children?: React.ReactNode;
isLoading?: boolean;
}
export default function BtnOutlinePrimary({
children = "Click Me",
isLoading: initialLoading = false,
className = "",
...props
}: BtnOutlinePrimaryProps) {
const [loading, setLoading] = useState(initialLoading);
const [clicked, setClicked] = useState(false);
const handleClick = (e: React.MouseEvent<HTMLButtonElement>) => {
setClicked(true);
setTimeout(() => setClicked(false), 300);
props.onClick?.(e);
};
return (
<button
{...props}
onClick={handleClick}
className={`inline-flex items-center justify-center gap-2 px-5 py-2.5 rounded-xl font-semibold text-xs transition-all active:scale-95 disabled:opacity-50 disabled:pointer-events-none ${
clicked ? "ring-2 ring-primary/40 ring-offset-2 ring-offset-background" : ""
} ${className || "bg-primary text-primary-foreground hover:bg-primary/90 shadow-sm"}`}
>
{loading && (
<svg className="animate-spin h-3.5 w-3.5" viewBox="0 0 24 24" fill="none">
<circle className="opacity-25" cx="12" cy="12" r="10" stroke="currentColor" strokeWidth="4" />
<path className="opacity-75" fill="currentColor" d="M4 12a8 8 0 018-8v8H4z" />
</svg>
)}
<span>{children}</span>
</button>
);
} "use client";
import React from "react";
import { motion } from "framer-motion";
export default function AnimatedBtnOutlinePrimary() {
return (
<motion.button
whileHover={{ scale: 1.04 }}
whileTap={{ scale: 0.96 }}
transition={{ type: "spring", stiffness: 400, damping: 20 }}
className="inline-flex items-center justify-center gap-2 px-6 py-3 rounded-xl bg-primary text-primary-foreground font-semibold text-xs shadow-md hover:bg-primary/90 transition-colors"
>
<span>Interactive Motion Button</span>
<motion.span
animate={{ x: [0, 4, 0] }}
transition={{ repeat: Infinity, duration: 1.5, ease: "easeInOut" }}
>
→
</motion.span>
</motion.button>
);
} Secondary Outline Button
Install this package in your project before importing the animated component.
npm i framer-motion lucide-react <button class="h-10 px-4 py-2 border bg-transparent rounded-md font-medium hover:bg-accent hover:text-accent-foreground border-muted-foreground text-muted-foreground">Secondary Outline</button> <button className="h-10 px-4 py-2 border bg-transparent rounded-md font-medium hover:bg-accent hover:text-accent-foreground border-muted-foreground text-muted-foreground">Secondary Outline</button> "use client";
import React, { useState } from "react";
interface BtnOutlineSecondaryProps extends React.ButtonHTMLAttributes<HTMLButtonElement> {
children?: React.ReactNode;
isLoading?: boolean;
}
export default function BtnOutlineSecondary({
children = "Click Me",
isLoading: initialLoading = false,
className = "",
...props
}: BtnOutlineSecondaryProps) {
const [loading, setLoading] = useState(initialLoading);
const [clicked, setClicked] = useState(false);
const handleClick = (e: React.MouseEvent<HTMLButtonElement>) => {
setClicked(true);
setTimeout(() => setClicked(false), 300);
props.onClick?.(e);
};
return (
<button
{...props}
onClick={handleClick}
className={`inline-flex items-center justify-center gap-2 px-5 py-2.5 rounded-xl font-semibold text-xs transition-all active:scale-95 disabled:opacity-50 disabled:pointer-events-none ${
clicked ? "ring-2 ring-primary/40 ring-offset-2 ring-offset-background" : ""
} ${className || "bg-primary text-primary-foreground hover:bg-primary/90 shadow-sm"}`}
>
{loading && (
<svg className="animate-spin h-3.5 w-3.5" viewBox="0 0 24 24" fill="none">
<circle className="opacity-25" cx="12" cy="12" r="10" stroke="currentColor" strokeWidth="4" />
<path className="opacity-75" fill="currentColor" d="M4 12a8 8 0 018-8v8H4z" />
</svg>
)}
<span>{children}</span>
</button>
);
} "use client";
import React from "react";
import { motion } from "framer-motion";
export default function AnimatedBtnOutlineSecondary() {
return (
<motion.button
whileHover={{ scale: 1.04 }}
whileTap={{ scale: 0.96 }}
transition={{ type: "spring", stiffness: 400, damping: 20 }}
className="inline-flex items-center justify-center gap-2 px-6 py-3 rounded-xl bg-primary text-primary-foreground font-semibold text-xs shadow-md hover:bg-primary/90 transition-colors"
>
<span>Interactive Motion Button</span>
<motion.span
animate={{ x: [0, 4, 0] }}
transition={{ repeat: Infinity, duration: 1.5, ease: "easeInOut" }}
>
→
</motion.span>
</motion.button>
);
} Destructive Outline Button
Install this package in your project before importing the animated component.
npm i framer-motion lucide-react <button class="h-10 px-4 py-2 border bg-transparent rounded-md font-medium hover:bg-accent hover:text-accent-foreground border-red-500 text-red-500">Destructive Outline</button> <button className="h-10 px-4 py-2 border bg-transparent rounded-md font-medium hover:bg-accent hover:text-accent-foreground border-red-500 text-red-500">Destructive Outline</button> "use client";
import React, { useState } from "react";
interface BtnOutlineDestructiveProps extends React.ButtonHTMLAttributes<HTMLButtonElement> {
children?: React.ReactNode;
isLoading?: boolean;
}
export default function BtnOutlineDestructive({
children = "Click Me",
isLoading: initialLoading = false,
className = "",
...props
}: BtnOutlineDestructiveProps) {
const [loading, setLoading] = useState(initialLoading);
const [clicked, setClicked] = useState(false);
const handleClick = (e: React.MouseEvent<HTMLButtonElement>) => {
setClicked(true);
setTimeout(() => setClicked(false), 300);
props.onClick?.(e);
};
return (
<button
{...props}
onClick={handleClick}
className={`inline-flex items-center justify-center gap-2 px-5 py-2.5 rounded-xl font-semibold text-xs transition-all active:scale-95 disabled:opacity-50 disabled:pointer-events-none ${
clicked ? "ring-2 ring-primary/40 ring-offset-2 ring-offset-background" : ""
} ${className || "bg-primary text-primary-foreground hover:bg-primary/90 shadow-sm"}`}
>
{loading && (
<svg className="animate-spin h-3.5 w-3.5" viewBox="0 0 24 24" fill="none">
<circle className="opacity-25" cx="12" cy="12" r="10" stroke="currentColor" strokeWidth="4" />
<path className="opacity-75" fill="currentColor" d="M4 12a8 8 0 018-8v8H4z" />
</svg>
)}
<span>{children}</span>
</button>
);
} "use client";
import React from "react";
import { motion } from "framer-motion";
export default function AnimatedBtnOutlineDestructive() {
return (
<motion.button
whileHover={{ scale: 1.04 }}
whileTap={{ scale: 0.96 }}
transition={{ type: "spring", stiffness: 400, damping: 20 }}
className="inline-flex items-center justify-center gap-2 px-6 py-3 rounded-xl bg-primary text-primary-foreground font-semibold text-xs shadow-md hover:bg-primary/90 transition-colors"
>
<span>Interactive Motion Button</span>
<motion.span
animate={{ x: [0, 4, 0] }}
transition={{ repeat: Infinity, duration: 1.5, ease: "easeInOut" }}
>
→
</motion.span>
</motion.button>
);
} Success Outline Button
Install this package in your project before importing the animated component.
npm i framer-motion lucide-react <button class="h-10 px-4 py-2 border bg-transparent rounded-md font-medium hover:bg-accent hover:text-accent-foreground border-green-500 text-green-500">Success Outline</button> <button className="h-10 px-4 py-2 border bg-transparent rounded-md font-medium hover:bg-accent hover:text-accent-foreground border-green-500 text-green-500">Success Outline</button> "use client";
import React, { useState } from "react";
interface BtnOutlineSuccessProps extends React.ButtonHTMLAttributes<HTMLButtonElement> {
children?: React.ReactNode;
isLoading?: boolean;
}
export default function BtnOutlineSuccess({
children = "Click Me",
isLoading: initialLoading = false,
className = "",
...props
}: BtnOutlineSuccessProps) {
const [loading, setLoading] = useState(initialLoading);
const [clicked, setClicked] = useState(false);
const handleClick = (e: React.MouseEvent<HTMLButtonElement>) => {
setClicked(true);
setTimeout(() => setClicked(false), 300);
props.onClick?.(e);
};
return (
<button
{...props}
onClick={handleClick}
className={`inline-flex items-center justify-center gap-2 px-5 py-2.5 rounded-xl font-semibold text-xs transition-all active:scale-95 disabled:opacity-50 disabled:pointer-events-none ${
clicked ? "ring-2 ring-primary/40 ring-offset-2 ring-offset-background" : ""
} ${className || "bg-primary text-primary-foreground hover:bg-primary/90 shadow-sm"}`}
>
{loading && (
<svg className="animate-spin h-3.5 w-3.5" viewBox="0 0 24 24" fill="none">
<circle className="opacity-25" cx="12" cy="12" r="10" stroke="currentColor" strokeWidth="4" />
<path className="opacity-75" fill="currentColor" d="M4 12a8 8 0 018-8v8H4z" />
</svg>
)}
<span>{children}</span>
</button>
);
} "use client";
import React from "react";
import { motion } from "framer-motion";
export default function AnimatedBtnOutlineSuccess() {
return (
<motion.button
whileHover={{ scale: 1.04 }}
whileTap={{ scale: 0.96 }}
transition={{ type: "spring", stiffness: 400, damping: 20 }}
className="inline-flex items-center justify-center gap-2 px-6 py-3 rounded-xl bg-primary text-primary-foreground font-semibold text-xs shadow-md hover:bg-primary/90 transition-colors"
>
<span>Interactive Motion Button</span>
<motion.span
animate={{ x: [0, 4, 0] }}
transition={{ repeat: Infinity, duration: 1.5, ease: "easeInOut" }}
>
→
</motion.span>
</motion.button>
);
} Warning Outline Button
Install this package in your project before importing the animated component.
npm i framer-motion lucide-react <button class="h-10 px-4 py-2 border bg-transparent rounded-md font-medium hover:bg-accent hover:text-accent-foreground border-yellow-500 text-yellow-500">Warning Outline</button> <button className="h-10 px-4 py-2 border bg-transparent rounded-md font-medium hover:bg-accent hover:text-accent-foreground border-yellow-500 text-yellow-500">Warning Outline</button> "use client";
import React, { useState } from "react";
interface BtnOutlineWarningProps extends React.ButtonHTMLAttributes<HTMLButtonElement> {
children?: React.ReactNode;
isLoading?: boolean;
}
export default function BtnOutlineWarning({
children = "Click Me",
isLoading: initialLoading = false,
className = "",
...props
}: BtnOutlineWarningProps) {
const [loading, setLoading] = useState(initialLoading);
const [clicked, setClicked] = useState(false);
const handleClick = (e: React.MouseEvent<HTMLButtonElement>) => {
setClicked(true);
setTimeout(() => setClicked(false), 300);
props.onClick?.(e);
};
return (
<button
{...props}
onClick={handleClick}
className={`inline-flex items-center justify-center gap-2 px-5 py-2.5 rounded-xl font-semibold text-xs transition-all active:scale-95 disabled:opacity-50 disabled:pointer-events-none ${
clicked ? "ring-2 ring-primary/40 ring-offset-2 ring-offset-background" : ""
} ${className || "bg-primary text-primary-foreground hover:bg-primary/90 shadow-sm"}`}
>
{loading && (
<svg className="animate-spin h-3.5 w-3.5" viewBox="0 0 24 24" fill="none">
<circle className="opacity-25" cx="12" cy="12" r="10" stroke="currentColor" strokeWidth="4" />
<path className="opacity-75" fill="currentColor" d="M4 12a8 8 0 018-8v8H4z" />
</svg>
)}
<span>{children}</span>
</button>
);
} "use client";
import React from "react";
import { motion } from "framer-motion";
export default function AnimatedBtnOutlineWarning() {
return (
<motion.button
whileHover={{ scale: 1.04 }}
whileTap={{ scale: 0.96 }}
transition={{ type: "spring", stiffness: 400, damping: 20 }}
className="inline-flex items-center justify-center gap-2 px-6 py-3 rounded-xl bg-primary text-primary-foreground font-semibold text-xs shadow-md hover:bg-primary/90 transition-colors"
>
<span>Interactive Motion Button</span>
<motion.span
animate={{ x: [0, 4, 0] }}
transition={{ repeat: Infinity, duration: 1.5, ease: "easeInOut" }}
>
→
</motion.span>
</motion.button>
);
}