ComboBox is the combination of a Textfield and an associated Dropdown that allows the user to filter a list when selecting an option. ComboBox allows users to type the full option, type part of the option and narrow the results, or select an option from the list.

also known as Typeahead, Autocomplete, Autosuggest

ComboBox is under an experiment to fix and improve underlying Popover component behavior. No visual updates. Visit the Pull Request to learn more.
; Opens a new tab
Figma:

Responsive:

Adaptive:

A11y:

Props

Component props
Name
Type
Default
id
Required
string
-

Unique id to identify each ComboBox. Used for accessibility purposes.

label
Required
string
-

Provide a label to identify the ComboBox field.

options
Required
$ReadOnlyArray<{
  label: string,
  subtext?: string,
  value: string,
}>
-

The data for each selection option. See subtext variant to learn more.

accessibilityClearButtonLabel
string
-

Label to describe the clear button's purpose.

disabled
boolean
false

When disabled, ComboBox looks inactive and cannot be interacted with. If tags are passed, they will appear disabled as well and cannot be removed. See tags variant to learn more.

errorMessage
React.Node
-

Provide feedback when an error on selection occurs. See error message variant.

helperText
string
-

Provides additional information about how to select a ComboBox option. See helper text variant.

inputValue
string | null
"null"

The user input in ComboBox for controlled components. See controlled ComboBox variant to learn more.

labelDisplay
"visible" | "hidden"
"visible"

Whether the label should be visible or not. If hidden, the label is still available for screen reader users, but does not appear visually. See the label visibility variant for more info.

noResultText
string
-

The text shown when the input value returns no matches.

onBlur
({
  event: SyntheticFocusEvent<HTMLInputElement> | SyntheticEvent<HTMLInputElement>,
  value: string,
}) => void
-

Callback when you focus outside the component.

onChange
({
  event: SyntheticInputEvent<HTMLInputElement>,
  value: string,
}) => void
-

Callback when user types into the control input field.

onClear
() => void
-

Callback when user clicks on clear button.

onFocus
({
  event: SyntheticFocusEvent<HTMLInputElement>,
  value: string,
}) => void
-

Callback when you focus on the component.

onKeyDown
({
  event: SyntheticKeyboardEvent<HTMLInputElement>,
  value: string,
}) => void
-

Callback for key stroke events. See tags variant to learn more.

onSelect
({
  event: SyntheticInputEvent<HTMLElement> | SyntheticKeyboardEvent<HTMLElement>,
  item: {
    label: string,
    subtext?: string,
    value: string,
  },
}) => void
-

Callback when an item is selected.

placeholder
string
-

Specify a short description that suggests the expected input for the field.

ref
React.Ref<"input">
-

Forward the ref to the underlying component container element. See the Ref variant to learn more about focus management.

selectedOption
{
  label: string,
  subtext?: string,
  value: string,
}
-

The selected option in ComboBox for controlled components. See controlled ComboBox variant to learn more.

size
"sm" | "md" | "lg"
"md"

Defines the height of ComboBox: sm: 32px, md: 40px, lg: 48px. See the size variant for more details.

tags
$ReadOnlyArray<React.Element<typeof Tag>>
-

List of tags to display in the component. See tags variant to learn more.

zIndex
Indexable
-

An object representing the zIndex value of the ComboBox list box. Learn more about zIndex classes

Usage guidelines

When to use
  • Presenting users with a long list of options (typically 10 or more) that can be filtered by typing in the text field.
When not to use
  • For shorter lists of items where filtering is not needed, typically under 10 items.

Best practices

Do

Use ComboBox to allow the user to edit or copy the textfield input values to select and/or narrow down from a given list of options.

Don't

Use ComboBox for a simple list of items. Use SelectList instead for the added native mobile functionality.

Accessibility

Labels

ComboBox requires both label and accessibilityClearButtonLabel. By default, the label is visible above TextField. However, if the form items are labeled by content elsewhere on the page, or a more complex label is needed, the labelDisplay prop can be used to visually hide the label. In this case, it is still available to screen reader users, but will not appear visually on the screen.

