Button Copy
smoothui-registry/button-copyFreeComponent
A ButtonCopy component for SmoothUI.
Install it
npx shadcn@latest add https://www.smoothui.dev/r/button-copy.jsonSource
1"use client";23import { Check, Copy, LoaderCircle } from "lucide-react";4import { AnimatePresence, motion, useReducedMotion } from "motion/react";5import { type ReactNode, useCallback, useState } from "react";67export interface ButtonCopyProps {8 className?: string;9 disabled?: boolean;10 duration?: number;11 idleIcon?: ReactNode;12 loadingDuration?: number;13 loadingIcon?: ReactNode;14 onCopy?: () => Promise<void> | void;15 successIcon?: ReactNode;16}1718const defaultIcons = {19 idle: <Copy size={16} />,20 loading: <LoaderCircle className="animate-spin" size={16} />,21 success: <Check size={16} />,22};2324export default function ButtonCopy({25 onCopy,26 idleIcon = defaultIcons.idle,27 loadingIcon = defaultIcons.loading,28 successIcon = defaultIcons.success,29 className = "",30 duration = 2000,31 loadingDuration = 1000,32 disabled = false,33}: ButtonCopyProps) {34 const [buttonState, setButtonState] = useState<35 "idle" | "loading" | "success"36 >("idle");37 const shouldReduceMotion = useReducedMotion();3839 const handleClick = useCallback(async () => {40 setButtonState("loading");41 if (onCopy) {42 await onCopy();43 }44 setTimeout(() => {45 setButtonState("success");46 }, loadingDuration);47 setTimeout(() => {48 setButtonState("idle");49 }, loadingDuration + duration);50 }, [onCopy, loadingDuration, duration]);5152 const icons = {53 idle: idleIcon,54 loading: loadingIcon,55 success: successIcon,56 };5758 const ariaLabels = {59 idle: "Copy",60 loading: "Copying...",61 success: "Copied",62 };6364 return (65 <div className="flex justify-center">66 <button67 aria-label={ariaLabels[buttonState]}68 aria-live="polite"69 className={`relative min-h-[44px] w-auto min-w-[44px] cursor-pointer overflow-hidden rounded-full border bg-background p-3 focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:opacity-50 ${className}`}70 disabled={buttonState !== "idle" || disabled}71 onClick={handleClick}72 type="button"73 >74 <AnimatePresence initial={false} mode="popLayout">75 <motion.span76 animate={77 shouldReduceMotion78 ? { opacity: 1 }79 : { filter: "blur(0px)", opacity: 1, y: 0 }80 }81 className="flex w-full items-center justify-center"82 exit={83 shouldReduceMotion84 ? { opacity: 0, transition: { duration: 0 } }85// … truncated
What it pulls in
npm packages
Files it writes
More from SmoothUI Registry
All 177 items| Component | Registry | Kind | Access | Installs | Command |
|---|---|---|---|---|---|
| Agent Avataragent-avatar | SmoothUI Registry | Components | Free | no deps | |
| Ai Approvalai-approval | SmoothUI Registry | Components | Free | 2 deps | |
| Ai Artifactai-artifact | SmoothUI Registry | Components | Free | 2 deps | |
| Ai Branchai-branch | SmoothUI Registry | Components | Free | 2 deps | |
| Ai Citationai-citation | SmoothUI Registry | Components | Free | 2 deps | |
| Ai Context Meterai-context-meter | SmoothUI Registry | Components | Free | 2 deps | |
| Ai Conversationai-conversation | SmoothUI Registry | Components | Free | 2 deps | |
| Ai Coreai-core | SmoothUI Registry | Components | Free | 1 dep |
