import { defineSlotRecipe, type SystemStyleObject } from '@pandacss/dev' export const selectSlots = [ 'trigger', 'content', 'viewport', 'scrollButton', 'item', 'itemIndicator', 'group', 'groupLabel', 'separator' ] as const export const selectSizes = ['small', 'medium', 'large'] as const export interface SelectRecipeArg { semanticColorNames: string[] } const selectRecipe = ({ semanticColorNames }: SelectRecipeArg) => { const colorVariants = ['neutral', ...semanticColorNames] return defineSlotRecipe({ className: 'select', slots: selectSlots, base: { trigger: { all: 'unset', boxSizing: 'border-box', display: 'inline-flex', alignItems: 'center', justifyContent: 'space-between', gap: 'xs', minWidth: 'fit-content', borderRadius: 'sm', border: '1px solid', cursor: 'pointer', transitionProperty: 'color, background-color, border-color', transitionDuration: 'normal', transitionTimingFunction: 'easeOut', focusVisibleRing: 'outside', focusRingWidth: '2px', focusRingOffset: '0px' }, content: { overflow: 'hidden', maxHeight: 'var(--radix-select-content-available-height, 90dvh)', width: 'var(--radix-select-trigger-width, min(max-content, 90dvw))', backgroundColor: 'var(--select-background-color)', color: 'var(--select-color)', borderRadius: 'sm', _active: { animationName: 'fade', animationDuration: 'normal' }, '&[data-state=closed]': { animationName: 'fade', animationDuration: 'normal', animationDirection: 'reverse' } }, viewport: { padding: 'xs' }, scrollButton: { display: 'flex', alignItems: 'center', justifyContent: 'center', color: 'var(--select-color-subtle)', cursor: 'pointer', transitionProperty: 'color, background-color', transitionDuration: 'normal', transitionTimingFunction: 'easeOut', '&:hover': { color: 'var(--select-color)' } }, item: { display: 'flex', alignItems: 'center', justifyContent: 'flex-start', gap: 'xs', padding: 'xs', borderRadius: 'sm', cursor: 'pointer', transitionProperty: 'color, background-color', transitionDuration: 'normal', transitionTimingFunction: 'easeOut', focusRingColor: 'var(--select-border-color-focus)', focusVisibleRing: 'outside', focusRingWidth: '2px', focusRingOffset: '0px', _highlighted: { backgroundColor: 'var(--select-background-color-hover)' }, '&[data-state=checked]': { backgroundColor: 'var(--select-background-color-active)' }, _disabled: { color: 'var(--select-color-disabled)', backgroundColor: 'var(--select-background-color-disabled)', cursor: 'not-allowed', _highlighted: { backgroundColor: 'var(--select-background-color-disabled)', color: 'var(--select-color-disabled)' } } }, itemIndicator: { color: 'var(--select-color-subtle)' }, group: { display: 'flex', flexDirection: 'column', gap: 'xs', marginInline: '-xs', borderBlock: '1px solid var(--select-border-color)', paddingInline: 'xs' }, groupLabel: { color: 'var(--select-color-subtle)', fontSize: 'sm', fontWeight: 'semibold', lineHeight: 'tight', userSelect: 'none' }, separator: { height: '1px', backgroundColor: 'var(--select-border-color)', marginBlock: 'xs', marginInline: '-xs' } }, variants: { size: { ...Object.fromEntries( selectSizes.map((size) => { switch (size) { case 'small': return [ size, { trigger: { paddingBlock: 'calc({spacing.xs} * 0.5)', paddingInline: 'calc({spacing.xs} * 1)', fontSize: 'sm' } } ] case 'medium': return [ size, { trigger: { paddingBlock: 'calc({spacing.xs} * 0.75)', paddingInline: 'calc({spacing.xs} * 1.25)', fontSize: 'base' } } ] case 'large': return [ size, { trigger: { paddingBlock: 'calc({spacing.xs} * 1)', paddingInline: 'calc({spacing.xs} * 1.5)', fontSize: 'lg' } } ] default: return [size, {}] } }) ) }, color: { ...Object.fromEntries( colorVariants.map((color) => [ color, Object.fromEntries( selectSlots.map((slot) => { switch (slot) { case 'trigger': // Trigger is outside the content, so it needs to be set independently return [ slot, { backgroundColor: `${color}.2`, color: `${color}.12`, borderColor: `${color}.6`, focusRingColor: `{colors.${color}.7}`, _placeholder: { color: `${color}.11` }, _hover: { backgroundColor: `${color}.3` }, _active: { backgroundColor: `${color}.4` }, _focus: { backgroundColor: `${color}.3`, borderColor: `${color}.7` }, _disabled: { cursor: 'not-allowed', backgroundColor: `color-mix(in srgb, {colors.${color}.2} 40%, transparent)`, color: `color-mix(in srgb, {colors.${color}.11} 40%, transparent)`, _placeholder: { color: `color-mix(in srgb, {colors.${color}.11} 40%, transparent)` }, _hover: { backgroundColor: `color-mix(in srgb, {colors.${color}.2} 40%, transparent)`, color: `color-mix(in srgb, {colors.${color}.11} 40%, transparent)` }, _active: { backgroundColor: `color-mix(in srgb, {colors.${color}.2} 40%, transparent)`, color: `color-mix(in srgb, {colors.${color}.11} 40%, transparent)` } } } as SystemStyleObject ] case 'content': // Items, Group, ScrollButtons are inside the content, so we can set them together return [ slot, { '--select-background-color': `{colors.${color}.2}`, '--select-background-color-hover': `{colors.${color}.4}`, '--select-background-color-active': `{colors.${color}.5}`, '--select-background-color-disabled': `color-mix(in srgb, {colors.${color}.2} 40%, transparent)`, '--select-border-color': `{colors.${color}.6}`, '--select-border-color-focus': `{colors.${color}.7}`, '--select-color-subtle': `{colors.${color}.11}`, '--select-color': `{colors.${color}.12}`, '--select-color-disabled': `color-mix(in srgb, {colors.${color}.11} 40%, transparent)` } as SystemStyleObject ] default: return [slot, {}] } }) ) ]) ) }, fullWidth: { true: { trigger: { width: '100%' } } } }, defaultVariants: { color: 'neutral', size: 'medium' } }) } export default selectRecipe