In the example below, the "Discover this week's top searched trends across all categories" text is acting as a heading, so instead of repeating another label, we visually hide the label. When a user focuses on the ComboBox, a screen reader will announce "Choose a category to display top search trends, Select category".

import { useState } from 'react';
import { Box, ComboBox, Flex, Heading, Link, Text } from 'gestalt';

export default function Example() {
  const CATEGORIES = [
    'All Categories',
    'Food and drinks',
    'Beauty',
    'Home decor',
    'Fashion',
    'Travel',
    'Art',
    'Quotes',
    'Entertainment',
    'Entertainment',
    'DIY and crafts',
    'Health',
    'Wedding',
    'Event planning',
    'Gardening',
    'Parenting',
    'Vehicles',
    'Design',
    'Sport',
    'Electronics',
    'Animals',
    'Finance',
    'Architecture',
  ];

  const options = CATEGORIES.map((category, index) => ({
    label: category,
    value: `value${index}`,
  }));

  const [errorMessage, setErrorMessage] = useState();

  const handleOnBlur = ({ value }) => {
    if (value !== '' && !CATEGORIES.includes(value))
      setErrorMessage('Please, select a valid option');
  };

  const resetErrorMessage = errorMessage ? () => setErrorMessage() : () => {};

  return (
    <Box padding={2}>
      <Flex direction="column" gap={4}>
        <Heading size="500">
          Discover this week&apos;s top searched trends across all categories
        </Heading>
        <Text inline>
          Wanna learn how trends work?
          <Text inline weight="bold">
            {' '}
            Read{' '}
            <Link
              accessibilityLabel="Learn how trends on Pinterest work"
              display="inlineBlock"
              href="https://business.pinterest.com/content/pinterest-predicts/"
              target="blank"
            >
              {' '}
              additional information
            </Link>
          </Text>
        </Text>
        <Flex justifyContent="center" width="100%">
          <Box width={320}>
            <ComboBox
              accessibilityClearButtonLabel="Clear category value"
              errorMessage={errorMessage}
              id="displayLabel"
              label="Choose a category to display top search trends"
              labelDisplay="hidden"
              noResultText="No results for your selection"
              onBlur={handleOnBlur}
              onChange={resetErrorMessage}
              onClear={resetErrorMessage}
              options={options}
              placeholder="Select category"
            />
          </Box>
        </Flex>
      </Flex>
    </Box>
  );
}

Keyboard interaction

  • Hitting Enter or Space key on the ComboBox's trigger opens the options list
  • Once an item is selected, hitting Enter or Space on the clear button clears the selection and returns focus to the input textfield
  • Escape key closes the options list, while moving focus back on the ComboBox's trigger
  • Arrow keys are used to navigate items within the options list
  • Enter key selects an item within the options list
  • Tab or Shift + Tab close the options list and move focus accordingly

Localization

Be sure to localize all text strings. Note that localization can lengthen text by 20 to 30 percent.

Note that accessibilityClearButtonLabel and noResultText are optional as DefaultLabelProvider provides default strings. Use custom labels if they need to be more specific.

ComboBox depends on DefaultLabelProvider for internal text strings. Localize the texts via DefaultLabelProvider. Learn more
import { useState } from 'react';
import { Box, ComboBox, DefaultLabelProvider, Flex } from 'gestalt';

