Select is a low-level, accessible UI primitive that helps achieve ecosystem-agnostic, fully accessible select menus that can be styled as needed.
Select follows the WAI-ARIA authoring practices for a listbox that displays a menu to the user, such as a set of actions or functions triggered by a button.
Import
import { Select } from "@fuegokit/react";
Additional styling guides and examples are coming soon. For now, explore the examples at Storybook.
Usage
<Select><Select.Trigger aria-label="Food"><Select.Value placeholder="Select a fruit…" /><Select.Icon><AkChevronDownIcon /></Select.Icon></Select.Trigger><Select.Portal><Select.Content>
Styling
To apply styles to the Select primitive, use Fuegokit React's themeGet
function to access Fuegokit Tokens directly.
Component API
<StyledSelect><StyledSelectTrigger aria-label="Food"><Select.Value placeholder="Select a fruit…" /><Select.Icon UNSAFE_className="StyledSelectIcon"><AkChevronDownIcon /></Select.Icon></StyledSelectTrigger><Select.Portal><StyledSelectContent>
CSS
const slideUpAndFade = keyframes`from {opacity: 0;transform: translateY(2px);}to {opacity: 1;transform: translateY(0);}
Accessibility
Select adheres to the listBox WAI-ARIA design pattern.
See the W3C Select-Only Combobox example for more information.
When to use
- Inside forms when users are selecting from a list of options and will be submitting data.
- When the experience is mostly form-based.
When not to use
- If there are fewer than three options to choose from, use a radio button group instead.
Selects vs Dropdowns
Select and Dropdown components look similar but serve different purposes.
- A Select displays a list of options. With a Select, users can select only one item from that list. It is best-suited for forms, when users are choosing an option from a select list and they intend to submit the data through the form.
- A Dropdown displays a list of options. With a Dropdown, Users can select one or several options from that list. Dropdown options are used for taking an action, filtering, or sorting existing content.
Keyboard interactions
Key | Description |
---|---|
Space | When focus is on Select.Trigger , opens the select and focuses the selected item. When focus is on an item, selects the focused item. When focus is on Select.Trigger , opens the select and focuses the first item. |
Enter | When focus is on Select.Trigger , opens the select and focuses the first item. When focus is on an item, selects the focused item. |
ArrowDown | When focus is on Select.Trigger , opens the select. When focus is on an item, moves focus to the next item. |
ArrowUp | When focus is on Select.Trigger , opens the select. When focus is on an item, moves focus to the previous item. |
Esc | Closes the select and moves focus to Select.Trigger . |
Props
Select
Contains all the parts of a select.
Name | Type | Default | Description |
---|---|---|---|
defaultValue | string | - | The value of the select when initially rendered. Use when you do not need to control the state of the select. |
value | boolean | - | The controlled value of the select. Should be used in conjunction with `onValueChange`. |
defaultOpen | boolean | - | The open state of the select when it is initially rendered. Use when you do not need to control its open state. |
open | boolean | - | The controlled open state of the select. Must be used in conjunction with onOpenChange. |
dir | 'ltr' | 'rtl' | - | The reading direction of the select when applicable. If omitted, inherits globally from `DirectionProvider` or assumes LTR (left-to-right) reading mode. |
name | string | - | The name of the select. Submitted with its owning form as part of a name/value pair. |
disabled | boolean | - | When `true`, prevents the user from interacting with select. |
required | boolean | - | When `true`, indicates that the user must select a value before the owning form can be submitted. |
Events
Name | Type | Default | Description |
---|---|---|---|
onValueChange | (value: string) => void | - | Event handler called when the value changes. |
Select.Trigger
The button that toggles the select. The Select.Content will position itself by aligning over the trigger.
Name | Type | Default | Description |
---|---|---|---|
asChild | boolean | false | Change the component to the HTML tag or custom component of the only child. This will merge the original component props with the props of the supplied element/component and change the underlying DOM node. |
Data attributes
Data attribute | Values |
---|---|
[data-state] | 'open' | 'closed' |
[data-disabled] | 'open' | 'closed' |
[data-placeholder] | 'open' | 'closed' |
Select.Value
The part that reflects the selected value. By default the selected item's text will be rendered. if you require more control, you can instead control the select and pass your own `children`. It should not be styled to ensure correct positioning. An optional placeholder prop is also available for when the select has no value.
Name | Type | Default | Description |
---|---|---|---|
asChild | boolean | false | Change the component to the HTML tag or custom component of the only child. This will merge the original component props with the props of the supplied element/component and change the underlying DOM node. |
placeholder | React.ReactNode | - | The content that will be rendered inside the `Select.Value` when no `value` or `defaultValue` is set. |
Select.Icon
A small icon often displayed next to the value as a visual affordance for the fact it can be open. By default renders ▼ but you can use your own icon via asChild or use children.
Name | Type | Default | Description |
---|---|---|---|
asChild | boolean | false | Change the component to the HTML tag or custom component of the only child. This will merge the original component props with the props of the supplied element/component and change the underlying DOM node. |
Select.Portal
When used, portals the content part into the body.
Name | Type | Default | Description |
---|---|---|---|
container | HTMLElement | document.body | Specify a container element to portal the content into. |
Select.Content
The component that pops out when the select is open.
Name | Type | Default | Description |
---|---|---|---|
asChild | boolean | false | Change the default rendered element for the one passed as a child, merging their props and behavior. |
position | 'item-aligned' | 'popper' | 'item-aligned' | The positioning mode to use, `item-aligned` is the default and behaves similarly to a native MacOS menu by positioning content relative to the active item, while `popper` positions content in the same way as `Popover` and `Dropdown`. |
side | 'top' | 'right' | 'bottom' | 'left' | 'bottom' | The preferred side of the anchor to render against when open. Will be reversed when collisions occur and `avoidCollisions` is enabled. Only available when `position` is set to `popper`. |
sideOffset | number | 0 | The distance in pixels from the anchor. Only available when `position` is set to `popper`. |
align | 'start' | 'center' | 'end' | 'start' | The preferred alignment against the anchor. May change when collisions occur. Only available when `position` is set to `popper`. |
alignOffset | number | 0 | An offset in pixels from the 'start' or 'end' alignment options. Only available when `position` is set to `popper`. |
avoidCollisions | boolean | true | When `true`, overrides the side andalign preferences to prevent collisions with boundary edges. Only available when `position` is set to `popper`. |
collisionBoundary | Boundary | [] | The element used as the collision boundary. By default this is the viewport, though you can provide additional element(s) to be included in this check. Only available when `position` is set to `popper`. |
collisionPadding | Padding | [] | The distance in pixels from the boundary edges where collision detection should occur. Accepts a number (same for all sides), or a partial padding object, for example: `{ top: 20, left: 20 }`. Only available when `position` is set to `popper`. |
arrowPadding | number | 0 | The padding between the arrow and the edges of the content. If your content has `border-radius`, this will prevent it from overflowing the corners. Only available when `position` is set to `popper`. |
sticky | 'partial' | 'always' | 'partial' | The sticky behavior on the align axis. `'partial'` will keep the content in the boundary as long as the trigger is at least partially in the boundary whilst `'always'` will keep the content in the boundary regardless. Only available when `position` is set to `popper`. |
hideWhenDetached | boolean | false | Whether to hide the content when the trigger becomes fully occluded. Only available when `position` is set to `popper`. |
Events
Name | Type | Default | Description |
---|---|---|---|
onCloseAutoFocus | (event: Event) => void | - | Event handler called when focus moves to the trigger after closing. It can be prevented by calling `event.preventDefault`. |
onEscapeKeyDown | (event: KeyboardEvent) => void | - | Event handler called when the escape key is down. It can be prevented by calling `event.preventDefault`. |
onPointerDownOutside | (event: PointerDownOutsideEvent) => void | - | Event handler called when a pointer event occurs outside the bounds of the component. It can be prevented by calling `event.preventDefault`. |
onPointerDownOutside | (event: PointerDownOutsideEvent) => void | - | The positioning mode to use, `item-aligned` is the default and behaves similarly to a native MacOS menu by positioning content relative to the active item. Positions content in the same way as `Popover` and `Dropdown`. |
Data attributes
Data attribute | Values |
---|---|
[data-state] | 'open' | 'closed' |
[data-side] | 'left' | 'right' | 'bottom' | 'top' |
[data-align] | 'start' | 'end' | 'center' |
Select.Viewport
The scrolling viewport that contains all of the items.
Name | Type | Default | Description |
---|---|---|---|
asChild | boolean | false | Change the component to the HTML tag or custom component of the only child. This will merge the original component props with the props of the supplied element/component and change the underlying DOM node. |
Select.Item
The component that contains the select items.
Name | Type | Default | Description |
---|---|---|---|
asChild | boolean | false | Change the component to the HTML tag or custom component of the only child. This will merge the original component props with the props of the supplied element/component and change the underlying DOM node. |
value* | string | - | The value given as data when submitted with a name. |
disabled | boolean | - | When `true`, prevents the user from interacting with the item. |
textValue | string | - | Optional text used for typeahead purposes. By default the typeahead behavior will use the `.textContent` of the `Select.ItemText` part. Use this when the content is complex, or you have non-textual content inside. |
Data attributes
Data attribute | Values |
---|---|
[data-state] | 'checked' | 'unchecked' |
[data-highlighted] | Present when highlighted |
[data-disabled] | Present when disabled |
Select.ItemText
The textual part of the item. It should only contain the text you want to see in the trigger when that item is selected. It should not be styled to ensure correct positioning.
Name | Type | Default | Description |
---|---|---|---|
asChild | boolean | false | Change the component to the HTML tag or custom component of the only child. This will merge the original component props with the props of the supplied element/component and change the underlying DOM node. |
Select.ItemIndicator
Renders when the item is selected. You can style this element directly, or you can use it as a wrapper to put an icon into, or both.
Name | Type | Default | Description |
---|---|---|---|
asChild | boolean | false | Change the component to the HTML tag or custom component of the only child. This will merge the original component props with the props of the supplied element/component and change the underlying DOM node. |
Select.ScrollUpButton
An optional button used as an affordance to show the viewport overflow as well as functionaly enable scrolling upwards.
Name | Type | Default | Description |
---|---|---|---|
asChild | boolean | false | Change the component to the HTML tag or custom component of the only child. This will merge the original component props with the props of the supplied element/component and change the underlying DOM node. |
Select.ScrollDownButton
An optional button used as an affordance to show the viewport overflow as well as functionaly enable scrolling downwards.
Name | Type | Default | Description |
---|---|---|---|
asChild | boolean | false | Change the component to the HTML tag or custom component of the only child. This will merge the original component props with the props of the supplied element/component and change the underlying DOM node. |
Select.Group
Used to group multiple items. use in conjunction with Select.Label to ensure good accessibility via automatic labelling.
Name | Type | Default | Description |
---|---|---|---|
asChild | boolean | false | Change the component to the HTML tag or custom component of the only child. This will merge the original component props with the props of the supplied element/component and change the underlying DOM node. |
Select.Label
Used to render the label of a group. It won't be focusable using arrow keys.
Name | Type | Default | Description |
---|---|---|---|
asChild | boolean | false | Change the component to the HTML tag or custom component of the only child. This will merge the original component props with the props of the supplied element/component and change the underlying DOM node. |
Select.Separator
Used to visually separate items in the select.
Name | Type | Default | Description |
---|---|---|---|
asChild | boolean | false | Change the component to the HTML tag or custom component of the only child. This will merge the original component props with the props of the supplied element/component and change the underlying DOM node. |
Select.Arrow
An optional arrow element to render alongside the content. This can be used to help visually link the trigger with the Select.Content. Must be rendered inside Select.Content. Only available when `position` is set to `popper`.
Name | Type | Default | Description |
---|---|---|---|
asChild | boolean | false | Change the component to the HTML tag or custom component of the only child. This will merge the original component props with the props of the supplied element/component and change the underlying DOM node. |
width | number | 10 | The width of the arrow in pixels. |
width | number | 5 | The height of the arrow in pixels. |