import { tv } from 'tailwind-variants'; import { twMerge } from 'tailwind-merge'; import { forwardRef } from 'react'; import { Link } from '@remix-run/react'; import type { LinkProps } from '@remix-run/react'; const button = tv({ base: 'font-sans focus:outline-none focus-visible:ring-2 inline-flex items-center', variants: { size: { md: 'px-6 py-4 text-lg font-medium', base: 'px-4 py-3 text-lg font-medium', sm: 'px-5 py-[0.6875rem] text-base font-medium', xs: 'px-4 py-1.5 text-base', '2xs': 'py-1 px-4 text-base', }, color: { default: 'bg-grey-900 text-white hover:bg-grey-800 shadow-md focus-visible:ring-grey-500 antialiased', grey: 'bg-grey-200 text-grey-900 focus-visible:ring-grey-300 ', red: 'bg-red-light text-error-700 focus-visible:ring-error-200', transparent: 'bg-transparent border font-thin border-solid border-grey-200 text-grey-900', }, disabled: { true: 'bg-grey-100 text-grey-800/40 pointer-events-none shadow-none', }, roundness: { default: 'rounded-[0.875rem]', lg: 'rounded-3xl', }, //Use in compound variants startIcon: { true: '', false: '', }, //Use in compound variants endIcon: { true: '', false: '', }, }, compoundVariants: [ { size: ['sm', 'xs', '2xs'], roundness: 'default', className: 'rounded-xl', }, { size: 'md', startIcon: true, className: 'pl-4' }, { size: 'md', endIcon: true, className: 'pr-4' }, { size: 'base', startIcon: true, className: 'pl-3' }, { size: 'base', endIcon: true, className: 'pr-3' }, { size: 'sm', startIcon: true, className: 'pl-4' }, { size: 'sm', endIcon: true, className: 'pr-4' }, { size: 'xs', startIcon: true, className: 'pl-3' }, { size: 'xs', endIcon: true, className: 'pr-3' }, { size: '2xs', startIcon: true, className: 'pl-3' }, { size: '2xs', endIcon: true, className: 'pr-3' }, ], }); const iconContainerBase = tv({ base: 'w-6 h-6 inline-flex items-center justify-center relative top-[1px]', }); const iconStartContainer = tv({ extend: iconContainerBase, variants: { size: { md: 'mr-2', base: 'mr-2', sm: 'mr-1', xs: 'mr-1 w-5 h-5', '2xs': 'mr-1 w-4 h-4', }, }, compoundVariants: [ { size: 'sm', roundness: 'lg', className: 'w-5 h-5', }, ], }); const iconEndContainer = tv({ extend: iconContainerBase, variants: { size: { md: 'ml-2', base: 'ml-2', sm: 'ml-1', xs: 'ml-1 w-5 h-5', '2xs': 'ml-1 w-4 h-4', }, roundness: { default: '', lg: '', }, }, compoundVariants: [ { size: 'sm', roundness: 'lg', className: 'w-5 h-5 -top-[1px]', }, ], }); type BaseButtonProps = { /** * How large should the button be? */ size?: 'md' | 'base' | 'sm' | 'xs' | '2xs'; /** * What color to use? */ color?: 'default' | 'grey' | 'red' | 'transparent'; /** * Is button disabled? */ disabled?: boolean; /** * How rounded the button should be */ roundness?: 'default' | 'lg'; /** * An icon before the button's label. */ startIcon?: React.ReactElement; /** * An icon after the button's label. */ endIcon?: React.ReactElement; }; type ButtonProps = BaseButtonProps & React.ComponentPropsWithRef<'button'>; type AnchorProps = BaseButtonProps & React.ComponentPropsWithRef<'a'>; type LinkButtonProps = BaseButtonProps & LinkProps; export const LinkButton = forwardRef(function LinkButton( { children, className, color = 'default', size = 'base', roundness = 'default', disabled, startIcon, endIcon, ...other }, ref, ) { return ( {startIcon ? {startIcon} : null} {children} {endIcon ? {endIcon} : null} ); }); export const Button = forwardRef(function Button( { children, className, color = 'default', size = 'base', roundness = 'default', disabled, startIcon, endIcon, ...other }, forwardedRef, ) { return ( ); }); export const AnchorButton = forwardRef(function Button( { children, className, color = 'default', size = 'base', roundness = 'default', disabled, startIcon, endIcon, ...other }, forwardedRef, ) { return ( {startIcon ? {startIcon} : null} {children} {endIcon ? {endIcon} : null} ); });