Skip to main content

Select

Used to allow a user to select a value from a list of options.

Import

import { Select, Option } from '@pluralsight/react'

Anatomy

  1. Container
  2. Select
  3. Icon
  4. Option

Usage

Basic Select

function BasicSelect() {
  const [fruit, setFruit] = useState('')

  function handleChange(e) {
    setFruit(e.target.value)
  }

  return (
    <FormControlProvider required={true}>
      <Label htmlFor="fruit">Select Fruit</Label>
      <Select
        describedBy="select:help"
        id="fruit"
        name="fruit"
        onChange={handleChange}
      >
        <Option value="apple">Apple</Option>
        <Option value="banana">Banana</Option>
        <Option value="Passionfruit">Passionfruit</Option>
      </Select>
      <FieldMessage id="select:help">Please choose a fruit.</FieldMessage>
    </FormControlProvider>
  )
}

States

The Select shares the same UI states as every field in Pando.

Customizing

There are 3 ways to customize the Select component.

1. Unused Classes

Each component layer of the Select has a unused class name that can be utilized in your local CSS to customize the Select at any level.

  1. pando-select-fieldwrapper: The container of the Select.
  2. pando-select: The Select element.
  3. pando-select-icon: The Icon element.
  4. pando-select-wrapper: The wrapper of the Select.
  5. pando-select-option: The Option element.

2. Passing a className prop

You can pass a className prop to the Select component to customize the Select. This is useful if your project uses CSS Modules or a CSS-in-JS library like Emotion.

import customStyles from './customStyles.module.css'

function CustomSelect(props) {
  return <Select className={customStyles.custom} {...props} />
}

function CustomOption(props) {
  return <Option className={customStyles.customOption} {...props} />
}

3. Ejected Select

For a low-level "ejected" approach, you can use the Headless-styles API to customize the Select however you prefer while keeping the accessibility behavior.

import {
  getSelectProps,
  getSelectOptionProps,
} from '@pluralsight/headless-styles'

To learn more about the Headless-styles API, check out the Headless-styles documentation.

Behavior

Layout

Do use a hidden label when using a Select within a Table Cell.

Don't exclude a label when using a Select within a Table Cell, which is not accessible.

Usage

Do use a Select when the list of options exceeds 5 items.

Don't use a Select when the list of options is less than 5 items. Instead, use a Radio group.

Do use a Select when a single option choice is needed from a user.

Don't use a Select to navigate to another location. Instead use a Menu.

Do use a Modal with a Checkbox List when you need to use a multi-select field.

Don't use Select to create a multi-select field.

Do use the styles provided by the Select Option to keep the experience native to the OS/Browser.

Don't re-style or fake a Select Option which is not accessbile and creates a poor user experience for all platforms.

API

Select: FC<SelectProps>

interface SelectProps extends SelectHTMLAttributes<HTMLSelectElement> {
  describedBy?: string
  pandoSize: 'm' | 'l'
}

Parameters

  1. Any props that can be passed to a select element.
  2. describedBy: The id of the element that describes the Select.
  3. pandoSize: The size of the Select.

Option: FC<OptionProps>

interface OptionProps extends HTMLAttributes<OptionHTMLElement> {
  value: string
}

Parameters

  1. Any props that can be passed to an option element.
  2. value: The value of the option.

Accessibility

The Pando Select/Option is fully accessible and screen-readable through the following features:

  1. The aria-invalid attribute is set to true when the select is invalid.
  2. The aria-describedby attribute is set to the id of the FieldMessage or ErrorMessage that describes the select.
  3. The aria-required attribute is set to true when the select is required.
  4. When no value is passed to an Option, the hidden and disabled attributes are set to true.
  5. All icons are hidden from screen readers.