# @leafygreen-ui/select

> leafyGreen UI Kit Select

Latest version **17.1.0** (published 2026-07-17) · Apache-2.0 license · 0 weekly downloads

## Install

```sh
npm install @leafygreen-ui/select
pnpm add @leafygreen-ui/select
yarn add @leafygreen-ui/select
bun add @leafygreen-ui/select
```

## Health

**Score 70/100 (B)** — status: active.

Positive: has types; esm support; no vulnerabilities; has provenance; recently updated; high maintenance score.

Warnings: low downloads.

## Facts

| | |
|---|---|
| Version | 17.1.0 |
| Published | 2026-07-17 |
| First published | 2020-12-17 |
| Weekly downloads | 0 |
| License | Apache-2.0 |
| TypeScript types | bundled |
| Module format | ESM + CommonJS |
| Dependencies | 16 |
| Unpacked size | 540.4 KB |
| Known vulnerabilities | 0 |
| Install scripts | no |
| Provenance | attested (GitHub Actions) |
| GitHub stars | 271 |
| Maintainers | thesonofthomp, shaneeza, stephl3, aitchpgm, hnevins, _tsck |

## Links

- npm: https://www.npmjs.com/package/@leafygreen-ui/select
- Repository: https://github.com/mongodb/leafygreen-ui
- Homepage: https://github.com/mongodb/leafygreen-ui/tree/main/packages/select
- Issues: https://jira.mongodb.org/projects/PD/summary
- npm.io page: https://npm.io/package/@leafygreen-ui/select

## Dependencies (16)