export default function Example() {
  const PRONOUNS = [
    'Dey/Dem',
    'Er/Ihm',
    'Ey/Em',
    'He/Him',
    'Hen/Hens',
    'She/Her',
    'Sie/Ihr',
    'They/Them',
    'Xier/Xiem',
  ];

  const options = PRONOUNS.map((pronoun, index) => ({
    label: pronoun,
    value: `value${index}`,
  }));

  const [errorMessage, setErrorMessage] = useState();

  const resetErrorMessage = errorMessage ? () => setErrorMessage() : () => {};

  return (
    <DefaultLabelProvider
      // $FlowExpectedError[incompatible-type] For demostration purposes
      labels={{
        ComboBox: {
          noResultText: 'Keine Ergebnisse',
          accessibilityClearButtonLabel: 'Eingabe löschen.',
        },
      }}
    >
      <Flex
        alignItems="center"
        gap={4}
        height="100%"
        justifyContent="center"
        width="100%"
      >
        <Box paddingX={8} paddingY={8}>
          <ComboBox
            accessibilityClearButtonLabel="Löscht den aktuellen Wert"
            errorMessage={errorMessage}
            helperText="Wählen Sie die Pronomen, die in Ihrem Profil erscheinen sollen, damit andere wissen, wie sie Sie ansprechen sollen. Sie können diese jederzeit bearbeiten oder entfernen."
            id="header"
            label="Pronomen"
            onBlur={({ value }) => {
              if (value !== '' && !PRONOUNS.includes(value))
                setErrorMessage('Bitte wählen Sie eine gültige Option.');
            }}
            onChange={resetErrorMessage}
            onClear={resetErrorMessage}
            options={options}
            placeholder="Fügen Sie Ihre Pronomen hinzu"
          />
        </Box>
      </Flex>
    </DefaultLabelProvider>
  );
}

Variants

Controlled vs Uncontrolled

ComboBox can be used as a controlled or an uncontrolled component. An uncontrolled ComboBox stores its own state internally and updates it based on the user input. On the other side, a controlled ComboBox's state is managed by a parent component. The parent component's state passes new values through props to the controlled component which notifies changes through event callbacks.

Uncontrolled ComboBox

An uncontrolled ComboBox should be used for basic cases where no default value or tags are required. Don't pass inputValue or selectedOptions props to keep the component uncontrolled. By passing inputValue to ComboBox, the component fully manages its internal state: any value different from null and undefined makes Combobox controlled.

import { useState } from 'react';
import { Box, ComboBox, Flex } from 'gestalt';

export default function Example() {
  const PRONOUNS = [
    'ey / em',
    'he / him',
    'ne / nem',
    'she / her',
    'they / them',
    've / ver',
    'xe / xem',
    'xie / xem',
    'zie / zem',
  ];

  const options = PRONOUNS.map((pronoun, index) => ({
    label: pronoun,
    value: `value${index}`,
  }));

  const [errorMessage, setErrorMessage] = useState();

  const handleOnBlur = ({ value }) => {
    if (value !== '' && !PRONOUNS.includes(value))
      setErrorMessage('Please, select a valid option');
  };

  const resetErrorMessage = errorMessage ? () => setErrorMessage() : () => {};

  return (
    <Box height="100%" padding={2} width="100%">
      <Flex
        alignItems="center"
        height="100%"
        justifyContent="center"
        width="100%"
      >
        <Box width={320}>
          <ComboBox
            accessibilityClearButtonLabel="Clear the current value"
            errorMessage={errorMessage}
            helperText="Choose your pronouns to appear on your profile so others know how to refer to you. You can edit or remove these any time."
            id="uncontrolled"
            label="Pronouns"
            noResultText="No results for your selection"
            onBlur={handleOnBlur}
            onChange={resetErrorMessage}
            onClear={resetErrorMessage}
            options={options}
            placeholder="Add your pronouns"
          />
        </Box>
      </Flex>
    </Box>
  );
}

Controlled ComboBox

A controlled ComboBox is required if a selected value is set, as shown in the first example. In the second example, values are set programatically. Controlled Comboboxes with tags are also controlled components. A controlled ComboBox requires three value props: options, inputValue, and selectedOptions. ComboBox is notified of changes via the onChange, onSelect, onBlur, onFocus, onKeyDown, and onClear props. All values displayed by ComboBox at any time are controlled externally. To clear inputValue, set the value to an empty string inputValue = "", null or undefined values turn ComboBox into an uncontrolled component.

import { useState } from 'react';
import { Box, ComboBox, Flex, Text } from 'gestalt';

