addons/components/Dropdown.tsxblame
View source
b69ab311/**
b69ab312 * Copyright (c) Meta Platforms, Inc. and affiliates.
b69ab313 *
b69ab314 * This source code is licensed under the MIT license found in the
b69ab315 * LICENSE file in the root directory of this source tree.
b69ab316 */
b69ab317
b69ab318import type {ReactNode} from 'react';
b69ab319import type {ReactProps} from './utils';
b69ab3110
b69ab3111import * as stylex from '@stylexjs/stylex';
b69ab3112import {useId} from 'react';
b69ab3113
b69ab3114const styles = stylex.create({
b69ab3115 label: {
b69ab3116 marginBlock: '0px',
b69ab3117 },
b69ab3118 select: {
b69ab3119 fontFamily: 'var(--font-family)',
b69ab3120 boxSizing: 'border-box',
b69ab3121 padding: '3px 6px',
b69ab3122 background: 'var(--input-background)',
b69ab3123 color: 'var(--input-foreground)',
b69ab3124 border: '1px solid var(--dropdown-border)',
b69ab3125 outline: {
b69ab3126 default: 'none',
b69ab3127 ':focus-visible': '1px solid var(--focus-border)',
b69ab3128 },
b69ab3129 outlineOffset: '-1px',
b69ab3130 },
b69ab3131 disabled: {
b69ab3132 opacity: 0.4,
b69ab3133 cursor: 'not-allowed',
b69ab3134 },
b69ab3135});
b69ab3136
b69ab3137export function Dropdown<T extends string | {value: string; name: string; disabled?: boolean}>({
b69ab3138 options,
b69ab3139 children,
b69ab3140 xstyle,
b69ab3141 value,
b69ab3142 disabled,
b69ab3143 ...rest
b69ab3144}: {
b69ab3145 options: Array<T>;
b69ab3146 children?: ReactNode;
b69ab3147 value?: T extends string ? T : T extends {value: string; name: string} ? T['value'] : never;
b69ab3148 disabled?: boolean;
b69ab3149 xstyle?: stylex.StyleXStyles;
b69ab3150} & ReactProps<HTMLSelectElement>) {
b69ab3151 const id = useId();
b69ab3152 return (
b69ab3153 <select
b69ab3154 {...stylex.props(styles.select, xstyle, disabled && styles.disabled)}
b69ab3155 {...rest}
b69ab3156 disabled={disabled || options.length === 0}
b69ab3157 value={value}>
b69ab3158 {children && (
b69ab3159 <label htmlFor={id} {...stylex.props(styles.label)}>
b69ab3160 {children}
b69ab3161 </label>
b69ab3162 )}
b69ab3163 {options.map((option, index) => {
b69ab3164 const val = typeof option === 'string' ? option : option.value;
b69ab3165 const name = typeof option === 'string' ? option : option.name;
b69ab3166 const disabled = typeof option === 'string' ? false : option.disabled;
b69ab3167 return (
b69ab3168 <option key={index} value={val} disabled={disabled}>
b69ab3169 {name}
b69ab3170 </option>
b69ab3171 );
b69ab3172 })}
b69ab3173 </select>
b69ab3174 );
b69ab3175}