- [lodash](https://npm.io/package/lodash.md) ^4.17.21
- [polished](https://npm.io/package/polished.md) ^4.1.3
- [react-is](https://npm.io/package/react-is.md) ^18.0.1
- [@types/react-is](https://npm.io/package/@types/react-is.md) ^18.0.0
- [@leafygreen-ui/lib](https://npm.io/package/@leafygreen-ui/lib.md) ^15.7.0
- [@leafygreen-ui/icon](https://npm.io/package/@leafygreen-ui/icon.md) ^14.9.0
- [@leafygreen-ui/hooks](https://npm.io/package/@leafygreen-ui/hooks.md) ^9.3.1
- [@leafygreen-ui/button](https://npm.io/package/@leafygreen-ui/button.md) ^25.2.1
- [@leafygreen-ui/tokens](https://npm.io/package/@leafygreen-ui/tokens.md) ^4.2.2
- [@leafygreen-ui/emotion](https://npm.io/package/@leafygreen-ui/emotion.md) ^5.2.0
- [@leafygreen-ui/palette](https://npm.io/package/@leafygreen-ui/palette.md) ^5.0.2
- [@leafygreen-ui/popover](https://npm.io/package/@leafygreen-ui/popover.md) ^14.3.2
- [@lg-tools/test-harnesses](https://npm.io/package/@lg-tools/test-harnesses.md) ^0.3.4
- [@leafygreen-ui/form-field](https://npm.io/package/@leafygreen-ui/form-field.md) ^4.0.9
- [@leafygreen-ui/typography](https://npm.io/package/@leafygreen-ui/typography.md) ^22.2.4
- [@leafygreen-ui/input-option](https://npm.io/package/@leafygreen-ui/input-option.md) ^4.1.5

## Recent versions

- 17.1.0 (latest) — 2026-07-17
- 17.0.3 — 2026-01-21
- 17.0.2 — 2025-11-24
- 17.0.1 — 2025-11-13
- 17.0.0 — 2025-11-06
- 16.3.0 — 2025-10-31
- 16.2.0 — 2025-10-21
- 16.1.4 — 2025-10-09
- 16.1.3 — 2025-09-25
- 16.1.2 — 2025-09-10
- 16.1.1 — 2025-09-03
- 16.1.0 — 2025-08-15
- 16.0.3 — 2025-07-28
- 16.0.2 — 2025-07-07
- 16.0.1 — 2025-07-03
- … 121 more at https://npm.io/package/@leafygreen-ui/select/versions

## README

# Select

![npm (scoped)](https://img.shields.io/npm/v/@leafygreen-ui/select.svg)

#### [View on MongoDB.design](https://www.mongodb.design/component/select/live-example/)

## Installation

### PNPM

```shell
pnpm add @leafygreen-ui/select
```

### Yarn

```shell
yarn add @leafygreen-ui/select
```

### NPM

```shell
npm install @leafygreen-ui/select
```

## Example

### Basic Usage

```js
import { Option, OptionGroup, Select, Size } from '@leafygreen-ui/select';

<Select
  label="Label"
  description="Description"
  placeholder="Placeholder"
  name="Name"
  size={Size.Default}
  defaultValue="cat"
>
  <Option value="dog" description="Bark">
    Dog
  </Option>
  <Option value="cat">Cat</Option>
  <OptionGroup label="Less common">
    <Option value="hamster">Hamster</Option>
    <Option value="parrot">Parrot</Option>
  </OptionGroup>
</Select>;
```

### Typed Values

`Select` accepts an optional type parameter (defaulting to `string`) to narrow the type of `value`, `defaultValue`, and the `onChange` callback value:

```tsx
type Pet = 'dog' | 'cat' | '';

const [value, setValue] = useState<Pet>('');

<Select<Pet> label="Pet" value={value} onChange={setValue}>
  <Option value="dog">Dog</Option>
  <Option value="cat">Cat</Option>
</Select>;
```

Note: when `allowDeselect` is enabled (default), deselecting calls `onChange` with `''` — include `''` in the union (as above) or set `allowDeselect={false}`.

Note: the type parameter narrows `value`, `defaultValue`, and `onChange` only — `Option` values are not checked against it (`<Option value="hamster">` above would still compile).

### Controlled Open State

```js
import { useState } from 'react';
import { Option, Select } from '@leafygreen-ui/select';

function ControlledSelect() {
  const [isOpen, setIsOpen] = useState(false);
  const [value, setValue] = useState('');

  return (
    <>
      <button onClick={() => setIsOpen(true)}>Open Select</button>
      <Select
        label="Controlled Select"
        open={isOpen}
        setOpen={setIsOpen}
        value={value}
        onChange={setValue}
      >
        <Option value="option1">Option 1</Option>
        <Option value="option2">Option 2</Option>
      </Select>
    </>
  );
}
```

## Select Properties

| Prop                 | Type                                                | Description                                                                                                                                                                                                                                                                                                                                                                           | Default                             |
| -------------------- | --------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------- |
| `children`           | `React.ReactNode`                                   | `<Option />` and `<OptionGroup />` elements.                                                                                                                                                                                                                                                                                                                                          |                                     |
| `className`          | `string`                                            | Adds a className to the outermost element.                                                                                                                                                                                                                                                                                                                                            |                                     |
| `darkMode`           | `boolean`                                           | Determines whether or not the component will appear in dark mode.                                                                                                                                                                                                                                                                                                                     | `false`                             |
| `size`               | `'xsmall'` \| `'small'` \| `'default'` \| `'large'` | Sets the size of the component's elements.                                                                                                                                                                                                                                                                                                                                            | `'default'`                         |
| `id`                 | `string`                                            | id associated with the Select component.                                                                                                                                                                                                                                                                                                                                              |                                     |
| `name`               | `string`                                            | The name that will be used when submitted as part of a form.                                                                                                                                                                                                                                                                                                                          |                                     |
| `label`              | `string`                                            | Text shown in bold above the input element.                                                                                                                                                                                                                                                                                                                                           |                                     |
| `aria-labelledby`    | `string`                                            | Must be provided if and only if neither `label` nor `aria-label` is not provided.                                                                                                                                                                                                                                                                                                     |
| `aria-label`         | `string`                                            | Must be provided if and only if neither `label` nor `aria-labelledby` is not provided.                                                                                                                                                                                                                                                                                                |                                     |
| `description`        | `React.ReactNode`                                   | Text that gives more detail about the requirements for the input.                                                                                                                                                                                                                                                                                                                     |                                     |
| `placeholder`        | `string`                                            | The placeholder text shown in the input element when an option is not selected.                                                                                                                                                                                                                                                                                                       | `'Select'`                          |
| `disabled`           | `boolean`                                           | Disables the component from being edited.                                                                                                                                                                                                                                                                                                                                             | `false`                             |
| `value`              | `T` (defaults to `string`)                          | Sets the `<Option />` that will appear selected and makes the component a controlled component. See [Typed Values](#typed-values).                                                                                                                                                                                                                                                    | `''`                                |
| `defaultValue`       | `T` (defaults to `string`)                          | Sets the `<Option />` that will appear selected on page load when the component is uncontrolled. See [Typed Values](#typed-values).                                                                                                                                                                                                                                                   | `''`                                |
| `onChange`           | `SelectOnChange<T>`                                 | A function that gets called when the selected value changes. Receives the value (type `T`) as the first argument and the event as the second. See [Typed Values](#typed-values).                                                                                                                                                                                                      | `() => {}`                          |
| `allowDeselect`      | `boolean`                                           | Enables or disables the option for a user to select a null default value.                                                                                                                                                                                                                                                                                                             | `true`                              |
| `open`               | `boolean`                                           | Controls whether the dropdown menu is open. When provided, the component becomes a controlled component for the open state.                                                                                                                                                                                                                                                           |                                     |
| `setOpen`            | `function`                                          | Callback function that is called when the open state should change. Required when `open` prop is provided. Receives a boolean value as the first argument.                                                                                                                                                                                                                            |                                     |
| `renderMode`         | `'inline'` \| `'portal'` \| `'top-layer'`           | Options to render the popover element <br> \* [deprecated] `'inline'` will render the popover element inline in the DOM where it's written <br> \* [deprecated] `'portal'` will render the popover element in a new div appended to the body. Alternatively, can be portaled into a provided `portalContainer` <br> \* `'top-layer'` will render the popover element in the top layer | `'top-layer'`                       |
| `portalContainer`    | `HTMLElement` \| `null`                             | Sets the container used for the popover's portal. NOTE: If using a `scrollContainer` make sure that the `portalContainer` is contained within the `scrollContainer`. E.g, passing the same refrence to `scrollContainer` and `portalContainer`.                                                                                                                                       |                                     |
| `scrollContainer`    | `HTMLElement` \| `null`                             | If the popover portal has a scrollable ancestor other than the window, this prop allows passing a reference to that lement to allow the portal to position properly.                                                                                                                                                                                                                  |                                     |
| `portalClassName`    | `string`                                            | Passes the given className to the popover's portal container if the default portal container is being used.                                                                                                                                                                                                                                                                           |                                     |
| `popoverZIndex`      | `number`                                            | Sets the z-index CSS property for the popover.                                                                                                                                                                                                                                                                                                                                        |                                     |
| `state`              | `'error'` \| `'none'` \| `'valid'`                  | Determines the state of the `<select>`                                                                                                                                                                                                                                                                                                                                                | `'none'`                            |
| `errorMessage`       | `string`                                            | Text that shows when the `state` is set to `error`.                                                                                                                                                                                                                                                                                                                                   | `'This input needs your attention'` |
| `successMessage`     | `string`                                            | Text that shows when the `state` is set to `valid`.                                                                                                                                                                                                                                                                                                                                   | `'Success'`                         |
| `baseFontSize`       | `'13'` \| `'16'`                                    | Determines the base font size if sizeVariant is set to `default`                                                                                                                                                                                                                                                                                                                      | `'13'`                              |
| `dropdownWidthBasis` | `'option'` \| `'trigger'`                           | Determines the width of the dropdown. `trigger` will make the dropdown width the width of the menu trigger. `option` will make the dropdown width as wide as the widest option.                                                                                                                                                                                                       | `trigger`                           |

# Option

| Prop          | Type                 | Description                                                                                           | Default                     |
| ------------- | -------------------- | ----------------------------------------------------------------------------------------------------- | --------------------------- |
| `children`    | `string` \| `number` | Content to appear inside of the component.                                                            |                             |
| `className`   | `string`             | Adds a className to the outermost element.                                                            |                             |
| `glyph`       | `React.ReactElement` | Icon to display next to the option text.                                                              |                             |
| `value`       | `string`             | Corresponds to the value passed into the `onChange` prop of `<Select />` when the option is selected. | text contents of `children` |
| `description` | `string`             | Optional descriptive text under the value                                                             |                             |
| `disabled`    | `boolean`            | Prevents the option from being selectable.                                                            | `false`                     |

# OptionGroup

| Prop        | Type      | Description                                               | Default |
| ----------- | --------- | --------------------------------------------------------- | ------- |
| `children`  | `node`    | `<Option />` elements                                     |         |
| `className` | `string`  | Adds a className to the outermost element.                |         |
| `label`     | `string`  | Text shown above the group's options.                     |         |
| `disabled`  | `boolean` | Prevents all the contained options from being selectable. | `false` |

# Test Harnesses

## getTestUtils()

`getTestUtils()` is a util that allows consumers to reliably interact with `LG Select` in a product test suite. If the `Select` component cannot be found, an error will be thrown.

### Usage

```tsx
import { Select, getTestUtils } from '@leafygreen-ui/select';

const utils = getTestUtils(lgId?: string); // lgId refers to the custom `data-lgid` attribute passed to `Select`. It defaults to 'lg-select' if left empty.
```

#### Single `Select`

```tsx
import { render } from '@testing-library/react';
import userEvent from '@testing-library/user-event';
import { Select, getTestUtils } from '@leafygreen-ui/select';

...

test('select', () => {
  render(
    <Select
      label="Label"
      description="Description"
    >
      <Option value="dog" description="Bark">
        Dog
      </Option>
      <Option value="cat">Cat</Option>
      <OptionGroup label="Less common">
        <Option value="hamster">Hamster</Option>
        <Option value="parrot">Parrot</Option>
      </OptionGroup>
    </Select>
  );

  const { getInputValue, getInput, getOptions } = getTestUtils();

  expect(getInput()).toBeInTheDocument();
  expect(getInputValue()).toBe('Select');

  // opens the select
  userEvent.click(getInput());
  // `select` is an option
  expect(getOptions()).toHaveLength(5);
});
```

#### Multiple `Select`'s

When testing multiple `Select`'s it is recommended to add the custom `data-lgid` attribute to each `Select`.

```tsx
import { render } from '@testing-library/react';
import { Select, getTestUtils } from '@leafygreen-ui/select';

...

test('select', () => {
  render(
    <>
      <Select
        label="Label 1"
        description="Description 1"
        data-lgid="select-1"
      >
        <Option value="dog" description="Bark">
          Dog
        </Option>
        <Option value="cat">Cat</Option>
        <OptionGroup label="Less common">
          <Option value="hamster">Hamster</Option>
          <Option value="parrot">Parrot</Option>
        </OptionGroup>
      </Select>
      <Select
        label="Label 2"
        description="Description 2"
        data-lgid="select-2"
        defaultValue="sad cat"
      >
        <Option value="sad dog" description="Sad Bark Bark">
          Sad Dog
        </Option>
        <Option value="sad cat">Sad Cat</Option>
        <OptionGroup label="Less common">
          <Option value="sad hamster">Sad Hamster</Option>
          <Option value="sad parrot">Sad Parrot</Option>
        </OptionGroup>
      </Select>
    </>,
  );
  const lgUtilsSelect1 = getTestUtils('select-1'); // data-lgid
  const lgUtilsSelect2 = getTestUtils('select-2'); // data-lgid

  // First Select
  expect(lgUtilsSelect1.getInput()).toBeInTheDocument();
  expect(lgUtilsSelect1.getInputValue()).toBe('Select');

  // Second Select
  expect(lgUtilsSelect2.getInput()).toBeInTheDocument();
  expect(lgUtilsSelect2.getInputValue()).toBe('sad cat');
});
```

#### Select with other LG elements

```tsx
import { render } from '@testing-library/react';
import TextInput, { getTestUtils as getTextInputTestUtils } from '@leafygreen-ui/text-input';
import { Select, getTestUtils as getSelectTestUtils } from '@leafygreen-ui/select';

...

test('Form', () => {
  render(
    <Form>
      <TextInput label="TextInput label" />
      <Select
        label="Label 1"
        description="Description 1"
      >
        <Option value="dog" description="Bark">
          Dog
        </Option>
        <Option value="cat">Cat</Option>
        <OptionGroup label="Less common">
          <Option value="hamster">Hamster</Option>
          <Option value="parrot">Parrot</Option>
        </OptionGroup>
      </Select>
    </Form>,
  );

  const lgUtilsTextInput = getTextInputTestUtils();
  const lgUtilsSelect = getSelectTestUtils();

  // LG TextInput
  expect(lgUtilsTextInput.getInput()).toBeInTheDocument();
  expect(lgUtilsTextInput.getInputValue()).toBe('');

  // LG Select
  expect(lgUtilsSelect.getInput()).toBeInTheDocument();
  expect(lgUtilsSelect.getInputValue()).toBe('Select');
});
```

### Test Utils

#### Elements

```tsx
const {
  getInput,
  getLabel,
  getDescription,
  getErrorMessage,
  getOptions,
  getOptionByValue,
  getPopover,
  getInputValue,
  isDisabled,
  isValid,
  isError,
} = getTestUtils();
```

| Util                       | Description                                | Returns                       |
| -------------------------- | ------------------------------------------ | ----------------------------- |
| `getInput()`               | Returns the input node                     | `HTMLButtonElement`           |
| `getLabel()`               | Returns the label node                     | `HTMLButtonElement` \| `null` |
| `getDescription()`         | Returns the description node               | `HTMLButtonElement` \| `null` |
| `getErrorMessage()`        | Returns the error message node             | `HTMLButtonElement` \| `null` |
| `getOptions()`             | Returns an array of options                | `Array<HTMLLIElement>`        |
| `getOptionByValue(string)` | Returns an individual option               | `HTMLLIElement` \| `null`     |
| `getPopover()`             | Returns the dropdown popover               | `HTMLDivElement` \| `null`    |
| `getInputValue()`          | Returns the input value                    | `string`                      |
| `isDisabled()`             | Returns whether the input is disabled      | `boolean`                     |
| `isError()`                | Returns whether the input state is `error` | `boolean`                     |

---
_Source: https://npm.io/package/@leafygreen-ui/select · Machine-readable twin of the npm.io package page. Health data is recomputed on every publish._
