import type { ForwardedRef } from 'react'; import React from 'react'; export type ButtonType = | 'default' | 'primary' | 'danger' | 'warning' | 'success' | 'ghost'; // Helper type to override types (overrides onClick) type MergeElementProps< T extends React.ElementType, P extends Record > = Omit, keyof P> & P; type ElementTypes = 'button' | 'a'; type Element

= P extends 'a' ? HTMLAnchorElement : HTMLButtonElement; type BaseProps

= { buttonType?: ButtonType; buttonSize?: 'default' | 'lg' | 'md' | 'sm'; // Had to do declare this manually as typescript would assume e was of type any otherwise onClick?: ( e: React.MouseEvent

) => void; }; type ButtonProps

= { as?: P; } & MergeElementProps>; function Button

( { buttonType = 'default', buttonSize = 'default', as, children, className, ...props }: ButtonProps

, ref?: React.Ref> ): JSX.Element { const buttonStyle = [ 'inline-flex items-center justify-center border border-transparent leading-5 font-medium rounded-md focus:outline-none transition ease-in-out duration-150 cursor-pointer disabled:opacity-50 whitespace-nowrap', ]; switch (buttonType) { case 'primary': buttonStyle.push( 'text-white bg-indigo-600 border-indigo-600 hover:bg-indigo-500 hover:border-indigo-500 focus:border-indigo-700 focus:ring-indigo active:bg-indigo-700 active:border-indigo-700' ); break; case 'danger': buttonStyle.push( 'text-white bg-red-600 border-red-600 hover:bg-red-500 hover:border-red-500 focus:border-red-700 focus:ring-red active:bg-red-700 active:border-red-700' ); break; case 'warning': buttonStyle.push( 'text-white bg-yellow-500 border-yellow-500 hover:bg-yellow-400 hover:border-yellow-400 focus:border-yellow-700 focus:ring-yellow active:bg-yellow-700 active:border-yellow-700' ); break; case 'success': buttonStyle.push( 'text-white bg-green-500 border-green-500 hover:bg-green-400 hover:border-green-400 focus:border-green-700 focus:ring-green active:bg-green-700 active:border-green-700' ); break; case 'ghost': buttonStyle.push( 'text-white bg-transaprent border-gray-600 hover:border-gray-200 focus:border-gray-100 active:border-gray-100' ); break; default: buttonStyle.push( 'text-gray-200 bg-gray-600 border-gray-600 hover:text-white hover:bg-gray-500 hover:border-gray-500 group-hover:text-white group-hover:bg-gray-500 group-hover:border-gray-500 focus:border-blue-300 focus:ring-blue active:text-gray-200 active:bg-gray-500 active:border-gray-500' ); } switch (buttonSize) { case 'sm': buttonStyle.push('px-2.5 py-1.5 text-xs button-sm'); break; case 'lg': buttonStyle.push('px-6 py-3 text-base button-lg'); break; case 'md': default: buttonStyle.push('px-4 py-2 text-sm button-md'); } buttonStyle.push(className ?? ''); if (as === 'a') { return ( )} ref={ref as ForwardedRef} > {children} ); } else { return ( ); } } export default React.forwardRef(Button) as typeof Button;