import * as React from 'react' type Variant = 'primary' | 'secondary' | 'soft' type Size = 'xs' | 'sm' | 'md' | 'lg' type Color = 'indigo' | 'blue' | 'emerald' | 'red' | 'amber' export type ButtonProps = Omit< React.ButtonHTMLAttributes, 'children' > & { children: React.ReactNode variant?: Variant size?: Size color?: Color rounded?: 'sm' | 'md' | 'full' leadingIcon?: React.ReactNode trailingIcon?: React.ReactNode isLoading?: boolean className?: string } function cn(...parts: Array) { return parts.filter(Boolean).join(' ') } const base = 'inline-flex items-center justify-center font-semibold focus-visible:outline-2 focus-visible:outline-offset-2 disabled:opacity-50 disabled:cursor-not-allowed' const roundedMap = { sm: 'rounded-sm', md: 'rounded-md', full: 'rounded-full', } as const const sizeMap: Record = { xs: 'px-2 py-1 text-xs', sm: 'px-2.5 py-1.5 text-sm', md: 'px-3 py-2 text-sm', lg: 'px-3.5 py-2.5 text-sm', } const colorMap: Record> = { indigo: { primary: '!bg-indigo-600 !text-white shadow-sm hover:!bg-indigo-700 focus-visible:outline-indigo-600 ' + 'dark:!bg-indigo-500 dark:hover:!bg-indigo-400 dark:focus-visible:outline-indigo-500', secondary: 'bg-white text-gray-900 shadow-xs inset-ring inset-ring-gray-300 hover:bg-gray-50 ' + 'dark:bg-white/10 dark:text-white dark:shadow-none dark:inset-ring-white/5 dark:hover:bg-white/20', soft: 'bg-indigo-50 text-indigo-600 shadow-xs hover:bg-indigo-100 ' + 'dark:bg-indigo-500/20 dark:text-indigo-400 dark:shadow-none dark:hover:bg-indigo-500/30', }, blue: { primary: '!bg-blue-600 !text-white shadow-sm hover:!bg-blue-700 focus-visible:outline-blue-600 ' + 'dark:!bg-blue-500 dark:hover:!bg-blue-400 dark:focus-visible:outline-blue-500', secondary: 'bg-white text-gray-900 shadow-xs inset-ring inset-ring-gray-300 hover:bg-gray-50 ' + 'dark:bg-white/10 dark:text-white dark:shadow-none dark:inset-ring-white/5 dark:hover:bg-white/20', soft: 'bg-blue-50 text-blue-600 shadow-xs hover:bg-blue-100 ' + 'dark:bg-blue-500/20 dark:text-blue-400 dark:shadow-none dark:hover:bg-blue-500/30', }, emerald: { primary: '!bg-emerald-600 !text-white shadow-sm hover:!bg-emerald-700 focus-visible:outline-emerald-600 ' + 'dark:!bg-emerald-500 dark:hover:!bg-emerald-400 dark:focus-visible:outline-emerald-500', secondary: 'bg-white text-gray-900 shadow-xs inset-ring inset-ring-gray-300 hover:bg-gray-50 ' + 'dark:bg-white/10 dark:text-white dark:shadow-none dark:inset-ring-white/5 dark:hover:bg-white/20', soft: 'bg-emerald-50 text-emerald-700 shadow-xs hover:bg-emerald-100 ' + 'dark:bg-emerald-500/20 dark:text-emerald-400 dark:shadow-none dark:hover:bg-emerald-500/30', }, red: { primary: '!bg-red-600 !text-white shadow-sm hover:!bg-red-700 focus-visible:outline-red-600 ' + 'dark:!bg-red-500 dark:hover:!bg-red-400 dark:focus-visible:outline-red-500', secondary: 'bg-white text-gray-900 shadow-xs inset-ring inset-ring-gray-300 hover:bg-gray-50 ' + 'dark:bg-white/10 dark:text-white dark:shadow-none dark:inset-ring-white/5 dark:hover:bg-white/20', soft: 'bg-red-50 text-red-700 shadow-xs hover:bg-red-100 ' + 'dark:bg-red-500/20 dark:text-red-400 dark:shadow-none dark:hover:bg-red-500/30', }, amber: { primary: '!bg-amber-500 !text-white shadow-sm hover:!bg-amber-600 focus-visible:outline-amber-500 ' + 'dark:!bg-amber-500 dark:hover:!bg-amber-400 dark:focus-visible:outline-amber-500', secondary: 'bg-white text-gray-900 shadow-xs inset-ring inset-ring-gray-300 hover:bg-gray-50 ' + 'dark:bg-white/10 dark:text-white dark:shadow-none dark:inset-ring-white/5 dark:hover:bg-white/20', soft: 'bg-amber-50 text-amber-800 shadow-xs hover:bg-amber-100 ' + 'dark:bg-amber-500/20 dark:text-amber-300 dark:shadow-none dark:hover:bg-amber-500/30', }, } function Spinner() { return ( ) } export default function Button({ children, variant = 'primary', color = 'indigo', size = 'md', rounded = 'md', leadingIcon, trailingIcon, isLoading = false, disabled, className, type = 'button', ...props }: ButtonProps) { const iconGap = leadingIcon || trailingIcon || isLoading ? 'gap-x-1.5' : '' return ( ) }