const US_STATES = [
  'AK - Alaska',
  'AL - Alabama',
  'AR - Arkansas',
  'AS - American Samoa',
  'AZ - Arizona',
  'CA - California',
  'CO - Colorado',
  'CT - Connecticut',
  'DC - District of Columbia',
  'DE - Delaware',
  'FL - Florida',
  'GA - Georgia',
  'GU - Guam',
  'HI - Hawaii',
  'IA - Iowa',
  'ID - Idaho',
  'IL - Illinois',
  'IN - Indiana',
  'KS - Kansas',
  'KY - Kentucky',
  'LA - Louisiana',
  'MA - Massachusetts',
  'MD - Maryland',
  'ME - Maine',
  'MI - Michigan',
  'MN - Minnesota',
  'MO - Missouri',
  'MS - Mississippi',
  'MT - Montana',
  'NC - North Carolina',
  'ND - North Dakota',
  'NE - Nebraska',
  'NH - New Hampshire',
  'NJ - New Jersey',
  'NM - New Mexico',
  'NV - Nevada',
  'NY - New York',
  'OH - Ohio',
  'OK - Oklahoma',
  'OR - Oregon',
  'PA - Pennsylvania',
  'PR - Puerto Rico',
  'RI - Rhode Island',
  'SC - South Carolina',
  'SD - South Dakota',
  'TN - Tennessee',
  'TX - Texas',
  'UT - Utah',
  'VA - Virginia',
  'VI - Virgin Islands',
  'VT - Vermont',
  'WA - Washington',
  'WI - Wisconsin',
  'WV - West Virginia',
  'WY - Wyoming',
];

export default function Example() {
  const usStatesOptions = US_STATES.map((pronoun, index) => ({
    label: pronoun,
    value: `value${index}`,
  }));

  const [suggestedOptions, setSuggestedOptions] = useState(usStatesOptions);
  const [inputValue, setInputValue] = useState(usStatesOptions[5].label);
  const [selected, setSelected] = useState(usStatesOptions[5]);

  const handleOnChange = ({ value }) => {
    setSelected();
    if (value) {
      setInputValue(value);
      const filteredOptions = usStatesOptions.filter((item) =>
        item.label.toLowerCase().includes(value.toLowerCase())
      );
      setSuggestedOptions(filteredOptions);
    } else {
      setInputValue(value);
      setSuggestedOptions(usStatesOptions);
    }
  };

  const handleSelect = ({ item }) => {
    setInputValue(item.label);
    setSuggestedOptions(usStatesOptions);
    setSelected(item);
  };

  return (
    <Box height="100%" padding={2} width="100%">
      <Flex
        alignItems="center"
        direction="column"
        gap={2}
        height="100%"
        justifyContent="center"
        width="100%"
      >
        <Box width={320}>
          <ComboBox
            accessibilityClearButtonLabel="Clear the current value"
            id="controlled"
            inputValue={inputValue}
            label="State"
            noResultText="No results for your selection"
            onBlur={() => {
              if (!selected) setInputValue('');
              setSuggestedOptions(usStatesOptions);
            }}
            onChange={handleOnChange}
            onClear={() => {
              setInputValue('');
              setSelected();
              setSuggestedOptions(usStatesOptions);
            }}
            onSelect={handleSelect}
            options={suggestedOptions}
            placeholder="Select a US state"
            selectedOption={selected}
          />
        </Box>
        {selected && selected.label ? (
          <Box width={320}>
            <Text>
              Estimated tax to be collected in {selected && selected.label} will
              be calculated at checkout
            </Text>
          </Box>
        ) : null}
      </Flex>
    </Box>
  );
}

import { useState } from 'react';
import { Box, Button, ComboBox, Flex } from 'gestalt';

