176 lines
5.7 KiB
TypeScript
176 lines
5.7 KiB
TypeScript
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
|