'use client';
import { ButtonHTMLAttributes, useState, useRef, useEffect } from 'react';
export type IconName =
| 'eye'
| 'credit-card'
| 'x-circle'
| 'check'
| 'x'
| 'edit'
| 'copy'
| 'pause'
| 'play'
| 'user-x'
| 'user-check'
| 'external-link'
| 'more'
| 'trash';
interface ActionIconProps extends Omit, 'title'> {
icon: IconName;
variant?: 'primary' | 'ghost' | 'danger';
size?: 'sm' | 'md' | 'lg';
label: string;
onClick?: (e: React.MouseEvent) => void;
}
const ICONS: Record React.ReactNode> = {
eye: (s) => (
),
'credit-card': (s) => (
),
'x-circle': (s) => (
),
check: (s) => (
),
x: (s) => (
),
edit: (s) => (
),
copy: (s) => (
),
pause: (s) => (
),
play: (s) => (
),
'user-x': (s) => (
),
'user-check': (s) => (
),
'external-link': (s) => (
),
more: (s) => (
),
trash: (s) => (
),
};
const VARIANT_STYLES: Record = {
primary:
'text-primary-600 hover:bg-primary-50 hover:text-primary-700 focus-visible:ring-primary-500/30',
ghost:
'text-surface-400 hover:bg-surface-100 hover:text-surface-700 focus-visible:ring-surface-500/30',
danger:
'text-surface-400 hover:bg-red-50 hover:text-red-600 focus-visible:ring-red-500/30',
};
const SIZE_MAP = { sm: 32, md: 36, lg: 40 } as const;
const ICON_SIZE_MAP = { sm: 15, md: 16, lg: 18 } as const;
export function ActionIcon({
icon,
variant = 'ghost',
size = 'sm',
label,
onClick,
className = '',
disabled,
...rest
}: ActionIconProps) {
const [showTooltip, setShowTooltip] = useState(false);
const btnRef = useRef(null);
const timeoutRef = useRef>(null);
useEffect(() => {
return () => {
if (timeoutRef.current) clearTimeout(timeoutRef.current);
};
}, []);
const btnSize = SIZE_MAP[size];
const iconSize = ICON_SIZE_MAP[size];
return (
);
}