import { defineRecipe } from '@pandacss/dev' export const buttonVariants = ['solid', 'outline', 'ghost'] as const export const buttonSizes = ['small', 'medium', 'large'] as const interface ButtonRecipeArg { semanticColorNames: string[] } const buttonRecipe = ({ semanticColorNames }: ButtonRecipeArg) => { const colorVariants = ['neutral', ...semanticColorNames] return defineRecipe({ className: 'button', base: { all: 'unset', display: 'inline-flex', alignItems: 'center', justifyContent: 'center', gap: 'xs', width: 'fit-content', borderRadius: 'sm', paddingBlock: 'xs', paddingInline: 'sm', cursor: 'pointer', transitionProperty: 'color, background-color, border-color', transitionDuration: 'normal', transitionTimingFunction: 'easeOut', fontWeight: 'semibold', _disabled: { cursor: 'not-allowed', _hover: { cursor: 'not-allowed' } } }, variants: { color: { ...Object.fromEntries(colorVariants.map((color) => [color, {}])) }, size: { ...Object.fromEntries( buttonSizes.map((size) => { switch (size) { case 'small': return [ size, { paddingBlock: 'calc({spacing.xs} * 0.5)', paddingInline: 'calc({spacing.xs} * 1)', fontSize: 'sm' } ] case 'medium': return [ size, { paddingBlock: 'calc({spacing.xs} * 0.75)', paddingInline: 'calc({spacing.xs} * 1.25)', fontSize: 'base' } ] case 'large': return [ size, { paddingBlock: 'calc({spacing.xs} * 1)', paddingInline: 'calc({spacing.xs} * 1.5)', fontSize: 'lg' } ] default: return [size, {}] } }) ) }, variant: { ...Object.fromEntries(buttonVariants.map((variant) => [variant, {}])) } }, compoundVariants: colorVariants.flatMap((color) => buttonVariants.map((variant) => { switch (variant) { case 'outline': return { color, variant, css: { border: '1px solid', borderColor: `${color}.9`, backgroundColor: 'transparent', color: `${color}.9`, _hover: { backgroundColor: `${color}.10`, color: `${color}.foreground` }, _active: { backgroundColor: `color-mix(in srgb, {colors.${color}.9} 80%, {colors.${color}.1})`, color: `${color}.foreground` }, _disabled: { backgroundColor: `color-mix(in srgb, {colors.${color}.9} 10%, transparent)`, color: `color-mix(in srgb, {colors.${color}.foreground} 40%, transparent)`, borderColor: `color-mix(in srgb, {colors.${color}.9} 10%, transparent)`, _hover: { backgroundColor: `color-mix(in srgb, {colors.${color}.9} 10%, transparent)`, color: `${color}.4/50` } } } } case 'ghost': return { color, variant, css: { border: 'none', backgroundColor: 'transparent', color: `${color}.9`, _hover: { backgroundColor: `${color}.10`, color: `${color}.foreground` }, _active: { backgroundColor: `color-mix(in srgb, {colors.${color}.9} 80%, {colors.${color}.1})`, color: `${color}.foreground` }, _disabled: { backgroundColor: `color-mix(in srgb, {colors.${color}.9} 10%, transparent)`, color: `color-mix(in srgb, {colors.${color}.foreground} 40%, transparent)`, _hover: { backgroundColor: `color-mix(in srgb, {colors.${color}.9} 10%, transparent)` } } } } // case 'solid' or unmatched: default: return { color, variant, css: { border: 'none', backgroundColor: `${color}.9`, color: `${color}.foreground`, _hover: { backgroundColor: `${color}.10`, color: `${color}.foreground` }, _active: { backgroundColor: `color-mix(in srgb, {colors.${color}.9} 80%, {colors.${color}.1})`, color: `${color}.foreground` }, _disabled: { backgroundColor: `color-mix(in srgb, {colors.${color}.9} 40%, transparent)`, color: `color-mix(in srgb, {colors.${color}.foreground} 40%, transparent)`, _hover: { backgroundColor: `color-mix(in srgb, {colors.${color}.9} 40%, transparent)`, color: `color-mix(in srgb, {colors.${color}.foreground} 40%, transparent)` } } } } } }) ), defaultVariants: { color: 'neutral', size: 'medium', variant: 'solid' } }) } export default buttonRecipe