Spaces:
Build error
Build error
import { cva, VariantProps } from 'class-variance-authority'; | |
import * as React from 'react'; | |
import { cn, ComponentAnatomy, defineStyleAnatomy } from '../core/styling'; | |
/* ------------------------------------------------------------------------------------------------- | |
* Anatomy | |
* -----------------------------------------------------------------------------------------------*/ | |
export const ButtonAnatomy = defineStyleAnatomy({ | |
root: cva( | |
[ | |
'UI-Button_root', | |
'shadow-sm whitespace-nowrap font-semibold rounded-[--radius]', | |
'inline-flex items-center text-white transition ease-in text-center text-base justify-center', | |
'focus-visible:outline-none focus-visible:ring-2 ring-offset-1 ring-offset-[--background] focus-visible:ring-[--ring]', | |
'disabled:opacity-50 disabled:pointer-events-none', | |
], | |
{ | |
variants: { | |
intent: { | |
primary: | |
'bg-brand-500 hover:bg-brand-600 active:bg-brand-700 border border-transparent', | |
'primary-outline': | |
'text-[--brand] border border-[--brand] bg-transparent hover:bg-brand-500 active:bg-brand-600 active:border-transparent hover:text-white dark:hover:border-brand-500 dark:active:bg-brand-600 dark:hover:text-white dark:active:border-transparent dark:active:text-white', | |
'primary-subtle': | |
'shadow-none text-[--brand] border bg-brand-50 border-transparent hover:bg-brand-100 active:bg-brand-200 dark:bg-opacity-10 dark:hover:bg-opacity-20', | |
'primary-link': | |
'shadow-none text-[--brand] border border-transparent bg-transparent hover:underline active:text-brand-700 dark:active:text-brand-300', | |
'primary-basic': | |
'shadow-none text-[--brand] border border-transparent bg-transparent hover:bg-brand-100 active:bg-brand-200 dark:hover:bg-opacity-10 dark:active:text-brand-300', | |
warning: | |
'bg-orange-500 hover:bg-orange-600 active:bg-orange-700 border border-transparent', | |
'warning-outline': | |
'text-[--orange] border border-[--orange] bg-transparent hover:bg-orange-500 active:bg-orange-600 active:border-transparent hover:text-white dark:hover:border-orange-500 dark:active:bg-orange-600 dark:hover:text-white dark:active:border-transparent dark:active:text-white', | |
'warning-subtle': | |
'shadow-none text-[--orange] border bg-orange-50 border-transparent hover:bg-orange-100 active:bg-orange-200 dark:bg-opacity-10 dark:hover:bg-opacity-20', | |
'warning-link': | |
'shadow-none text-[--orange] border border-transparent bg-transparent hover:underline active:text-orange-700 dark:active:text-orange-300', | |
'warning-basic': | |
'shadow-none text-[--orange] border border-transparent bg-transparent hover:bg-orange-100 active:bg-orange-200 dark:hover:bg-opacity-10 dark:active:text-orange-300', | |
success: | |
'bg-green-500 hover:bg-green-600 active:bg-green-700 border border-transparent', | |
'success-outline': | |
'text-[--green] border border-[--green] bg-transparent hover:bg-green-500 active:bg-green-600 active:border-transparent hover:text-white dark:hover:border-green-500 dark:active:bg-green-600 dark:hover:text-white dark:active:border-transparent dark:active:text-white', | |
'success-subtle': | |
'shadow-none text-[--green] border bg-green-50 border-transparent hover:bg-green-100 active:bg-green-200 dark:bg-opacity-10 dark:hover:bg-opacity-20', | |
'success-link': | |
'shadow-none text-[--green] border border-transparent bg-transparent hover:underline active:text-green-700 dark:active:text-green-300', | |
'success-basic': | |
'shadow-none text-[--green] border border-transparent bg-transparent hover:bg-green-100 active:bg-green-200 dark:hover:bg-opacity-10 dark:active:text-green-300', | |
alert: | |
'bg-red-500 hover:bg-red-600 active:bg-red-700 border border-transparent', | |
'alert-outline': | |
'text-[--red] border border-[--red] bg-transparent hover:bg-red-500 active:bg-red-600 active:border-transparent hover:text-white dark:hover:border-red-500 dark:active:bg-red-600 dark:hover:text-white dark:active:border-transparent dark:active:text-white', | |
'alert-subtle': | |
'shadow-none text-[--red] border bg-red-50 border-transparent hover:bg-red-100 active:bg-red-200 dark:bg-opacity-10 dark:hover:bg-opacity-20', | |
'alert-link': | |
'shadow-none text-[--red] border border-transparent bg-transparent hover:underline active:text-red-700 dark:active:text-red-300', | |
'alert-basic': | |
'shadow-none text-[--red] border border-transparent bg-transparent hover:bg-red-100 active:bg-red-200 dark:hover:bg-opacity-10 dark:active:text-red-300', | |
gray: 'bg-gray-500 hover:bg-gray-600 active:bg-gray-700 border border-transparent', | |
'gray-outline': | |
'text-gray-600 border bg-transparent hover:bg-gray-100 active:border-transparent active:bg-gray-200 dark:text-gray-300 dark: dark:hover:bg-gray-800 dark:hover:bg-opacity-50 dark:active:bg-gray-700 dark:active:border-transparent dark:hover:text-gray-100', | |
'gray-subtle': | |
'shadow-none text-[--gray] border bg-gray-100 border-transparent hover:bg-gray-200 active:bg-gray-300 dark:text-gray-300 dark:bg-opacity-10 dark:hover:bg-opacity-20', | |
'gray-link': | |
'shadow-none text-[--gray] border border-transparent bg-transparent hover:underline active:text-gray-700 dark:text-gray-300 dark:active:text-gray-200', | |
'gray-basic': | |
'shadow-none text-[--gray] border border-transparent bg-transparent hover:bg-gray-100 active:bg-gray-200 dark:active:bg-opacity-20 dark:text-gray-200 dark:hover:bg-opacity-10 dark:active:text-gray-200', | |
white: | |
'text-[#000] bg-white hover:bg-gray-200 active:bg-gray-300 border border-transparent', | |
'white-outline': | |
'text-white border border-gray-200 bg-transparent hover:bg-white hover:text-black active:bg-gray-100 active:text-[#000]', | |
'white-subtle': | |
'shadow-none text-white bg-white bg-opacity-15 hover:bg-opacity-20 border border-transparent active:bg-opacity-25', | |
'white-link': | |
'shadow-none text-white border border-transparent bg-transparent hover:underline active:text-gray-200', | |
'white-basic': | |
'shadow-none text-white border border-transparent bg-transparent hover:bg-white hover:bg-opacity-15 active:bg-opacity-20 active:text-white-300', | |
}, | |
rounded: { | |
true: 'rounded-full', | |
false: null, | |
}, | |
contentWidth: { | |
true: 'w-fit', | |
false: null, | |
}, | |
size: { | |
xs: 'text-sm h-6 px-2', | |
sm: 'text-sm h-8 px-3', | |
md: 'text-sm h-10 px-4', | |
lg: 'h-12 px-6 text-lg', | |
xl: 'text-2xl h-14 px-8', | |
}, | |
}, | |
defaultVariants: { | |
intent: 'primary', | |
size: 'md', | |
}, | |
} | |
), | |
icon: cva(['UI-Button__icon', 'inline-flex self-center flex-shrink-0']), | |
}); | |
/* ------------------------------------------------------------------------------------------------- | |
* Button | |
* -----------------------------------------------------------------------------------------------*/ | |
export type ButtonProps = React.ComponentPropsWithoutRef<'button'> & | |
VariantProps<typeof ButtonAnatomy.root> & | |
ComponentAnatomy<typeof ButtonAnatomy> & { | |
loading?: boolean; | |
leftIcon?: React.ReactNode; | |
rightIcon?: React.ReactNode; | |
iconSpacing?: React.CSSProperties['marginInline']; | |
hideTextOnSmallScreen?: boolean; | |
hideTextOnLargeScreen?: boolean; | |
}; | |
export const Button = React.forwardRef<HTMLButtonElement, ButtonProps>( | |
(props, ref) => { | |
const { | |
children, | |
size, | |
className, | |
rounded = false, | |
contentWidth = false, | |
intent, | |
leftIcon, | |
rightIcon, | |
iconSpacing = '0.5rem', | |
loading, | |
iconClass, | |
disabled, | |
hideTextOnSmallScreen, | |
hideTextOnLargeScreen, | |
...rest | |
} = props; | |
return ( | |
<button | |
type="button" | |
className={cn( | |
ButtonAnatomy.root({ | |
size, | |
intent, | |
rounded, | |
contentWidth, | |
}), | |
className | |
)} | |
disabled={disabled || loading} | |
aria-disabled={disabled} | |
{...rest} | |
ref={ref} | |
> | |
{loading ? ( | |
<> | |
<svg | |
width="15" | |
height="15" | |
fill="currentColor" | |
className="animate-spin" | |
viewBox="0 0 1792 1792" | |
xmlns="http://www.w3.org/2000/svg" | |
style={{ | |
marginInlineEnd: !hideTextOnSmallScreen ? iconSpacing : 0, | |
}} | |
> | |
<path d="M526 1394q0 53-37.5 90.5t-90.5 37.5q-52 0-90-38t-38-90q0-53 37.5-90.5t90.5-37.5 90.5 37.5 37.5 90.5zm498 206q0 53-37.5 90.5t-90.5 37.5-90.5-37.5-37.5-90.5 37.5-90.5 90.5-37.5 90.5 37.5 37.5 90.5zm-704-704q0 53-37.5 90.5t-90.5 37.5-90.5-37.5-37.5-90.5 37.5-90.5 90.5-37.5 90.5 37.5 37.5 90.5zm1202 498q0 52-38 90t-90 38q-53 0-90.5-37.5t-37.5-90.5 37.5-90.5 90.5-37.5 90.5 37.5 37.5 90.5zm-964-996q0 66-47 113t-113 47-113-47-47-113 47-113 113-47 113 47 47 113zm1170 498q0 53-37.5 90.5t-90.5 37.5-90.5-37.5-37.5-90.5 37.5-90.5 90.5-37.5 90.5 37.5 37.5 90.5zm-640-704q0 80-56 136t-136 56-136-56-56-136 56-136 136-56 136 56 56 136zm530 206q0 93-66 158.5t-158 65.5q-93 0-158.5-65.5t-65.5-158.5q0-92 65.5-158t158.5-66q92 0 158 66t66 158z"></path> | |
</svg> | |
{children} | |
</> | |
) : ( | |
<> | |
{leftIcon && ( | |
<span | |
className={cn(ButtonAnatomy.icon(), iconClass)} | |
style={{ | |
marginInlineEnd: !hideTextOnSmallScreen ? iconSpacing : 0, | |
}} | |
> | |
{leftIcon} | |
</span> | |
)} | |
<span | |
className={cn( | |
hideTextOnSmallScreen && | |
cn( | |
'hidden', | |
leftIcon && 'pl-[0.5rem]', | |
rightIcon && 'pr-[0.5rem]' | |
), | |
hideTextOnLargeScreen | |
? 'inline-block lg:hidden' | |
: 'md:inline-block' | |
)} | |
> | |
{children} | |
</span> | |
{rightIcon && ( | |
<span | |
className={cn(ButtonAnatomy.icon(), iconClass)} | |
style={{ | |
marginInlineStart: !hideTextOnSmallScreen ? iconSpacing : 0, | |
}} | |
> | |
{rightIcon} | |
</span> | |
)} | |
</> | |
)} | |
</button> | |
); | |
} | |
); | |
Button.displayName = 'Button'; | |