feat: add menu recipe

This commit is contained in:
2025-10-20 18:07:32 -06:00
parent 0ff9252fa9
commit bab9339249
2 changed files with 180 additions and 0 deletions

View File

@@ -14,6 +14,7 @@ import detailsRecipe from '@/recipes/details'
import iconButtonRecipe from '@/recipes/iconButton'
import inputRecipe from '@/recipes/input'
import markRecipe from '@/recipes/mark'
import menuRecipe from '@/recipes/menu'
import progressBarRecipe from '@/recipes/progressBar'
import selectRecipe from '@/recipes/select'
import { type BrandColor, type Color, type ColorVariation, color, type NeutralColor } from '@/types'
@@ -51,6 +52,7 @@ const srJuggernautPandaPreset = (config?: ThemeConfig) => {
chip: chipRecipe({ semanticColorNames: semanticColorKeysArray }),
details: detailsRecipe({ semanticColorNames: semanticColorKeysArray }),
mark: markRecipe({ semanticColorNames: semanticColorKeysArray }),
menu: menuRecipe({ semanticColorNames: semanticColorKeysArray }),
input: inputRecipe({ semanticColorNames: semanticColorKeysArray }),
iconButton: iconButtonRecipe({ semanticColorNames: semanticColorKeysArray }),
progressBar: progressBarRecipe({ semanticColorNames: semanticColorKeysArray }),

178
src/recipes/menu.ts Normal file
View File

@@ -0,0 +1,178 @@
import { defineSlotRecipe, type SystemStyleObject } from '@pandacss/dev'
export const menuSlots = ['container', 'item', 'label', 'group', 'separator'] as const
export interface MenuRecipeArg {
semanticColorNames: string[]
}
const menuRecipe = ({ semanticColorNames }: MenuRecipeArg) => {
const colors = ['neutral', ...semanticColorNames]
return defineSlotRecipe({
className: 'menu',
slots: menuSlots,
base: {
container: {
'--menu-background-color-disabled': `color-mix(in srgb, {colors.neutral.3} 40%, transparent)`,
'--menu-background-color': `{colors.neutral.3}`,
'--menu-background-color-hover': `{colors.neutral.4}`,
'--menu-background-color-active': `{colors.neutral.5}`,
'--menu-border-color': `{colors.neutral.6}`,
'--menu-border-color-hover': `{colors.neutral.7}`,
'--menu-border-color-active': `{colors.neutral.8}`,
'--menu-text-color-disabled': `color-mix(in srgb, {colors.neutral.12} 40%, transparent)`,
'--menu-text-color': `{colors.neutral.12}`,
width: 'fit-content',
border: '1px solid',
borderColor: 'var(--menu-border-color)',
borderRadius: 'sm',
backgroundColor: 'var(--menu-background-color)',
color: 'var(--menu-text-color)',
overflow: 'hidden'
},
item: {
all: 'unset',
display: 'flex',
alignItems: 'center',
gap: 'sm',
paddingBlock: 'xs',
paddingInline: 'sm',
cursor: 'pointer',
transitionProperty: 'color, background-color',
color: 'var(--menu-item-text-color, var(--menu-group-text-color ,var(--menu-text-color)))',
transitionDuration: 'normal',
transitionTimingFunction: 'easeOut',
_hover: {
backgroundColor:
'var(--menu-item-background-color-hover, var(--menu-group-background-color-hover ,var(--menu-background-color-hover)))'
},
_active: {
backgroundColor:
'var(--menu-item-background-color-active, var(--menu-group-background-color-active ,var(--menu-background-color-active)))'
},
_checked: {
backgroundColor:
'var(--menu-item-background-color-active, var(--menu-group-background-color-active ,var(--menu-background-color-active)))'
},
_selected: {
backgroundColor:
'var(--menu-item-background-color-active, var(--menu-group-background-color-active ,var(--menu-background-color-active)))'
},
_disabled: {
cursor: 'not-allowed',
color:
'var(--menu-item-text-color-disabled, var(--menu-group-text-color-disabled, var(--menu-text-color-disabled)))',
backgroundColor:
'var(--menu-item-background-color-disabled, var(--menu-group-background-color-disabled, var(--menu-background-color-disabled)))',
_hover: {
backgroundColor:
'var(--menu-item-background-color-disabled, var(--menu-group-background-color-disabled, var(--menu-background-color-disabled)))'
},
_active: {
backgroundColor:
'var(--menu-item-background-color-disabled, var(--menu-group-background-color-disabled, var(--menu-background-color-disabled)))'
},
_checked: {
backgroundColor:
'var(--menu-item-background-color-disabled, var(--menu-group-background-color-disabled, var(--menu-background-color-disabled)))'
},
_selected: {
backgroundColor:
'var(--menu-item-background-color-disabled, var(--menu-group-background-color-disabled, var(--menu-background-color-disabled)))'
}
}
},
label: {
fontSize: 'sm',
color: 'var(--menu-label-text-color, var(--menu-text-color))',
fontWeight: 'bold'
},
group: {
borderBlock: '1px solid',
borderColor: 'var(--menu-group-border-color, var(--menu-border-color))',
backgroundColor: 'var(--menu-group-background-color, var(--menu-background-color))',
color: 'var(--menu-group-text-color, var(--menu-text-color))'
},
separator: {
height: '1px',
backgroundColor: 'var(--menu-separator-border-color, var(--menu-group-border-color, var(--menu-border-color)))'
}
},
variants: {
color: {
...Object.fromEntries(
colors.map((color) => [
color,
Object.fromEntries(
menuSlots.map((slot) => {
switch (slot) {
case 'container':
return [
slot,
{
'--menu-background-color-disabled': `color-mix(in srgb, {colors.${color}.3} 40%, transparent)`,
'--menu-background-color': `{colors.${color}.3}`,
'--menu-background-color-hover': `{colors.${color}.4}`,
'--menu-background-color-active': `{colors.${color}.5}`,
'--menu-border-color': `{colors.${color}.6}`,
'--menu-border-color-hover': `{colors.${color}.7}`,
'--menu-border-color-active': `{colors.${color}.8}`,
'--menu-text-color-disabled': `color-mix(in srgb, {colors.${color}.12} 40%, transparent)`,
'--menu-text-color': `{colors.${color}.12}`
} as SystemStyleObject
]
case 'item':
return [
slot,
{
'--menu-item-background-color-disabled': `color-mix(in srgb, {colors.${color}.3} 40%, transparent)`,
'--menu-item-background-color': `{colors.${color}.3}`,
'--menu-item-background-color-hover': `{colors.${color}.4}`,
'--menu-item-background-color-active': `{colors.${color}.5}`,
'--menu-item-text-color-disabled': `color-mix(in srgb, {colors.${color}.12} 40%, transparent)`,
'--menu-item-text-color': `{colors.${color}.12}`
} as SystemStyleObject
]
case 'label':
return [
slot,
{
'--menu-label-text-color': `{colors.${color}.12}`
} as SystemStyleObject
]
case 'group':
return [
slot,
{
'--menu-group-background-color-disabled': `color-mix(in srgb, {colors.${color}.3} 40%, transparent)`,
'--menu-group-background-color': `{colors.${color}.3}`,
'--menu-group-background-color-hover': `{colors.${color}.4}`,
'--menu-group-background-color-active': `{colors.${color}.5}`,
'--menu-group-border-color': `{colors.${color}.6}`,
'--menu-group-border-color-hover': `{colors.${color}.7}`,
'--menu-group-border-color-active': `{colors.${color}.8}`,
'--menu-group-text-color-disabled': `color-mix(in srgb, {colors.${color}.12} 40%, transparent)`,
'--menu-group-text-color': `{colors.${color}.12}`
} as SystemStyleObject
]
case 'separator':
return [
slot,
{
'--menu-separator-border-color': `{colors.${color}.6}`
} as SystemStyleObject
]
default:
return [slot, {} as SystemStyleObject]
}
})
)
])
)
}
},
defaultVariants: {}
})
}
export default menuRecipe