2.0 KB76 lines
Blame
1/**
2 * Copyright (c) Meta Platforms, Inc. and affiliates.
3 *
4 * This source code is licensed under the MIT license found in the
5 * LICENSE file in the root directory of this source tree.
6 */
7
8import type {ReactNode} from 'react';
9import type {ReactProps} from './utils';
10
11import * as stylex from '@stylexjs/stylex';
12import {useId} from 'react';
13
14const styles = stylex.create({
15 label: {
16 marginBlock: '0px',
17 },
18 select: {
19 fontFamily: 'var(--font-family)',
20 boxSizing: 'border-box',
21 padding: '3px 6px',
22 background: 'var(--input-background)',
23 color: 'var(--input-foreground)',
24 border: '1px solid var(--dropdown-border)',
25 outline: {
26 default: 'none',
27 ':focus-visible': '1px solid var(--focus-border)',
28 },
29 outlineOffset: '-1px',
30 },
31 disabled: {
32 opacity: 0.4,
33 cursor: 'not-allowed',
34 },
35});
36
37export function Dropdown<T extends string | {value: string; name: string; disabled?: boolean}>({
38 options,
39 children,
40 xstyle,
41 value,
42 disabled,
43 ...rest
44}: {
45 options: Array<T>;
46 children?: ReactNode;
47 value?: T extends string ? T : T extends {value: string; name: string} ? T['value'] : never;
48 disabled?: boolean;
49 xstyle?: stylex.StyleXStyles;
50} & ReactProps<HTMLSelectElement>) {
51 const id = useId();
52 return (
53 <select
54 {...stylex.props(styles.select, xstyle, disabled && styles.disabled)}
55 {...rest}
56 disabled={disabled || options.length === 0}
57 value={value}>
58 {children && (
59 <label htmlFor={id} {...stylex.props(styles.label)}>
60 {children}
61 </label>
62 )}
63 {options.map((option, index) => {
64 const val = typeof option === 'string' ? option : option.value;
65 const name = typeof option === 'string' ? option : option.name;
66 const disabled = typeof option === 'string' ? false : option.disabled;
67 return (
68 <option key={index} value={val} disabled={disabled}>
69 {name}
70 </option>
71 );
72 })}
73 </select>
74 );
75}
76