Select
Select allows users to make a single selection or multiple selections from a list of options.Neutral selected states
When the platform-dst-tokens-finesse feature flag is enabled, this component uses the new neutral treatment for selected states.
Motion in Early Access
Motion updates for multi-value Select tags are in Early Access and available behind the platform-dst-motion-uplift-labels feature flag.
Async select
Select now supports to handle loading data from remote sources by default, please use loadOptions
prop that can be given a promise or callback that will eventually resolve to its list of options
instead of options.
import React from 'react';
import { Label } from '@atlaskit/form/label/default';
import Select from '@atlaskit/select/default';
import { type OptionsType } from '@atlaskit/select/types';
import { cities } from '../common/data';
const filterCities = (inputValue: string) =>
cities.filter((i) => i.label.toLowerCase().includes(inputValue.toLowerCase()));
const promiseOptions = (inputValue: string) =>
new Promise<OptionsType>((resolve) => {
setTimeout(() => {
resolve(filterCities(inputValue));
}, 1000);
});
const WithPromises = () => {
return (
<>
<Label htmlFor="async-select-example">What city do you live in?</Label>
<Select
inputId="async-select-example"
cacheOptions
defaultOptions
loadOptions={promiseOptions}
/>
</>
);
};
export default (): React.JSX.Element => <WithPromises />;Single select
Allows the user to select a single item from a dropdown list of options.
import React from 'react';
import { Label } from '@atlaskit/form/label/default';
import Select from '@atlaskit/select/default';
const SelectSingleExample = (): React.JSX.Element => (
<>
<Label htmlFor="single-select-example">What city do you live in?</Label>
<Select
inputId="single-select-example"
testId="react-select"
options={[
{ label: 'Adelaide', value: 'adelaide' },
{ label: 'Brisbane', value: 'brisbane' },
{ label: 'Canberra', value: 'canberra' },
{ label: 'Darwin', value: 'darwin' },
{ label: 'Hobart', value: 'hobart' },
{ label: 'Melbourne', value: 'melbourne' },
{ label: 'Perth', value: 'perth' },
{ label: 'Sydney', value: 'sydney' },
]}
placeholder=""
/>
</>
);
export default SelectSingleExample;Single select clearable
Setting isClearable to true lets users clear their selection using the Backspace or Delete key.
import React from 'react';
import { Label } from '@atlaskit/form/label/default';
import Select from '@atlaskit/select/default';
const SelectSingleClearable = (): React.JSX.Element => (
<>
<Label htmlFor="single-select-example-clearable">What city do you live in?</Label>
<Select
inputId="single-select-example-clearable"
testId="react-select"
isClearable={true}
clearControlLabel="Clear city"
options={[
{ label: 'Adelaide', value: 'adelaide' },
{ label: 'Brisbane', value: 'brisbane' },
{ label: 'Canberra', value: 'canberra' },
{ label: 'Darwin', value: 'darwin' },
{ label: 'Hobart', value: 'hobart' },
{ label: 'Melbourne', value: 'melbourne' },
{ label: 'Perth', value: 'perth' },
{ label: 'Sydney', value: 'sydney' },
]}
placeholder=""
/>
</>
);
export default SelectSingleClearable;Multi select
Allows the user to select multiple items from a dropdown list of options.
import React from 'react';
import { Label } from '@atlaskit/form/label/default';
import Select from '@atlaskit/select/default';
import { cities } from '../common/data';
const SelectMultiExample = (): React.JSX.Element => (
<>
<Label htmlFor="multi-select-example">What cities have you lived in?</Label>
<Select
inputId="multi-select-example"
testId="react-select"
options={cities}
isMulti
isSearchable={false}
placeholder=""
/>
</>
);
export default SelectMultiExample;Grouped options
Related options can be grouped together in both a single and multi select.
import React from 'react';
import { Label } from '@atlaskit/form/label/default';
import Select from '@atlaskit/select/default';
const SelectGroupedOptionsExample = (): React.JSX.Element => (
<>
<Label htmlFor="grouped-options-example">What city do you live in?</Label>
<Select
inputId="grouped-options-example"
testId="react-select"
options={[
{
label: 'NSW',
options: [
{ label: 'Sydney', value: 's' },
{ label: 'Newcastle', value: 'n' },
],
},
{
label: 'QLD',
options: [
{ label: 'Brisbane', value: 'b' },
{ label: 'Gold coast', value: 'g' },
],
},
{
label: 'Other',
options: [
{ label: 'Canberra', value: 'c' },
{ label: 'Williamsdale', value: 'w' },
{ label: 'Darwin', value: 'd' },
{ label: 'Perth', value: 'p' },
],
},
]}
placeholder=""
/>
</>
);
export default SelectGroupedOptionsExample;Appearance
Default
The default select appearance.
import React from 'react';
import { Label } from '@atlaskit/form/label/default';
import Select from '@atlaskit/select/default';
export default function SelectAppearanceDefault(): React.JSX.Element {
return (
<>
<Label htmlFor="default-appearance-example">Favorite fruit</Label>
<Select
inputId="default-appearance-example"
appearance="default"
options={[
{ label: 'Apple', value: 'a' },
{ label: 'Banana', value: 'b' },
]}
/>
</>
);
}Subtle
A select that's transparent until interaction or error.
import React from 'react';
import { Label } from '@atlaskit/form/label/default';
import Select from '@atlaskit/select/default';
export default function SelectAppearanceSubtle(): React.JSX.Element {
return (
<>
<Label htmlFor="subtle-appearance-example">Favorite fruit</Label>
<Select
inputId="subtle-appearance-example"
appearance="subtle"
options={[
{ label: 'Apple', value: 'a' },
{ label: 'Banana', value: 'b' },
]}
/>
</>
);
}Style customization
The Select component provides flexible styling options to customize its appearance and behavior.
With the migration to Compiled CSS, we now offer enhanced styling capabilities through the
components API with xcss prop support.
Recommended: Components API with xcss
The preferred method for customizing Select styles is using the components API with the xcss prop.
This approach provides type-safe, performant styling with Compiled CSS-in-JS.
// oxlint-disable-next-line no-unused-vars
import { Fragment, type JSX } from 'react';
import { cssMap, cx, jsx } from '@compiled/react';
import { Label } from '@atlaskit/form/label/default';
import { components } from '@atlaskit/react-select/components';
import Select from '@atlaskit/select/default';
import { token } from '@atlaskit/tokens';
import { cities } from '../common/data';
const controlStyles = cssMap({
root: {
minHeight: '40px',
},
focused: {
boxShadow: `0 0 0 2px ${token('color.border.focused')}`,
},
});
const _default: () => JSX.Element = () => (
<>
<Label htmlFor="indicators-dropdown">What city do you live in?</Label>
<Select
components={{
Control: (props) => (
<components.Control
{...props}
xcss={cx(controlStyles.root, props.isFocused && controlStyles.focused)}
/>
),
}}
options={cities}
/>
</>
);
export default _default;Legacy: Styles Prop (Limited Support)
The styles prop is still supported for backward compatibility, but has limitations with certain
CSS selectors.
import React from 'react';
import { Label } from '@atlaskit/form/label/default';
import Select from '@atlaskit/select/default';
import { token } from '@atlaskit/tokens';
import { cities } from '../common/data';
export default (): React.JSX.Element => (
<>
<Label htmlFor="indicators-dropdown">What city do you live in?</Label>
<Select
styles={{
control: (provided, state) => ({
...provided,
backgroundColor: token('elevation.surface'),
borderColor: state.isFocused ? token('color.border.selected') : token('color.border'),
}),
}}
options={cities}
/>
</>
);Component customization
The following components are customizable and switchable:
Clear indicator
The indicator is presented to clear the values from a multi-select. The default component is a cross. The indicator will not render when:
isClearableis false, orisMultiis false andisClearableis undefined- the select is disabled
- the select has no value
- the select is loading
The clear control has been intentionally removed from the tab order. It can confuse people across multiple disability cohorts and be cumbersome for sighted people who use keyboards.
Instead, the clear control is optimized for pointer interactions, like mouse click or tap. And
people using a keyboard will use the DELETE key to clear contents and CTRL+A to select all.
import { type CSSProperties, Fragment, type FunctionComponent, type JSX } from 'react';
import { cssMap, cx, jsx } from '@compiled/react';
import { Label } from '@atlaskit/form/label/default';
import { Box } from '@atlaskit/primitives/compiled';
import Select from '@atlaskit/select/default';
import type { ClearIndicatorProps, OptionType } from '@atlaskit/select/types';
import { token } from '@atlaskit/tokens';
import { cities } from '../common/data';
const clearIndicatorStyles = cssMap({
default: {
paddingInline: token('space.050'),
color: token('color.text'),
},
focus: {
color: token('color.text.brand'),
},
});
const CustomClearText: FunctionComponent = () => <Fragment>clear all</Fragment>;
const ClearIndicator = (props: ClearIndicatorProps<OptionType, true>) => {
const {
children = <CustomClearText />,
getStyles,
innerProps: { ref, ...restInnerProps },
isFocused,
} = props;
return (
<div
{...restInnerProps}
ref={ref}
style={getStyles('clearIndicator', props) as CSSProperties}
>
<Box xcss={cx(clearIndicatorStyles.default, isFocused && clearIndicatorStyles.focus)}>
{children}
</Box>
</div>
);
};
const _default: () => JSX.Element = () => (
<Fragment>
<Label htmlFor="indicators-clear">What city do you live in?</Label>
<Select
inputId="indicators-clear"
closeMenuOnSelect={false}
components={{ ClearIndicator }}
defaultValue={[cities[4], cities[5]]}
isMulti
options={cities}
/>
</Fragment>
);
export default _default;Dropdown indicator
The indicator for opening the Select is designed to indicate to users that this is a Select
component. By default, it is a chevron pointed down, but in this example we have replaced it with an
emoji.
import React from 'react';
import { Label } from '@atlaskit/form/label/default';
import EmojiIcon from '@atlaskit/icon/core/emoji';
import { components } from '@atlaskit/react-select/components';
import Select from '@atlaskit/select/default';
import type { DropdownIndicatorProps, OptionType } from '@atlaskit/select/types';
import { cities } from '../common/data';
const DropdownIndicator = (props: DropdownIndicatorProps<OptionType, true>) => {
return (
<components.DropdownIndicator {...props}>
<EmojiIcon label="Emoji" />
</components.DropdownIndicator>
);
};
export default (): React.JSX.Element => (
<>
<Label htmlFor="indicators-dropdown">What city do you live in?</Label>
<Select
inputId="indicators-dropdown"
closeMenuOnSelect={false}
components={{ DropdownIndicator }}
defaultValue={[cities[4], cities[5]]}
isMulti
options={cities}
/>
</>
);Loading indicator
Loading indicator to be displayed in the Indicators Container when isLoading is true.
import React from 'react';
import { Label } from '@atlaskit/form/label/default';
import Select from '@atlaskit/select/default';
import type { OptionType } from '@atlaskit/select/types';
import { cities } from '../common/data';
const filterCities = (inputValue: string) =>
cities.filter((i) => i.label.toLowerCase().includes(inputValue.toLowerCase()));
const promiseOptions = (inputValue: string) =>
new Promise<OptionType[]>((resolve) => {
setTimeout(() => {
resolve(filterCities(inputValue));
}, 1000);
});
export default (): React.JSX.Element => {
return (
<>
<Label htmlFor="indicators-loading">What city do you live in?</Label>
<Select
inputId="indicators-loading"
cacheOptions
defaultOptions
loadOptions={promiseOptions}
/>
</>
);
};