xcn
componentmotion-btnsource: ok · hit
Motion Button
A button component with a motion effect.
npx shadcn add "https://ui.radiumcoders.com/r/xcn/motion-btn.json"free
No selection tags yet — empty means no evidence, not lack of support.
Dependencies
Bundle weight · mediumanimationmotion
Files1 · source cached 10/8/2026, 9:03:04 PM
components/xcn/motion-btn.tsx
import { cn } from "@/lib/utils"
import { motion } from "motion/react"
import { useState } from "react"
export const MotionBtn = ({
children,
className,
tapDuration = 500,
}: {
children: React.ReactNode
className?: string
tapDuration?: number
}) => {
const [isTapped, setIsTapped] = useState(false)
const handleTap = () => {
if (isTapped) return
setIsTapped(true)
setTimeout(() => setIsTapped(false), tapDuration)
}
const state = isTapped ? "tap" : "rest"
return (
<motion.div
initial="rest"
animate={state}
whileHover={isTapped ? "tap" : "hover"}
onTap={handleTap}
className="relative inline-block cursor-pointer"
>
{/* Corner brackets */}
{[
{ corner: "top-right", cls: "absolute top-0 right-0 size-2 border-t border-r z-20" },
{ corner: "top-left", cls: "absolute top-0 left-0 size-2 border-t border-l z-20" },
{ corner: "bottom-left", cls: "absolute bottom-0 left-0 size-2 border-b border-l z-20" },
{ corner: "bottom-right", cls: "absolute right-0 bottom-0 size-2 border-r border-b z-20" },
].map(({ corner, cls }) => (
<motion.div
key={corner}
custom={corner}
variants={{
rest: () => ({ x: 0, y: 0, borderColor: "rgb(38 38 38)" }),
hover: (c: string) => ({
x: c.includes("right") ? 3 : -3,
y: c.includes("bottom") ? 3 : -3,
borderColor: "rgb(38 38 38)",
}),
tap: (c: string) => ({
x: c.includes("right") ? -2 : 2,
y: c.includes("bottom") ? -2 : 2,
borderColor: "#2CD4BD",
}),
}}
transition={{ type: "spring", stiffness: 300, damping: 20 }}
className={cls}
/>
))}
<button
className={cn("relative px-10 py-3 font-medium uppercase overflow-hidden", className)}
>
{/* Pattern */}
<span className="absolute inset-0 z-0 bg-[repeating-linear-gradient(315deg,var(--pattern)_0,var(--pattern)_1px,transparent_0,transparent_50%)] bg-size-[7px_7px]" />
{/* Arm panel */}
<motion.span
variants={{
rest: { scaleX: 0, originX: 0, backgroundColor: "#171717" },
hover: { scaleX: 1, originX: 0, backgroundColor: "#171717" },
tap: { scaleX: 1, originX: 0, backgroundColor: "#2CD4BD" },
}}
transition={{ type: "spring", stiffness: 220, damping: 22 }}
className="absolute inset-0 z-10 origin-left"
/>
{/* Text */}
<motion.span
variants={{
rest: { color: "var(--color-foreground)" },
hover: { color: "#ffffff" },
tap: { color: "#0a2926" },
}}
transition={{ type: "spring", stiffness: 220, damping: 22 }}
className="relative z-20"
>
{children}
</motion.span>
</button>
</motion.div>
)
}