Select

One choice from a list that stays collapsed until opened.

StableSince 1.0.0
On this page

Import

import { Select } from '@envsemble/envui';

Usage

<Select
  label="Visibility"
  items={[
    { value: 'team', label: 'Team' },
    { value: 'private', label: 'Private' },
    {
      value: 'public',
      label: 'Public',
      description: 'Turned off by your administrator',
      disabled: true,
    },
  ]}
  value={visibility}
  onValueChange={setVisibility}
/>

Each item has a value, a label, optionally a muted description under the label in the list, read as the option's description, and disabled where it can't be chosen. Control it with value and onValueChange, or leave it uncontrolled with defaultValue; with neither, nothing is chosen and the trigger shows placeholder. label, description and error work as on TextField.

In a form

<form onSubmit={invite}>
  <TextField label="E-mail address" name="email" type="email" required />
  <Select label="Role" name="role" items={roleOptions} defaultValue="editor" />
  <Button type="submit">Send invitation</Button>
</form>

With name, a hidden input submits the chosen value, and a form reset restores defaultValue. required makes the browser refuse the form while nothing is chosen and move focus to the trigger, and autoComplete gives the browser's autofill a hint, such as country.

In list rows

Where a row's title names the select, give the select that name as its aria-label; it is then as wide as its longest option.

Sizes

size is sm, md or lg; without it, the field takes its container's control height. visibleLabel={false} keeps the label for assistive technology only, as on a TextField, and the field fits its longest option.

Composition

The field is env-field with env-select, a text field's frame.

  • Its well, env-select-control, holds the trigger, env-select-trigger: the chosen option's label, env-select-value, the label and the chevron, env-select-icon.
  • The open list is the shared popup, with its list, env-select-list. Its options are the popup's rows.
  • className and style reach the field's root, and ref the trigger.
  • defaultOpen opens the list on the first render. open and onOpenChange, which receives why, control it.
  • readOnly shows the choice in the resting outline, which doesn't answer the pointer, its chevron muted, and doesn't open the list.

Customize

Its popup is frosted, as every popup is: --env-popup-opacity, --env-popup-blur and --env-popup-shadow, set on a theme, change it, as Popover describes.

Accessibility

You provide

  • A label, or aria-label where the name shows elsewhere.
  • A name for a select in a form.
  • Validation and the error message.

envUI provides

  • A combobox trigger with a listbox of options, the select-only combobox pattern.
  • The label, description and error tied to the trigger, and aria-invalid.
  • Focus into the list as it opens and back to the trigger as it closes.
  • A hidden input for form submission, validation and reset.

Props

Select

One choice from a list that stays collapsed until opened: an outlined field, as TextField is, whose button shows the chosen option and opens a popup list, where a check mark shows the chosen option, with its label inside, a description, an error and native form participation.

PropTypeDescription
ref
Ref<HTMLButtonElement>
The trigger, the button that shows the chosen option and opens the list.
className
string
The field's class, on its root element, beside env-field and env-select.
style
CSSProperties
Styles of the field's root element.
itemsrequired
readonly SelectItem[]
The options of the list, in order, each with a value, a label, an optional description and whether it is disabled.
value
stringnull
The chosen option's value in a controlled select, or null for none, which shows the placeholder; update it from onValueChange.
defaultValue
stringnull
The chosen option's value an uncontrolled select starts with; a native form reset returns to it. Without it, nothing is chosen and the trigger shows the placeholder.
onValueChange
(value: string | null) => void
Receives the value of the option people choose.
open
boolean
Whether the list is open, for a select the application controls with onOpenChange.
defaultOpenDefault false
boolean
Whether the list of an uncontrolled select starts open, such as in a picture of the open list.
onOpenChange
(open: boolean, details: SelectOpenChangeDetails) => void
Receives the requested state, and why, each time the list asks to open or close.
readOnlyDefault false
boolean
People can read the chosen option, and a form submits it, but the list doesn't open.
name
string
Submits the chosen option's value with a form under this name, through a hidden input.
requiredDefault false
boolean
Require a choice before the form submits: the browser refuses the form and moves focus to the trigger while nothing is chosen.
placeholder
string
What the trigger shows while nothing is chosen, such as Choose an owner.
autoComplete
string
A hint for the browser's autofill, such as country, set on the hidden input.
label
ReactNode
The field's visible name, such as Project name; it also names the control for assistive technology.
description
ReactNode
Lasting guidance under the field, such as a format or a limit, linked to the control as its description.
error
ReactNode
A message under the field that says how to correct the value. While it is set, the control is invalid (aria-invalid) and the message joins its description, after the description.
size
'sm''md''lg'
The control height, sm, md or lg; without it, the container's, and else md. sm is for a field with its label hidden.
visibleLabelDefault true
boolean
The label shows in the field, where it rests while the field is empty and floats into the outline while the field is in use or has a value. false hides it, for a field whose purpose is clear without it, such as a search in a toolbar: the label still names the field for assistive technology, and a placeholder gives the visible guidance.

