Skip to content

Select

Select provides users with a dropdown menu of options.
Figma logo
  • SelectField is a field element that wrapsSelect with label, helper, and validation text.
  • We rely on the the native styling because the native element provides an enormous amount of functionality for all users, whether or not they are using assistive technologies.
Select
  • Higher cognitive load than Radio
  • Options are hidden and require effort for the user to reveal them
  • Generally takes up less space on the page
Radio
  • Lower cognitive load than Select
  • Options are always visible
  • A good choice when there are only a few options

Basic SelectField implementation with validation via Formik.

Basic SelectField with grouped options.

  • SelectField will occupy the width of its parent by default.
  • The fit prop can be used to limit the width of the container to the length of its options.

Disabled states should be used with caution.

It may sometimes be necessary to hide labels, but label text must still be made available for screen readers. This example uses visuallyHidden to visually hide the label.

React props
NameTypeDefaultDescription
after  ReactNodeContent shown after the inpinputut value. By default this content is not interactive and will ignore pointer events. Any interactive elements must be styled with pointer-events: auto;
before  ReactNodeContent shown before the input value. By default this content is not interactive and will ignore pointer events. Any interactive elements must be styled with pointer-events: auto;
children  RequiredReactNodeIndividual options related to the group.
counter  ReactNodeIndicator of a limit placed on a field, e.g. maximum character count or remaining hours. Frequently used with CharacterCount.
disabled  booleanIf true, the elements in this group will be disabled.
helperText  ReactNodeAdditional descriptive information for the input.
invalid  booleanfalseIf true, the input will be shown in an invalid state.
label  RequiredReactNodeLabel for the associated input.
name  RequiredstringName of the input. Submitted with the form as part of a name/value pair.
optionalText  stringText used to indicate that a field is not required.
validationText  ReactNodeValidation message associated with the input.

The following testing snippet(s) offer suggestions for testing the component using React Testing Library with occasional help from Jest.

// BASIC TESTS
render(
<Select aria-label="State">
<Option value="">Select…</Option>
<Option value="CA">California</Option>
<Option value="NY">New York</Option>
</Select>,
);
const select = screen.getByLabelText('State');
userEvent.selectOptions(select, 'NY');
expect(select).toHaveDisplayValue('New York');
// TESTING MULTIPLE SELECTION
render(
<Select aria-label="State" multiple>
<Option value="">Select…</Option>
<Option value="CA">California</Option>
<Option value="NY">New York</Option>
</Select>,
);
const select = screen.getByLabelText('State');
userEvent.selectOptions(select, ['NY', 'CA']);
expect(select).toHaveDisplayValue(['New York', 'California']);
userEvent.deselectOptions(select, 'CA');
expect(select).toHaveDisplayValue('New York');
// TESTING VALIDITY
render(
<Select aria-label="Label" invalid>
<Option value="">Select…</Option>
</Select>,
);
const select = screen.getByLabelText('Label');
expect(select).toBeInvalid(); // or expect(select).not.toBeValid();
// TESTING BEFORE AND AFTER
render(
<Select aria-label="Label" invalid before="Before" after="After">
<Option value="">Select…</Option>
</Select>,
);
const selectContainer = screen.getByLabelText('Label').parentElement as HTMLDivElement;
expect(selectContainer).toHaveTextContent('Before');
expect(selectContainer).toHaveTextContent('After');