89 lines
1.9 KiB
TypeScript
89 lines
1.9 KiB
TypeScript
import { useState } from 'react';
|
|
import { Button } from '@/components/ui/button';
|
|
import { type SharePlatform, getPlatformLabel } from '@/lib/social-utils';
|
|
import {
|
|
Facebook,
|
|
Twitter,
|
|
MessageCircle,
|
|
Send,
|
|
Mail,
|
|
Link,
|
|
Share2
|
|
} from 'lucide-react';
|
|
|
|
interface ShareButtonProps {
|
|
platform: SharePlatform;
|
|
onClick: () => void;
|
|
disabled?: boolean;
|
|
size?: 'sm' | 'default' | 'lg';
|
|
variant?: 'default' | 'outline' | 'ghost';
|
|
className?: string;
|
|
showLabel?: boolean;
|
|
}
|
|
|
|
export function ShareButton({
|
|
platform,
|
|
onClick,
|
|
disabled = false,
|
|
size = 'default',
|
|
variant = 'outline',
|
|
className = '',
|
|
showLabel = false,
|
|
}: ShareButtonProps) {
|
|
const [isLoading, setIsLoading] = useState(false);
|
|
|
|
const handleClick = async () => {
|
|
if (disabled || isLoading) return;
|
|
|
|
setIsLoading(true);
|
|
try {
|
|
await onClick();
|
|
} finally {
|
|
setIsLoading(false);
|
|
}
|
|
};
|
|
|
|
const label = getPlatformLabel(platform);
|
|
|
|
// Get the appropriate icon component
|
|
const getIconComponent = () => {
|
|
switch (platform) {
|
|
case 'facebook':
|
|
return Facebook;
|
|
case 'twitter':
|
|
return Twitter;
|
|
case 'whatsapp':
|
|
return MessageCircle;
|
|
case 'telegram':
|
|
return Send;
|
|
case 'email':
|
|
return Mail;
|
|
case 'link':
|
|
return Link;
|
|
default:
|
|
return Share2;
|
|
}
|
|
};
|
|
|
|
const IconComponent = getIconComponent();
|
|
|
|
return (
|
|
<Button
|
|
type="button"
|
|
variant={variant}
|
|
size={size}
|
|
onClick={handleClick}
|
|
disabled={disabled || isLoading}
|
|
className={`relative ${className}`}
|
|
aria-label={label}
|
|
title={label}
|
|
>
|
|
{isLoading ? (
|
|
<div className="animate-spin rounded-full h-4 w-4 border-b-2 border-current" />
|
|
) : (
|
|
<IconComponent className="h-4 w-4" />
|
|
)}
|
|
{showLabel && <span className="ml-2">{label}</span>}
|
|
</Button>
|
|
);
|
|
} |