The Basics

What it is

Select allows users to enter data by selecting options from a predefined list. Users can also type to filter the list of predefined options. This restricts users to a specific set of options and enhances the predictability of the entered data. Select is commonly used in forms and comes in two primary variants: Single selection and Multi selection.

 

Key differences between Single selection and Multi selection

 

FeatureSingle selectionMulti selection
Number of selections allowed11 or more
Grouped selectionsOptionalOptional
Ofter used forSelecting a select option from a predefined list, validating user input, collecting categorical dataCollecting categorical data

 

How it works

 

Single selectionMulti selection
The user clicks or focuses on Select, which makes it activeThe user clicks or focuses on Select, which makes it active
A Forge dropdown appears, listing all available optionsA Forge dropdown appears, listing all available options, with a checkbox next to each one
Typing in the field filters the list of optionsTyping in the field filters the list of option
When the user hovers on an option, it’s highlightedWhen the user hovers on an option, it’s highlighted
When the user clicks an option, it appears in the fieldWhen the user clicks an option, its box is checked, and it appears in the field as a Tag.
To remove a selected option, the user can click the Remove(Close) icon or use the Delete key in the fieldTo remove a selected option, the user can click the Close icon in the Tag, uncheck its box in the dropdown list, or use the Delete key in the field
If the user types a full text string in the field and there are no matching options, “No options found” appears. You may optionally allow users to create their own options via the 'allowUserCreatedOptions' prop.If the user types a full text string in the field and there are no matching options, “No options found” appears. You may optionally allow users to create their own options via the 'allowUserCreatedOptions' prop.
After selecting the desired option in the list, the user navigates away from the fieldAfter selecting all desired options in the list, the user navigates away from the field
Selections are generally not saved until another action is taken (typically by using a button, like “Submit”)Selections are generally not saved until another action is taken (typically by using a button, like “Submit”)

 

When to use

  • To ask users to select options from a list
  • For long lists that would take up too much vertical space on the page

When not to use

  • For short lists that can appear directly on the page, reducing the number of clicks

What to use instead

List

Use List to display all list options on the page.

RadioGroup

Use RadioGroup to display all list options on the page.

Menu

Use Menu for navigation and filtering via dropdown menu

How to use

Select can be used as a standalone component, but it’s better when used with Form and FormField. Form  provides a consistent and responsive layout, while FormField adds features like labels, error message handling, and hint text.

 

Filtering the options list

Typing in the field automatically displays a filtered list of options that match the input. This helps users find specific options in long lists (e.g., typing “hyper” to narrow down a long list of diagnoses).

The filtering function compares the input to the text and value for every option in the list and displays the matches. For example, if an option's text is “Tylenol” and its value is “acetaminophen”, then the input “ace” is a match. If the input doesn't match anything in the list, “No options found” appears below the field.

 

Loading the options list

The dropdown options list can be loaded synchronously or asynchronously.

  • Synchronous (on page load)
    • Use for predefined lists that don’t change often.
    • Loads at the same time as the rest of the page, so that when the component is activated, it displays the full list of options immediately.
    • As users start typing in the field, matches appear instantly.
    • Lists with hundreds or thousands of entries can slow down page load significantly.
  • Asynchronous (after page load)
    • Use for lists that are hosted elsewhere and change more frequently.
    • Loads when users start typing (default) or when the component is activated.
    • As users start typing in the field, “Loading...” appears, followed by matches.
    • Reduces initial page load time but can also make the component feel slow as it searches the full list of options for matches.
    • Can show a short list of predefined options when the dropdown is first opened, before users start typing. For example, a Select with hundreds of medications can first display the top 5 frequently prescribed meds.
    • Once users enter text into the field, the predefined options disappear.

 

Grouping

The dropdown options list can be loaded in groups/categories with stylized group headers

  • Use groups for pre-filtering options

 

Tips for use in forms

With FormField, the label appears to the left of Select by default. The label indicates the type of data users are being asked to select (“Provider”).

Placeholder text appears inside the field before the user has interacted with it and offers short instructions for how to use the component.

Always use a label with Multi style Select, and don’t use its placeholder text as a label. This is an accessibility best practice.

Do:

Use a label to indicate what data users should enter.

<p>Use a label to indicate what data users should enter.</p>
Don't:

Use placeholder text as a label.

<p>Use placeholder text as a label.</p>

Style

Design details

Required fields

Forge offers 3 options to indicate required form fields. See Form for details.

Spacing and size

Select is available in three sizes:

  • Small (22px H)
  • Medium (28px H)
  • Large (32px H)

When used in forms, the size of this component and the vertical space around it vary according to the form layout (i.e., medium, compact, super-compact). See Form for details on which Select corresponds to which Form size.

