import clsx from 'clsx'; import Link from 'next/link'; import type { UrlObject } from 'url'; import Spinner from '../Spinner'; export type ButtonAddOnPosition = 'end' | 'start'; export type ButtonDisplay = 'block' | 'inline'; export type ButtonSize = 'lg' | 'md' | 'sm'; export type ButtonType = 'button' | 'reset' | 'submit'; export type ButtonVariant = | 'primary' | 'secondary' | 'special' | 'success' | 'tertiary'; type Props = Readonly<{ addonPosition?: ButtonAddOnPosition; 'aria-controls'?: string; className?: string; display?: ButtonDisplay; href?: UrlObject | string; icon?: (props: React.ComponentProps<'svg'>) => JSX.Element; isDisabled?: boolean; isLabelHidden?: boolean; isLoading?: boolean; label: string; onClick?: (event: React.MouseEvent) => void; size?: ButtonSize; type?: ButtonType; variant: ButtonVariant; }>; const sizeClasses: Record = { lg: 'px-5 py-2.5', md: 'px-4 py-2', sm: 'px-2.5 py-1.5', }; const iconOnlySizeClasses: Record = { lg: 'p-3', md: 'p-2', sm: 'p-1.5', }; const baseClasses: Record = { lg: 'text-base rounded-xl', md: 'text-sm rounded-lg', sm: 'text-xs rounded-md', }; const sizeIconSpacingEndClasses: Record = { lg: 'ml-3 -mr-1 ', md: 'ml-2 -mr-1 ', sm: 'ml-2 -mr-0.5', }; const sizeIconSpacingStartClasses: Record = { lg: 'mr-3 -ml-1 ', md: 'mr-2 -ml-1 ', sm: 'mr-2 -ml-0.5', }; const sizeIconClasses: Record = { lg: '!h-5 !w-5', md: '!h-5 !w-5', sm: '!h-4 !w-4', }; const variantClasses: Record = { primary: 'border-transparent text-white bg-primary-600 hover:bg-primary-500', secondary: 'border-transparent text-primary-700 bg-primary-100 hover:bg-primary-200', special: 'border-slate-900 text-white bg-slate-900 hover:bg-slate-700', success: 'border-transparent text-white bg-emerald-600 hover:bg-emerald-500', tertiary: 'border-slate-300 text-slate-700 bg-white hover:bg-slate-50', }; const variantDisabledClasses: Record = { primary: 'border-transparent text-slate-500 bg-slate-300', secondary: 'border-transparent text-slate-400 bg-slate-200', special: 'border-transparent text-slate-500 bg-slate-300', success: 'border-transparent text-slate-500 bg-slate-300', tertiary: 'border-slate-300 text-slate-400 bg-slate-100', }; export default function Button({ addonPosition = 'end', 'aria-controls': ariaControls, className, display = 'inline', href, icon: Icon, isDisabled = false, isLabelHidden = false, isLoading = false, label, size = 'md', type = 'button', variant, onClick, }: Props) { const iconSpacingClass = (() => { if (!isLabelHidden && addonPosition === 'start') { return sizeIconSpacingStartClasses[size]; } if (!isLabelHidden && addonPosition === 'end') { return sizeIconSpacingEndClasses[size]; } })(); const addOnClass = clsx(iconSpacingClass, sizeIconClasses[size]); const addOn = isLoading ? ( ) : Icon != null ? (