/** * Select Component * * Theme-agnostic select dropdown with focus effects. * Automatically adapts styling based on active theme (luxe or cyberpunk). * * IMPORTANT: This component preserves ALL business logic from cyberpunk-ui/ui-core. * Only styling has been converted to styled-components with semantic tokens. */ import { forwardRef } from 'react' import type { SelectHTMLAttributes, ReactNode } from 'react' import styled, { css } from 'styled-components' /** * Option type for Select component */ export interface SelectOption { value: string | number label: string disabled?: boolean } /** * Select component props */ export interface SelectProps extends Omit, 'children'> { /** Visual style variant with different focus colors */ variant?: 'primary' | 'secondary' | 'danger' /** Whether the select should take full width of container */ fullWidth?: boolean /** Array of options to render */ options?: SelectOption[] /** Children option elements (alternative to options prop) */ children?: ReactNode /** Placeholder text (shows as first disabled option) */ placeholder?: string } // Styled Components const StyledSelect = styled.select<{ $variant: SelectProps['variant'] $fullWidth: boolean }>` background: ${props => props.theme.colors.background}; border: 2px solid ${props => props.theme.colors.border}; color: ${props => props.theme.colors.text.primary}; padding: ${props => props.theme.spacing.md}; font-family: ${props => props.theme.typography.fontFamily.body}; font-size: ${props => props.theme.typography.fontSize.base}; outline: none; transition: all ${props => props.theme.transitions.normal}; width: ${props => props.$fullWidth ? '100%' : 'auto'}; cursor: pointer; border-radius: ${props => props.theme.borderRadius.md}; /* Cyberpunk darker background */ ${props => props.theme.extensions?.cyberpunk && css` background: ${props.theme.colors.surface}; color: ${props.theme.colors.primary}; `} /* Focus states per variant */ &:focus { ${({ $variant, theme }) => { switch ($variant) { case 'primary': return css` border-color: ${theme.colors.primary}; box-shadow: 0 0 0 3px ${theme.colors.primary}20; ${theme.extensions?.cyberpunk && css` box-shadow: 0 0 10px ${theme.colors.primary}; `} ` case 'secondary': return css` border-color: ${theme.colors.secondary}; box-shadow: 0 0 0 3px ${theme.colors.secondary}20; ${theme.extensions?.cyberpunk && css` box-shadow: 0 0 10px ${theme.colors.secondary}; `} ` case 'danger': return css` border-color: ${theme.colors.error}; box-shadow: 0 0 0 3px ${theme.colors.error}20; ${theme.extensions?.cyberpunk && css` box-shadow: 0 0 10px ${theme.colors.error}; `} ` default: return css` border-color: ${theme.colors.primary}; box-shadow: 0 0 0 3px ${theme.colors.primary}20; ` } }} } /* Disabled state */ &:disabled { opacity: 0.5; cursor: not-allowed; background-color: ${props => props.theme.colors.disabled.background}; color: ${props => props.theme.colors.disabled.text}; } /* Hover state */ &:hover:not(:disabled) { border-color: ${props => { switch (props.$variant) { case 'secondary': return props.theme.colors.secondary case 'danger': return props.theme.colors.error default: return props.theme.colors.primary } }}; } ` /** * Cyberpunk-themed select dropdown for form inputs with focus effects. * Features dynamic border colors and box shadows based on variant. * Supports both options array and children