import { ComplexStyleRule, globalStyle, style } from '@vanilla-extract/css'; import { recipe } from '@vanilla-extract/recipes'; import { vars, buttonReset, CompoundVariant } from '../css'; /*-- Types --*/ export type ButtonVariant = 'filled' | 'outlined' | 'text'; export type ButtonBaseColor = 'primary' | 'secondary' | 'error'; export type ButtonColor = ButtonBaseColor | 'inherit'; export type ButtonSubtle = 'true'; export type ButtonFontSize = 'base' | 'subtle'; export type ButtonWidth = 'auto' | 'full' | 'sm' | 'md' | 'lg' | 'xl' | '2xl'; export type ButtonHasIcon = 'true'; export type ButtonVariants = { variant: Record; color: Record; subtle: Record; fontSize: Record; width: Record; hasIcon: Record; }; /*-- Main --*/ const buttonBase = style({ padding: '0.6rem 1.375rem', fontSize: vars.components.button.fontSizes.base, fontWeight: vars.components.button.fontWeights.base, }); globalStyle(`${buttonBase} > *:not(:last-child)`, { marginRight: vars.space[3], }); export const button = recipe({ base: [buttonReset, buttonBase], variants: { variant: { filled: {}, outlined: { backgroundColor: 'transparent', boxShadow: '0 0 0 1px inset', color: vars.colors['base-text-strong'], fontWeight: vars.fontWeights.normal, }, text: { backgroundColor: 'transparent', color: vars.colors['base-text-strong'], textDecoration: 'underline', textDecorationColor: 'transparent', textDecorationThickness: '0.125em', textUnderlineOffset: '0.125em', selectors: { '&:not(:disabled):hover': { textDecorationColor: 'currentcolor', }, }, }, }, color: { primary: {}, secondary: {}, error: {}, inherit: { color: 'inherit', }, }, subtle: { true: {}, }, fontSize: { subtle: { fontSize: vars.components.button.fontSizes.subtle }, base: { fontSize: vars.components.button.fontSizes.base }, }, width: { auto: { width: 'auto', }, full: { width: '100%', }, sm: { minWidth: vars.components.button.sizes['width-sm'], }, md: { minWidth: vars.components.button.sizes['width-md'], }, lg: { minWidth: vars.components.button.sizes['width-lg'], }, xl: { minWidth: vars.components.button.sizes['width-xl'], }, '2xl': { minWidth: vars.components.button.sizes['width-2xl'], }, }, hasIcon: { true: { paddingLeft: '1rem', paddingRight: '1rem', }, }, }, compoundVariants: [ // Filed generateFilledCompound('primary'), generateFilledCompound('secondary'), generateFilledCompound('error'), // Outlined generateOutlinedCompound('primary'), generateOutlinedCompound('secondary'), generateOutlinedCompound('error'), // Text generateTextCompound('primary'), generateTextCompound('secondary'), generateTextCompound('error'), { variants: { variant: 'text', subtle: true, }, style: { fontSize: vars.components.button.fontSizes.subtle, fontWeight: vars.fontWeights.normal, textDecorationThickness: '0.0625em', }, }, ], }); /*-- Utils --*/ function generateFilledCompound( color: ButtonBaseColor, ): CompoundVariant { return { variants: { variant: 'filled', color, }, style: { backgroundColor: vars.colors[color], color: vars.colors[`${color}-text-strong`], selectors: { '&:not(:disabled):hover': { backgroundColor: vars.colors[`${color}-down`], }, '&:not(:disabled):active': { backgroundColor: vars.colors[color], }, }, }, }; } function generateOutlinedCompound( color: ButtonBaseColor, ): CompoundVariant { return { variants: { variant: 'outlined', color, }, style: { color: vars.colors[color], selectors: { '&:not(:disabled):hover': { color: vars.colors[`${color}-down`], }, '&:not(:disabled):active': { color: vars.colors[color], }, }, }, }; } function generateTextCompound( color: ButtonBaseColor, ): CompoundVariant { return { variants: { variant: 'text', color, }, style: { color: vars.colors[color], }, }; }