Placement and hierarchy

No additional information for this component.

Content

There’s no maximum length for option text. When a long option is selected and added to the input field, it’s automatically truncated to one line of text. Use sentence case for option text (“Abdominal pain”, not “Abdominal Pain”).

Use sentence case for label text (“Patient care team”, not “Patient Care Team”).

Use sentence case for placeholder text. It defaults to “- Type or Select -”, but you can change it to reflect the content of your list (“- Type or select patient names -”).

If no options match the input, “No options found” appears. You can change this to reflect the content of your list (“No patients found”).

If loading the options list asynchronously, “Loading...” appears at the top of the list by default, but you can change this to reflect the content of your list (“Loading patients…”).

Demos

Select Standalone Share

Multi Select In Form Field Share

Select With User Entered Options Share

Select With Grouped Options Share

Select With Styled Status Tag Share

Single Select Synchronous Share

Multi Select Asynchronous Share

Coding

Developer tips

Select uses the react-select library. Any props not used by Select (see Props table) are passed down to react-select. It can be used on its own or as an input in FormField.

Known issue with dropdown

The react-select library has a known dropdown issue, where the dropdown remains at a fixed position if the parent container has a scrollbar independent from the rest of the window. This can occur when using the CSS property overflow:auto. Until this is fixed, we suggest using the disablePortal prop as a workaround, unless you’re using Select in Lightbox or Modal (this workaround isn’t suitable for these 2 components).

Asynchronous usage

  • Filtering
    • When loading options asynchronously, Select doesn’t automatically handle option filtering (matching the user input string to option text and values). You must build this into the loadAsyncOptions function. See the Demos for an example of option filtering for asynchronous use.
  • Loading options on input vs. loading options on mount
    • By default, Select doesn’t load options until users start typing in the input field. To display options before user input (on click or focus), use the initialAsyncOptions prop.
    • You can provide initialAsyncOptions with a predefined set of options to display or set initialAsyncOptions to {true}, which tells Select to load options on mount using the function provided to the loadAsyncOptions prop.

Caching

Select sets the cacheOptions prop to {true} by default. This causes the component to cache the options that are loaded for each unique input. Set this prop to {false} to disable caching. To maintain good application performance, pay attention to the size of your cache. cacheOptions continues to cache loaded options until the prop’s value changes; it can be reset or altered manually at any time.

Memoization

It is important to use functions such as useMemo to to not generate new option values on every render. Otherwise keyboard navigation does not work as well as it should.

Required fields

Use the required prop to mark Select as required.

Forge offers 3 options to indicate required form fields. When using Form with this component, set Form’s requiredVariation prop. See Form for details.

User Created Options

Use the allowUserCreatedOptions prop to allow users to input their own options into Select. When set, the user is able to type and select an option that isn't on the existing list of options.

For more control over what user-entered text is allowed to become a new option, the isValidNewOption prop can be used instead of allowUserCreatedOptions.

Repository

Implementation links

Select directory in Bitbucket

Implementation details

It is strongly recommended to familiarize yourself with the Forge source code. While this documentation is a best effort to document the intent and usage of a component, sometimes some features only become clear when looking at the source code. Also, looking at Forge's source code may help identify and fix bugs in either your application or Forge itself.

Storybook files

Forge maintains at least one storybook file per component. While the primary audience for these files is typically the Forge team, these storybook files may cover usages of the component not covered by a demo. The storybook for the latest version of forge can be found at go/forge-storybook.

Testing library

Forge strongly encourages using testing-library to write tests for your application.

"The more your tests resemble the way your software is used, the more confidence they can give you."

If you're having trouble testing a Forge component using testing-library, it would be a good idea to see how Forge tests its own components. For the most part, Forge tries to use screen.getByRole as much as it can, as that API provides the best feedback on a11y compliance. Forge discourages the use of document.querySelector and screen.getByTestId as both APIs encourage using implementation details to test your component, and discourage adding roles to your component.

With that being said, many of Forge's components were not built with accessibility in mind. These components do break the recommendations listed above.

Import statements

In Nimbus applications

athenaOne serves the Forge bundle independently from your application's bundle. Importing Forge components directly from '@athena/forge' takes advantage of this feature.

import { Select } from '@athena/forge'

In standalone applications

Importing components using the exact path to the module takes advantage of webpack's tree shaking feature. Webpack will include only that module and its dependencies.

import Select from '@athena/forge/Select';

To use this import guidance, Typescript applications must use typescript >= 4.7.3, and should add this setting to their tsconfig.json file:

{
"compilerOptions": {
"moduleResolution": "Node16",
}
}

If this setting doesn't work for your application, use this import statement instead:

import Select from '@athena/forge/dist/Select';

Props