'use client'; import { ReactNode, useState } from 'react'; import { LucideIcon, Loader2 } from 'lucide-react'; import { cn } from '@/lib/utils'; interface ActionButtonProps { children: ReactNode; onClick?: () => void | Promise; variant?: 'primary' | 'secondary' | 'danger' | 'success' | 'export'; size?: 'sm' | 'md' | 'lg'; icon?: LucideIcon; disabled?: boolean; loading?: boolean; className?: string; type?: 'button' | 'submit' | 'reset'; /** * Native tooltip. CLAUDE.md asks for a disabled control with a visible reason * over a silently hidden one, so permission-gated buttons pass the reason here * alongside `disabled`. */ title?: string; } const variants = { primary: 'bg-[rgb(20,113,76)] text-white hover:bg-[rgb(16,90,61)] shadow-sm', secondary: 'bg-muted text-foreground hover:bg-muted/80 border border-border/60', danger: 'bg-red-600 text-white hover:bg-red-700 shadow-sm', success: 'bg-green-600 text-white hover:bg-green-700 shadow-sm', export: 'bg-[rgb(20,113,76)] text-white hover:bg-[rgb(16,90,61)] shadow-sm', }; const sizes = { sm: 'px-3 py-1.5 text-sm', md: 'px-4 py-2 text-sm', lg: 'px-6 py-3 text-base', }; export default function ActionButton({ children, onClick, variant = 'primary', size = 'md', icon: Icon, disabled = false, loading = false, className, type = 'button', title, }: ActionButtonProps) { const [isLoading, setIsLoading] = useState(false); const handleClick = async () => { if (!onClick || disabled || loading || isLoading) return; try { setIsLoading(true); await onClick(); } catch (error) { } finally { setIsLoading(false); } }; const isDisabled = disabled || loading || isLoading; const showLoading = loading || isLoading; return ( ); }