export default function Example() {
  const CATEGORIES = {
    BEAUTY: [
      'Beauty tips',
      'DIY beauty',
      'Wedding beauty',
      'Vegan beauty products',
      'Beauty photography',
      'Beauty quotes',
      'Beauty illustration',
      'Beauty salon',
      'Beauty blender',
    ].map((pronoun, index) => ({ label: pronoun, value: `value${index}` })),
    DIY: [
      'DIY Projects',
      'DIY Art',
      'DIY Home decor',
      'DIY Furniture',
      'DIY Gifts',
      'DIY Wall decor',
      'DIY Clothes',
      'DIY Christmas decorations',
      'DIY Christmas gifts',
      'DIY Wall art',
    ].map((pronoun, index) => ({ label: pronoun, value: `value${index}` })),
  };

  const [currentCategory, setCurrentCategory] = useState('BEAUTY');

  const [suggestedOptions, setSuggestedOptions] = useState(
    CATEGORIES[currentCategory]
  );

  const [inputValue, setInputValue] = useState('');

  const [selectedOption, setSelectedOption] = useState();

  const resetOptions = () => {
    setSuggestedOptions(CATEGORIES[currentCategory]);
  };

  const handleOnChange = ({ value }) => {
    setSelectedOption();
    if (value) {
      setInputValue(value);
      const filteredOptions = CATEGORIES[currentCategory].filter((item) =>
        item.label.toLowerCase().includes(value.toLowerCase())
      );
      setSuggestedOptions(filteredOptions);
    } else {
      setInputValue(value);
      resetOptions();
    }
  };

  const handleSelect = ({ item }) => {
    setInputValue(item.label);
    setSelectedOption(item);
    resetOptions();
  };

  const handleOnBlur = () => {
    if (!selectedOption) setInputValue('');
    resetOptions();
  };

  const handleOnClear = () => {
    setInputValue('');
    setSelectedOption();
    resetOptions();
  };

  return (
    <Box height="100%" padding={2} width="100%">
      <Flex
        alignItems="center"
        height="100%"
        justifyContent="center"
        width="100%"
      >
        <Flex direction="column" gap={4}>
          <Button
            onClick={() => {
              const nextCategory =
                currentCategory === 'BEAUTY' ? 'DIY' : 'BEAUTY';
              setCurrentCategory(nextCategory);
              setSuggestedOptions(CATEGORIES[nextCategory]);
              setInputValue('');
            }}
            text={`Change options to ${
              currentCategory === 'BEAUTY' ? 'DIY' : 'BEAUTY'
            } category`}
          />
          <Box width={320}>
            <ComboBox
              accessibilityClearButtonLabel="Clear the current value"
              id="programaticallySet"
              inputValue={inputValue}
              label="Pin category"
              noResultText="No results for your selection"
              onBlur={handleOnBlur}
              onChange={handleOnChange}
              onClear={handleOnClear}
              onSelect={handleSelect}
              options={suggestedOptions}
              placeholder="Select a category"
              selectedOption={selectedOption}
              size="lg"
            />
          </Box>
        </Flex>
      </Flex>
    </Box>
  );
}

Tags

Include Tag elements in the input using the tags prop.

Note that the ComboBox component doesn't internally manage tags; therefore, it must be a controlled component. A controlled ComboBox requires three value props: options, inputValue, and tags.

To use ComboBox with tags, it's recommended to create new tags on enter key presses, to remove them on backspaces when the cursor is in the beginning of the field and to filter out empty tags. These best practices are shown in the following example.

import { useRef, useState } from 'react';
import { Box, ComboBox, Flex, Tag } from 'gestalt';

