Props
Usage guidelines
- When presenting users with a list of options that utilizes the native select functionality of the browser or device.
- When presenting users with a list of options to choose from, like display settings.
Best practices
Use SelectList when the user needs to select from a simple list of items.
Use SelectList when additional functionality such as subtext or images are needed. Use Dropdown instead.
Order the list items in SelectList either alphabetically or by usage.
Use SelectList if there are fewer than 4 items in the list and there is space to display all options. Use RadioGroup instead.
Accessibility
Labels
SelectList comes with
Label built-in: just use the label
prop. We strongly encourage always supplying a label. Be sure to provide a unique id
so the Label is associated with the correct SelectList.
If SelectList is 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.
import { useState } from 'react'; import { Box, Flex, SelectList } from 'gestalt'; export default function Example() { const [range, setRange] = useState(''); return ( <Box padding={8} width="100%"> <Flex direction="column" gap={6} width="100%"> <SelectList id="selectlist-visible-label" label="Date range" onChange={({ value }) => setRange(value)} placeholder="Select a country" size="md" value={range} > {[ { label: 'Last 5 days', value: '5' }, { label: 'Last week', value: '7' }, { label: 'Last 30 days', value: '30' }, { label: 'Last sixth months', value: '6m' }, { label: 'Last year', value: '365' }, ].map(({ label, value }) => ( <SelectList.Option key={label} label={label} value={value} /> ))} </SelectList> <SelectList id="selectlist-visible-label" label="Date range" onChange={({ value }) => setRange(value)} placeholder="Select a country" size="lg" value={range} > {[ { label: 'Last 5 days', value: '5' }, { label: 'Last week', value: '7' }, { label: 'Last 30 days', value: '30' }, { label: 'Last sixth months', value: '6m' }, { label: 'Last year', value: '365' }, ].map(({ label, value }) => ( <SelectList.Option key={label} label={label} value={value} /> ))} </SelectList> </Flex> </Box> ); }
Subcomponents
SelectList.Option
Use SelectList.Option to define the available options within SelectList.
SelectList.Option Props
SelectList.Group
Use SelectList.Group to group a subset of the options within SelectList.
SelectList.Group Props
Variants
Controlled component
SelectList must be used as a controlled component when the placeholder
or value
props are needed. When used in this manner, onChange
and value
are required, while placeholder
is optional.
import { useState } from 'react'; import { Box, SelectList } from 'gestalt'; export default function Example() { const [country, setCountry] = useState(''); return ( <Box padding={8} width="100%"> <SelectList id="selectlist-controlled" label="Country" name="country" onChange={({ value }) => setCountry(value)} placeholder="Select a country" value={country} > {[ { label: 'Algeria', value: 'algeria' }, { label: 'Belgium', value: 'belgium' }, { label: 'Canada', value: 'canada' }, { label: 'Denmark', value: 'denmark' }, { label: 'Egypt', value: 'egypt' }, { label: 'France', value: 'france' }, ].map(({ label, value }) => ( <SelectList.Option key={label} label={label} value={value} /> ))} </SelectList> </Box> ); }
Size
Use lg
as the recommended size within Pinterest products.
Use md
on denser surfaces, such as business products or internal tools.
import { Box, Flex, SelectList } from 'gestalt'; export default function Example() { return ( <Box padding={8} width="100%"> <Flex direction="column" gap={6} width="100%"> <SelectList id="selectlistMd" label="Country" onChange={() => {}} size="md" > {[ { label: 'Algeria', value: 'algeria' }, { label: 'Belgium', value: 'belgium' }, { label: 'Canada', value: 'canada' }, { label: 'Denmark', value: 'denmark' }, { label: 'Egypt', value: 'egypt' }, { label: 'France', value: 'france' }, ].map(({ label, value }) => ( <SelectList.Option key={label} label={label} value={value} /> ))} </SelectList> <SelectList id="selectlistLg" label="Country" onChange={() => {}} size="lg" > {[ { label: 'Algeria', value: 'algeria' }, { label: 'Belgium', value: 'belgium' }, { label: 'Canada', value: 'canada' }, { label: 'Denmark', value: 'denmark' }, { label: 'Egypt', value: 'egypt' }, { label: 'France', value: 'france' }, ].map(({ label, value }) => ( <SelectList.Option key={label} label={label} value={value} /> ))} </SelectList> </Flex> </Box> ); }
State
Enabled
The enabled state of Textfield that represents it can be interacted with.Disabled
TextFields cannot be interacted with using the mouse or keyboard. They also do not need to meet contrast requirements, so do not use them to present info to the user (use "readOnly" instead).Error
TextField can display an error message. Simply pass in anerrorMessage
when there is an error present and TextField will handle the rest. Don't useerrorMessage
to provide feedback on character count errors. See the maximum length variant for more details.x
import { useState } from 'react'; import { Box, Flex, SelectList } from 'gestalt'; export default function Example() { const [country, setCountry] = useState(''); return ( <Box padding={8} width="100%"> <Flex direction="column" gap={6} width="100%"> <SelectList id="selectlist-enabled" label="Country" name="country" onChange={({ value }) => setCountry(value)} placeholder="Select a country" size="md" value={country} > {[ { label: 'Algeria', value: 'algeria' }, { label: 'Belgium', value: 'belgium' }, { label: 'Canada', value: 'canada' }, { label: 'Denmark', value: 'denmark' }, { label: 'Egypt', value: 'egypt' }, { label: 'France', value: 'france' }, ].map(({ label, value }) => ( <SelectList.Option key={label} label={label} value={value} /> ))} </SelectList> <SelectList id="selectlist-enabled" label="Country" name="country" onChange={({ value }) => setCountry(value)} placeholder="Select a country" size="lg" value={country} > {[ { label: 'Algeria', value: 'algeria' }, { label: 'Belgium', value: 'belgium' }, { label: 'Canada', value: 'canada' }, { label: 'Denmark', value: 'denmark' }, { label: 'Egypt', value: 'egypt' }, { label: 'France', value: 'france' }, ].map(({ label, value }) => ( <SelectList.Option key={label} label={label} value={value} /> ))} </SelectList> </Flex> </Box> ); }
import { useState } from 'react'; import { Box, Flex, SelectList } from 'gestalt'; export default function Example() { const [country, setCountry] = useState(''); return ( <Box padding={8} width="100%"> <Flex direction="column" gap={6} width="100%"> <SelectList disabled id="selectlist-disabled" label="Country" name="country" onChange={({ value }) => setCountry(value)} placeholder="Select a country" size="md" value={country} > {[ { label: 'Algeria', value: 'algeria' }, { label: 'Belgium', value: 'belgium' }, { label: 'Canada', value: 'canada' }, { label: 'Denmark', value: 'denmark' }, { label: 'Egypt', value: 'egypt' }, { label: 'France', value: 'france' }, ].map(({ label, value }) => ( <SelectList.Option key={label} label={label} value={value} /> ))} </SelectList> <SelectList disabled id="selectlist-disabled" label="Country" name="country" onChange={({ value }) => setCountry(value)} placeholder="Select a country" size="lg" value={country} > {[ { label: 'Algeria', value: 'algeria' }, { label: 'Belgium', value: 'belgium' }, { label: 'Canada', value: 'canada' }, { label: 'Denmark', value: 'denmark' }, { label: 'Egypt', value: 'egypt' }, { label: 'France', value: 'france' }, ].map(({ label, value }) => ( <SelectList.Option key={label} label={label} value={value} /> ))} </SelectList> </Flex> </Box> ); }
import { useState } from 'react'; import { Box, Flex, SelectList } from 'gestalt'; export default function Example() { const [country, setCountry] = useState(''); return ( <Box padding={8} width="100%"> <Flex direction="column" gap={6} width="100%"> <SelectList errorMessage="You must select a country" id="selectlist-error" label="Country" name="country" onChange={({ value }) => setCountry(value)} placeholder="Select a country" size="md" value={country} > {[ { label: 'Algeria', value: 'algeria' }, { label: 'Belgium', value: 'belgium' }, { label: 'Canada', value: 'canada' }, { label: 'Denmark', value: 'denmark' }, { label: 'Egypt', value: 'egypt' }, { label: 'France', value: 'france' }, ].map(({ label, value }) => ( <SelectList.Option key={label} label={label} value={value} /> ))} </SelectList> <SelectList errorMessage="You must select a country" id="selectlist-error" label="Country" name="country" onChange={({ value }) => setCountry(value)} placeholder="Select a country" size="lg" value={country} > {[ { label: 'Algeria', value: 'algeria' }, { label: 'Belgium', value: 'belgium' }, { label: 'Canada', value: 'canada' }, { label: 'Denmark', value: 'denmark' }, { label: 'Egypt', value: 'egypt' }, { label: 'France', value: 'france' }, ].map(({ label, value }) => ( <SelectList.Option key={label} label={label} value={value} /> ))} </SelectList> </Flex> </Box> ); }
Label
'label' is an optional prop; however, TextField should always be properly labelled. Learn about accessibility best practices regarding labels.
- Built-in label. Preferred. Consistent Textfield design and tested accessibility.
In some cases, the label for a TextField is represented in a different way visually, as demonstrated below. We can take 2 approaches in this case.
Labelled Textfield (Label + Textfield). This is the best approach when a custom label is needed. The label focuses the Textfield when pressed.
Hidden built-in label (Label + Textfield). This is the best approach when there's significant visual distance between the label and the input. You can set
labelDisplay="hidden"
to ensure TextField is properly labeled for screen readers while using a different element to represent the label visually. The 'visual' label doesn't focus the Textfield when pressed.
import { useState } from 'react'; import { Box, Flex, SelectList } from 'gestalt'; export default function Example() { const [range, setRange] = useState(''); return ( <Box padding={8} width="100%"> <Flex direction="column" gap={6} width="100%"> <SelectList id="selectlist-visible-label" label="Date range" onChange={({ value }) => setRange(value)} placeholder="Select a country" size="md" value={range} > {[ { label: 'Last 5 days', value: '5' }, { label: 'Last week', value: '7' }, { label: 'Last 30 days', value: '30' }, { label: 'Last sixth months', value: '6m' }, { label: 'Last year', value: '365' }, ].map(({ label, value }) => ( <SelectList.Option key={label} label={label} value={value} /> ))} </SelectList> <SelectList id="selectlist-visible-label" label="Date range" onChange={({ value }) => setRange(value)} placeholder="Select a country" size="lg" value={range} > {[ { label: 'Last 5 days', value: '5' }, { label: 'Last week', value: '7' }, { label: 'Last 30 days', value: '30' }, { label: 'Last sixth months', value: '6m' }, { label: 'Last year', value: '365' }, ].map(({ label, value }) => ( <SelectList.Option key={label} label={label} value={value} /> ))} </SelectList> </Flex> </Box> ); }
import { Box, Flex, IconButton, Label, SelectList, Text } from 'gestalt'; export default function Example() { return ( <Box padding={8} width="100%"> <Flex direction="column" gap={6} width="100%"> <Flex direction="column" gap={2}> <Label htmlFor="selectList-labelled"> <Flex alignItems="center" gap={1}> <Text size="300">Date range</Text> <IconButton accessibilityLabel="Info" icon="info-circle" size="sm" tooltip={{ text: 'Options available are based on your usage.', idealDirection: 'right', }} /> </Flex> </Label> <SelectList id="selectList-labelled" label="Date range" labelDisplay="hidden" onChange={() => {}} size="md" > {[ { label: 'Last 5 days', value: '5' }, { label: 'Last week', value: '7' }, { label: 'Last 30 days', value: '30' }, { label: 'Last sixth months', value: '6m' }, { label: 'Last year', value: '365' }, ].map(({ label, value }) => ( <SelectList.Option key={label} label={label} value={value} /> ))} </SelectList> </Flex> <Flex direction="column" gap={2}> <Label htmlFor="selectList-labelled"> <Flex alignItems="center" gap={1}> <Text size="300">Date range</Text> <IconButton accessibilityLabel="Info" icon="info-circle" size="sm" tooltip={{ text: 'Options available are based on your usage.', idealDirection: 'right', }} /> </Flex> </Label> <SelectList id="selectList-labelled" label="Date range" labelDisplay="hidden" onChange={() => {}} size="lg" > {[ { label: 'Last 5 days', value: '5' }, { label: 'Last week', value: '7' }, { label: 'Last 30 days', value: '30' }, { label: 'Last sixth months', value: '6m' }, { label: 'Last year', value: '365' }, ].map(({ label, value }) => ( <SelectList.Option key={label} label={label} value={value} /> ))} </SelectList> </Flex> </Flex> </Box> ); }
import { useState } from 'react'; import { BannerSlim, Box, Flex, SelectList, Text } from 'gestalt'; export default function Example() { const [range, setRange] = useState(''); return ( <Box padding={8} width="100%"> <Flex direction="column" gap={6}> <Text size="400" weight="bold"> Select a Pin release date range </Text> <BannerSlim iconAccessibilityLabel="Recommendation" message="Pin launches work better on weekends." type="recommendationBare" /> <SelectList id="selectlist-hidden-label" label="Date range" labelDisplay="hidden" onChange={({ value }) => setRange(value)} placeholder="Select a country" value={range} > {[ { label: 'Last 5 days', value: '5' }, { label: 'Last week', value: '7' }, { label: 'Last 30 days', value: '30' }, { label: 'Last sixth months', value: '6m' }, { label: 'Last year', value: '365' }, ].map(({ label, value }) => ( <SelectList.Option key={label} label={label} value={value} /> ))} </SelectList> </Flex> </Box> ); }
Helper text
Helper text should be used when additional description may be required to understand the SelectList. Common examples include text that is legally required to be displayed, or instructions to fill out a form (e.g. proper formatting). If the text is optional, Tooltip could be used instead.
import { Box, Flex, SelectList } from 'gestalt'; export default function Example() { return ( <Box padding={8} width="100%"> <Flex direction="column" gap={6} width="100%"> <SelectList helperText="Product prices in your data source without an ISO currency code will default to this currency" id="selectlistHelperText" label="Default currency" onChange={() => {}} size="md" > {[ { label: 'ARS - Argentine peso', value: 'ars' }, { label: 'AUD - Australian dollar', value: 'aud' }, { label: 'ERN - Eritrean nakfa', value: 'ern' }, { label: 'EUR - Euro', value: 'eur' }, { label: 'GBP - British pound', value: 'gbp' }, { label: 'JPY - Japanese yen', value: 'jpy' }, { label: 'USD - United States Dollar', value: 'usd' }, ].map(({ label, value }) => ( <SelectList.Option key={label} label={label} value={value} /> ))} </SelectList> <SelectList helperText="Product prices in your data source without an ISO currency code will default to this currency" id="selectlistHelperText" label="Default currency" onChange={() => {}} size="lg" > {[ { label: 'ARS - Argentine peso', value: 'ars' }, { label: 'AUD - Australian dollar', value: 'aud' }, { label: 'ERN - Eritrean nakfa', value: 'ern' }, { label: 'EUR - Euro', value: 'eur' }, { label: 'GBP - British pound', value: 'gbp' }, { label: 'JPY - Japanese yen', value: 'jpy' }, { label: 'USD - United States Dollar', value: 'usd' }, ].map(({ label, value }) => ( <SelectList.Option key={label} label={label} value={value} /> ))} </SelectList> </Flex> </Box> ); }
Grouping
SelectList.Group can be used to group related options. Note that disabling a group disables all of its options.
import { Box, SelectList } from 'gestalt'; export default function Example() { return ( <Box padding={8} width="100%"> <SelectList helperText="Note that the family members aren't secondary!" id="selectlistGrouping" label="Choose your favorite secondary character" onChange={() => {}} placeholder="Select a character" > <SelectList.Group disabled label="Family"> {['Bart', 'Lisa', 'Homer', 'Marge', 'Maggie'].map((name) => ( <SelectList.Option key={name} label={name} value={name} /> ))} </SelectList.Group> <SelectList.Group label="Neighbors"> {['Ned', 'Maude', 'Rod', 'Todd'].map((name) => ( <SelectList.Option key={name} label={name} value={name} /> ))} </SelectList.Group> <SelectList.Group label="Cartoons"> {['Itchy', 'Scratchy', 'Poochie'].map((name) => ( <SelectList.Option key={name} label={name} value={name} /> ))} </SelectList.Group> </SelectList> </Box> ); }
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. |
Related
Dropdown
If additional functionality is needed in the menu, such as subtext, headers or custom styling, use Dropdown.
ComboBox
If users need the ability to choose an option by entering text to filter a long list of options, use ComboBox.
RadioGroup
If users need the ability to choose between fewer than 4 options, use RadioButton.
Checkbox
If users need the ability to choose between a yes/no option, use Checkbox.