Single-value dropdown picker built on Headless UI Listbox. Renders a labelled input-style trigger with a floating option list.
Reach for Select when the user picks one value from a fixed list and no text filtering is needed.
Combobox.MultiSelect.Use @uxf/ui/select for a controlled select outside a form. Inside a @uxf/form form, use @uxf/form/select instead — it registers the field with react-hook-form and derives isInvalid / helperText from validation. This @uxf/ui component is the controlled primitive the form twin wraps.
import { Select, SelectOption } from "@uxf/ui/select";
import { useState } from "react";
const options: SelectOption[] = [
{ id: "one", label: "Option one" },
{ id: "two", label: "Option two", disabled: true },
{ id: "three", label: "Option three" },
];
function Example() {
const [value, setValue] = useState<string | number | null>(null);
return (
<Select
label="Choose an option"
name="example"
onChange={setValue}
options={options}
placeholder="Select..."
value={value}
/>
);
}
value is the selected option's id (string | number) or null, and onChange is called with the new id — not the option object.
Exports: Select and the types SelectProps, SelectOption, SelectValue.
SelectProps<Value = SelectValue, Option = SelectOption<Value>> extends FormControlProps<Value | null> and Clearable. SelectValue is number | string; SelectOption is { id: Value; label: ReactNode; disabled?: boolean }.
| Prop | Type | Default | Description |
|---|---|---|---|
label |
ReactNode |
— | Required. Field label. |
name |
string |
— | Required. Field name (also set as data-name). |
value |
Value | null |
— | Required. Selected option id, or null. |
onChange |
(value: Value | null) => void |
— | Required. Called with the newly selected id (or null when cleared). |
options |
Option[] |
— | Required. Selectable options. |
placeholder |
string |
— | Shown when no option is selected. |
helperText |
ReactNode |
— | Text under the control; styled as an error when isInvalid. |
isClearable |
boolean |
false |
Show a clear button that resets the value to null. |
isDisabled |
boolean |
false |
Disable the control. |
isReadOnly |
boolean |
false |
Prevent changes while staying focusable. |
isInvalid |
boolean |
false |
Invalid styling; sets aria-invalid and styles helperText as an error. |
isRequired |
boolean |
false |
Mark the field required (adds the label indicator). |
hiddenLabel |
boolean |
false |
Visually hide the label (kept for assistive tech). |
renderOption |
(option: Option, isSelected: boolean) => ReactNode |
option.label |
Custom renderer for each dropdown option. |
renderSelectedOption |
(option: Option) => ReactNode |
option.label |
Custom renderer for the selected value in the trigger. |
keyExtractor |
(option: Option) => string | number |
option.id |
Custom React key for options. |
noOptionsMessage |
string |
localized "No items found" | Empty-list message. |
iconName |
IconName |
arrow icon | Icon for the dropdown arrow. |
size |
InputGroupSize |
"default" |
"small", "default", or "large". |
variant |
InputGroupVariant |
"default" |
Input group variant. |
id |
string |
auto (useId) |
Root id; the error-message id derives from it. |
onBlur / onFocus |
FocusEventHandler<HTMLInputElement> |
— | Focus handlers. |
Layout, dropdown, and ref props: className, style, form, leftAddon, rightAddon, leftElement, rightElement, inputArrow, dropdownClassName, dropdownMatchesInputWidth (default true), dropdownMaxHeight (default 240), dropdownPlacement (default "bottom"), dropdownStrategy, inputRef, inputGroupRef, inputWrapperRef.
small, default, large (via size).isInvalid; combine with helperText to show an error message.isDisabled blocks all interaction; isReadOnly keeps focus but prevents changes.isClearable, a remove button appears once a value is selected (unless disabled/read-only).dropdownPlacement="top" flips the list above the input; Floating UI auto-flips on collision.The component composes the input, label, dropdown, form-component, and icon primitives, so import all of their stylesheets once in your global CSS:
@import url("@uxf/ui/css/icon.css");
@import url("@uxf/ui/css/dropdown.css");
@import url("@uxf/ui/css/label.css");
@import url("@uxf/ui/css/form-component.css");
@import url("@uxf/ui/css/input-basic.css");
@import url("@uxf/ui/css/input.css");
@import url("@uxf/ui/css/select.css");
Also requires the global @uxf/ui token layer, set up once per app — see @uxf/ui setup.