Also accepts the native props of <button>, such as ref, className and aria-* attributes.

Part names

Each part's class and state attributes are public and versioned, for an application's CSS to style.

env-select
The select field.
env-select-control
The outlined well that holds the button, the label and the chevron.
env-select-end
The chevron's place at the end of the well.
env-select-icon
The chevron.
env-select-item
One option.
env-select-item-indicator
The check of the chosen option.
env-select-label
The label, inside the well, which floats into the outline.
env-select-list
The list of options.
env-select-placeholder
What the button shows while nothing is chosen.
env-select-popup
The popup with the options.
env-select-sizer
The labels of every option, hidden, which give the field its width without a visible label.
env-select-trigger
The button that shows the value and opens the list.
env-select-value
The chosen option's label.
data-disabled
Any value, or present on env-select-item
data-highlighted
Any value, or present on env-select-item
data-label-floating
Present on env-select-control
data-label-hidden
Any value, or present
data-selected
Any value, or present on env-select-item

Color properties

Each sets a color of one instance, through style or CSS; its hover, focus and press follow it. They are public and versioned.

--env-select-container
The field's well, transparent by default.
--env-select-content
The chosen option's label and the chevron.
--env-select-outline
The field's edge at rest.

Changelog

1.0.0

showLabel is visibleLabel, named after the label that visibleLabel={false} hides.

options is items, and SelectOption is SelectItem; hint is description; variant="outlined" is variant="outline". className and style style the field's root rather than the trigger, which takes ref. The trigger is a Button, the popup the shared popup and the options its rows: env-dropdown-trigger is env-select-trigger, env-dropdown-options env-select-popup, env-dropdown-list env-select-list, env-dropdown-option env-select-item and env-dropdown-option-check env-select-item-indicator.

The open list takes the level-2 elevation edge, with no shadow.

1.0.0-prerelease.6

The chevron turns over --env-motion-duration-medium with --env-motion-ease-enter as the list opens, and back in --env-motion-duration-fast with --env-motion-ease-exit, done when the list is.

The list opens over --env-motion-duration-medium, fading in and growing from 98 % with --env-motion-ease-enter, rather than growing from 96 % over the slow duration, so it shows from its first frames rather than late.

The chevron turns half a circle as the list opens and closes, rather than flipping over.

While its list is open, the field keeps its focused frame, the accent edge and label, also when focus is in the popup, as when it opens under the pointer.

In an option with a description, the check mark and the leading content sit on the label's line rather than across both lines.

The floating variant and the variant prop are gone: the field is outlined, and takes size="lg" in a long form on a page. The field takes a text area's rounded corners rather than round ends. A small one with a visible label takes the medium height, so its floated label and its value each have room, and says so in the console while developing: sm is for a field with its label hidden.

The open list is at least as wide as the field; when options have descriptions it grows up to 20 rem, or the field's width where that is more, and longer descriptions wrap.

1.0.0-prerelease.5

Select is an outlined field, as TextField and DatePicker are, with the label inside: variant is outline, the default, or floating, where it was a Button's secondary or outline. Without a visible label it fits its longest option. It takes open, onOpenChange, readOnly and showLabel.

The open list is frosted: the popup's color lets a little of what is behind through, blurred, with a soft shadow and no outline edge but a faint hairline in dark, and is solid with its edge at high contrast and with reduced transparency. Options are the md control height in body text, the highlighted one, under the pointer or the keyboard, takes the neutral fill with no focus ring, and the chosen one takes the selection's fill as well as its check mark. The list opens 8 px clear of the trigger at every scale and size. Its options lie one under the next with no space between them. The chosen option's check mark ends its row, after the label. The outline trigger has no fill at rest, as an outline button has none.