export default function Example() {
  const ref = useRef(null);
  const [selected, setSelected] = useState([]);
  const [searchTerm, setSearchTerm] = useState('');

  const PRONOUNS = [
    'ey / em',
    'he / him',
    'ne / nem',
    'she / her',
    'they / them',
    've / ver',
    'xe / xem',
    'xie / xem',
    'zie / zem',
  ];

  const options = PRONOUNS.map((pronoun, index) => ({
    label: pronoun,
    value: `value${index}`,
  }));

  const [suggestedOptions, setSuggestedOptions] = useState(
    options.filter((pronoun) => !selected.includes(pronoun.value))
  );

  const handleOnSelect = ({ item: { label } }) => {
    if (!selected.includes(label) && selected.length < 2) {
      const newSelected = [...selected, label];
      setSelected(newSelected);
      setSuggestedOptions(
        options.filter((pronoun) => !newSelected.includes(pronoun.label))
      );
      setSearchTerm('');
    }
  };

  const handleOnChange = ({ value }) => {
    setSearchTerm(value);

    const suggested = value
      ? suggestedOptions.filter((item) =>
          item.label.toLowerCase().includes(value.toLowerCase())
        )
      : options.filter((option) => !selected.includes(option.value));

    setSuggestedOptions(suggested);
  };

  const handleOnBlur = () => setSearchTerm('');

  const handleClear = () => {
    setSelected([]);
    setSuggestedOptions(options);
  };

  const handleOnKeyDown = ({ event: { keyCode, currentTarget } }) => {
    // Remove tag on backspace if the cursor is at the beginning of the field

    if (keyCode === 8 /* Backspace */ && currentTarget.selectionEnd === 0) {
      const newSelected = [...selected.slice(0, -1)];
      setSelected(newSelected);
      setSuggestedOptions(
        options.filter((pronoun) => !newSelected.includes(pronoun.label))
      );
    }
  };

  const handleRemoveTag = (removedValue) => {
    const newSelected = selected.filter(
      (tagValue) => tagValue !== removedValue
    );
    setSelected(newSelected);
    setSuggestedOptions(
      options.filter((pronoun) => !newSelected.includes(pronoun.label))
    );
  };

  const renderedTags = selected.map((pronoun) => (
    <Tag
      key={pronoun}
      accessibilityRemoveIconLabel={`Remove ${pronoun} tag`}
      onRemove={() => handleRemoveTag(pronoun)}
      text={pronoun}
    />
  ));

  return (
    <Box height="100%" padding={2} width="100%">
      <Flex
        alignItems="center"
        height="100%"
        justifyContent="center"
        width="100%"
      >
        <Box width={320}>
          <ComboBox
            ref={ref}
            accessibilityClearButtonLabel="Clear the current value"
            helperText="Choose up to 2 sets of pronouns to appear on your profile so others know how to refer to you. You can edit or remove these any time."
            id="tags"
            inputValue={searchTerm}
            label="Pronouns"
            noResultText="No results for your selection"
            onBlur={handleOnBlur}
            onChange={handleOnChange}
            onClear={handleClear}
            onKeyDown={handleOnKeyDown}
            onSelect={handleOnSelect}
            options={suggestedOptions}
            placeholder={selected.length > 0 ? '' : 'Add your pronouns'}
            tags={renderedTags}
          />
        </Box>
      </Flex>
    </Box>
  );
}

Ref

To control focus or position and anchor components to ComboBox, use ref as shown in the examples below.

Focus management with ref example
import { useRef } from 'react';
import { Box, ComboBox, Flex } from 'gestalt';

export default function Example() {
  const ref = useRef(null);

  return (
    <Box height="100%" padding={2} width="100%">
      <Flex
        alignItems="center"
        height="100%"
        justifyContent="center"
        width="100%"
      >
        <Flex direction="column" gap={4}>
          <Box width={320}>
            <ComboBox
              accessibilityClearButtonLabel="Clear the current values"
              id="favoriteShape"
              label="Select your favorite shape"
              noResultText="No results for your selection"
              onSelect={() => ref.current?.focus()}
              options={[
                { label: 'square', value: '1' },
                { label: 'circle', value: '2' },
              ]}
              placeholder="Select a shape"
            />
          </Box>
          <Box width={320}>
            <ComboBox
              ref={ref}
              accessibilityClearButtonLabel="Clear the current values"
              id="favoriteColor"
              label="Select your favorite color"
              noResultText="No results for your selection"
              options={[
                { label: 'red', value: '1' },
                { label: 'blue', value: '2' },
                { label: 'green', value: '3' },
                { label: 'yellow', value: '4' },
              ]}
              placeholder="Select a color"
            />
          </Box>
        </Flex>
      </Flex>
    </Box>
  );
}

