import { define } from 'forge' import { theme } from './theme' import { Section } from './section' import { H2 } from './text' import { VStack, HStack } from './stack' export type SelectOption = { value: string label: string disabled?: boolean } // Custom dropdown arrow as base64 SVG const dropdownArrow = `url("data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTYiIGhlaWdodD0iMTYiIHZpZXdCb3g9IjAgMCAxNiAxNiIgZmlsbD0ibm9uZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KPHBhdGggZD0iTTQgNkw4IDEwTDEyIDYiIHN0cm9rZT0iIzZCNzI4MCIgc3Ryb2tlLXdpZHRoPSIyIiBzdHJva2UtbGluZWNhcD0icm91bmQiIHN0cm9rZS1saW5lam9pbj0icm91bmQiLz4KPC9zdmc+")` export const Select = define('Select', { parts: { Wrapper: { display: 'flex', flexDirection: 'column', gap: theme('spacing-1'), flex: 1, minWidth: 0, }, Label: { base: 'label', fontSize: theme('fontSize-sm'), fontWeight: 500, color: theme('colors-fg'), }, Field: { base: 'select', height: 40, padding: `${theme('spacing-2')} 32px ${theme('spacing-2')} ${theme('spacing-3')}`, borderRadius: theme('radius-md'), border: `1px solid ${theme('colors-border')}`, background: theme('colors-bg'), fontSize: theme('fontSize-sm'), outline: 'none', appearance: 'none', backgroundImage: dropdownArrow, backgroundRepeat: 'no-repeat', backgroundPosition: 'right 8px center', backgroundSize: '16px' as any, flex: 1, states: { ':focus': { borderColor: theme('colors-borderActive'), }, ':disabled': { opacity: 0.5, cursor: 'not-allowed', }, }, }, }, variants: { labelPosition: { above: { parts: { Wrapper: { flexDirection: 'column', gap: theme('spacing-1'), }, }, }, left: { parts: { Wrapper: { flexDirection: 'row', alignItems: 'center', gap: theme('spacing-1'), }, }, }, right: { parts: { Wrapper: { flexDirection: 'row-reverse', alignItems: 'center', gap: theme('spacing-1'), }, }, }, }, }, render({ props, parts: { Root, Wrapper, Label, Field } }) { const { children, options, placeholder, labelPosition = 'above', ...selectProps } = props // Generate id for label association if needed const elementId = props.id || (children ? `select-${Math.random().toString(36).slice(2)}` : undefined) const selectElement = ( {placeholder && ( )} {options?.map((option: SelectOption) => ( ))} ) if (!children) { return selectElement } return ( {selectElement} ) }, }) export type SelectProps = Parameters[0] export const Test = () => { const months = [ { value: '01', label: 'January' }, { value: '02', label: 'February' }, { value: '03', label: 'March' }, { value: '04', label: 'April' }, { value: '05', label: 'May' }, { value: '06', label: 'June' }, { value: '07', label: 'July' }, { value: '08', label: 'August' }, { value: '09', label: 'September' }, { value: '10', label: 'October' }, { value: '11', label: 'November' }, { value: '12', label: 'December' }, ] const years = Array.from({ length: 10 }, (_, i) => ({ value: String(2024 + i), label: String(2024 + i), })) const countries = [ { value: 'us', label: 'United States' }, { value: 'ca', label: 'Canada' }, { value: 'uk', label: 'United Kingdom' }, { value: 'de', label: 'Germany' }, { value: 'fr', label: 'France' }, { value: 'au', label: 'Australia', disabled: true }, ] return (
{/* Basic selects */}

Basic Selects

Birth Month
{/* Label to the left */}

Label Left

{/* Label to the right */}

Label Right

{/* Horizontal layout (like card form) */}

Horizontal Layout

) }