Subtext

Display subtext under each selection option

import { Box, ComboBox, Flex } from 'gestalt';

export default function Example() {
  const options = Array(20)
    .fill(0)
    .map((item, index) => ({
      label: `Label-${index + 1}`,
      value: `Value-${index + 1}`,
      subtext: `Subtext-${index + 1}`,
    }));

  return (
    <Box height="100%" padding={2} width="100%">
      <Flex
        alignItems="center"
        height="100%"
        justifyContent="center"
        width="100%"
      >
        <Box width={320}>
          <ComboBox
            accessibilityClearButtonLabel="Clear the current value"
            id="subtext"
            label="Choose a value"
            noResultText="No results for your selection"
            options={options}
            placeholder="Select a value"
          />
        </Box>
      </Flex>
    </Box>
  );
}

Size

ComboBox can have different sizes. The default size is md (40px). The lg size is 48px. For a dense variant, use the sm (32px) variant.

import { useState } from 'react';
import { Box, ComboBox, Flex, SegmentedControl } from 'gestalt';

export default function Example() {
  const sizes = ['sm', 'md', 'lg'];
  const [size, setSize] = useState('md');
  const options = Array(20)
    .fill(0)
    .map((item, index) => ({
      label: `Label-${index + 1}`,
      value: `Value-${index + 1}`,
      subtext: `Subtext-${index + 1}`,
    }));

  return (
    <Box height="100%" padding={2} width="100%">
      <Flex
        alignItems="center"
        direction="column"
        height="100%"
        justifyContent="center"
        width="100%"
      >
        <Box width={320}>
          <ComboBox
            accessibilityClearButtonLabel="Clear the current value"
            id="subtext"
            label="Choose a value"
            noResultText="No results for your selection"
            options={options}
            placeholder="Select a value"
            size={size}
          />
          <Box paddingY={5}>
            <SegmentedControl
              items={sizes}
              onChange={({ activeIndex }) => {
                setSize(sizes[activeIndex]);
              }}
              selectedItemIndex={sizes.indexOf(size)}
              size="sm"
            />
          </Box>
        </Box>
      </Flex>
    </Box>
  );
}

Helper text

Whenever you want to provide more information about a form field, you should use helperText.

import { Box, ComboBox, Flex } from 'gestalt';

export default function Example() {
  return (
    <Box height="100%" padding={2} width="100%">
      <Flex
        alignItems="center"
        height="100%"
        justifyContent="center"
        width="100%"
      >
        <Box width={320}>
          <ComboBox
            accessibilityClearButtonLabel="Clear the current value"
            helperText="Select one from all your current active accounts."
            id="helperText"
            label="Select account"
            noResultText="No results for your selection"
            options={[]}
          />
        </Box>
      </Flex>
    </Box>
  );
}

Error message

For most use cases, pass a string with a helpful error message (be sure to localize!). In certain instances it can be useful to make some text clickable; to support this, you may instead pass a React.Node to wrap text in Link or TapArea

import { Box, ComboBox, Flex } from 'gestalt';

export default function Example() {
  return (
    <Box height="100%" padding={2} width="100%">
      <Flex
        alignItems="center"
        height="100%"
        justifyContent="center"
        width="100%"
      >
        <Box width={320}>
          <ComboBox
            accessibilityClearButtonLabel="Clear the current value"
            errorMessage="Please select a valid category"
            id="error"
            label="Category"
            noResultText="No results for your selection"
            options={[]}
          />
        </Box>
      </Flex>
    </Box>
  );
}

Component quality checklist

Component quality checklist
Quality item
Status
Status description
Figma Library
Ready
Component is available in Figma for web and mobile web.
Responsive Web
Ready
Component responds to changing viewport sizes in web and mobile web.

SelectList
If users need to select from a short, simple list (without needing sections, subtext details, or the ability to filter the list), use SelectList.

Dropdown
Dropdown is an element constructed using Popover as its container. Use Dropdown to display a list of actions or options in a Popover.

Fieldset
Use Fieldset to group related form items.