Summit
ComponentsSelection

Select

A Select allows users to choose one option from a list that opens from a button.

When to Use

  • to choose one option from a short, fixed list, such as payment terms or a currency
  • when an option has more than text, like a currency code next to its name
  • as a control joined to an Input in a Button Group, for example a currency before an amount

When Not to Use

SelectNative SelectCombobox
PurposeOne option from a short listOne option from the browser’s listAn option from a list long enough to search
ListA popup below the triggerThe browser’s ownA popup below the input
TypingMoves focus to the next matchHandled by the browserFilters the list
Option ContentText, icons, and markupTextText, icons, and markup
Several Valuesmultiple, with the labels on one lineNomultiple, with a chip for each value
Clear ButtonNoNoshowClear
Sizessm, defaultsm, default32px only
ControlA button with role="combobox"A select elementAn input with role="combobox"

Anatomy

ElementUsage
ValueRequired
TriggerRequired
CaretAlways shown
Group labelOptional
PopupRequired
ItemRequired
SeparatorOptional

SelectTrigger adds the caret, SelectItem adds a check at the end of the selected option, and SelectContent renders the portal and the popup, so you don’t need to add them. The popup’s padding is set on SelectGroup, so place every item in a group, even when the group has no label.

Sizes

Set size on SelectTrigger.

SizeHeightPlacement
sm28pxA dense toolbar with no Input
default32pxEverywhere else

An Input is 32px tall and has no other size, so use default for a Select next to one. See Sizing for the rule on controls in a row.

DoUse the default size for a Select next to an Input so that both are 32px tall.
Don’tWhen an sm Select is next to an Input, it is 28px tall and the Input is 32px tall, so their top and bottom edges don’t line up.

Behavior

By default, a Select is modal while its list is open: Base UI locks the page’s scroll and prevents clicks from reaching the page. If you want the page to stay interactive, set modal={false} on Select.

Position

By default, the list opens below the trigger and is aligned with its start edge. If the list doesn’t fit there, Base UI moves it to another side. The list is as wide as the trigger, with a minimum width of 144px. To change its position, use side, sideOffset, align, and alignOffset on SelectContent.

If alignItemWithTrigger is set, the list opens over the trigger, with the selected option on top of the value. This is the default in Base UI, and it is off in Summit.

Overflow

By default, the trigger is as wide as its value. If you set a width and the value is longer than the trigger, the value is truncated to one line. If the list is taller than the space available next to the trigger, it scrolls inside the popup. SelectScrollUpButton and SelectScrollDownButton are rendered only when alignItemWithTrigger is set.

Content

StringRuleExampleCounterexample
PlaceholderSay what to choose“Choose payment terms”“Select…”
OptionSentence case, with no end period“Due on receipt”“Due On Receipt”

Accessibility

Base UI’s Select sets the roles, moves focus into the list, and returns it to the trigger. You provide the name.

Keyboard

KeyResult
TabMoves focus to the trigger. If the list is open, closes it without choosing and moves focus to the next control.
Enter, Space, or ArrowDown on the triggerOpens the list. Focus moves to the selected option, or to the first option if no value is set.
ArrowUp on the triggerOpens the list. Focus moves to the selected option, or to the last option if no value is set.
A letter on the triggerSelects the next option that starts with it. The list stays closed.
ArrowDown, ArrowUpMoves focus to the next or the previous option, including disabled options. Focus stops at the first and the last option.
Home, EndMoves focus to the first or the last option
A letter in the listMoves focus to the next option that starts with it
Enter or Space on an optionSelects it and closes the list. Focus returns to the trigger. A disabled option does nothing.
EscapeCloses the list without choosing. Focus returns to the trigger.

Requirements

A Select needs a name so that screen readers can announce it, as WCAG 2.2 SC 4.1.2 Name, Role, Value requires. To provide one, place it in a Field with a FieldLabel, connect a Label to the id of SelectTrigger with htmlFor, or set aria-label on SelectTrigger. A placeholder can’t be used as the name because the trigger’s text is its value.

Installation

npx shadcn@latest add @summit/select

Usage

To show the label of the selected option in SelectValue, pass the options to items on Select. If items isn’t set, SelectValue shows the raw value.

import { Select, SelectContent, SelectGroup, SelectItem, SelectTrigger, SelectValue } from '@/components/ui/select';

const terms = [
    { value: 'net-15', label: 'Net 15' },
    { value: 'net-30', label: 'Net 30' },
];

<Select items={terms}>
    <SelectTrigger aria-label="Payment terms" className="w-48">
        <SelectValue placeholder="Choose payment terms" />
    </SelectTrigger>
    <SelectContent>
        <SelectGroup>
            {terms.map(({ value, label }) => (
                <SelectItem key={value} value={value}>
                    {label}
                </SelectItem>
            ))}
        </SelectGroup>
    </SelectContent>
</Select>;

With Groups

To name a SelectGroup, add a SelectLabel to it. To divide two groups, place a SelectSeparator between them.

With Groups
<SelectContent>
    <SelectGroup>
        <SelectLabel>Americas</SelectLabel>
        <SelectItem value="USD">US dollar</SelectItem>
        <SelectItem value="CAD">Canadian dollar</SelectItem>
    </SelectGroup>
    <SelectSeparator />
    <SelectGroup>
        <SelectLabel>Europe</SelectLabel>
        <SelectItem value="EUR">Euro</SelectItem>
        <SelectItem value="CHF" disabled>
            Swiss franc
        </SelectItem>
    </SelectGroup>
</SelectContent>

In a Field

In a Field, the FieldLabel names the Select, and a click on the label opens the list.

In a Field
import { Field, FieldDescription, FieldLabel } from '@/components/ui/field';

<Field>
    <FieldLabel>Payment terms</FieldLabel>
    <Select items={terms}>
        <SelectTrigger>
            <SelectValue placeholder="Choose payment terms" />
        </SelectTrigger>
    </Select>
    <FieldDescription>Applied to new invoices for this client.</FieldDescription>
</Field>;

API Reference

The parts accept the props of their matching parts in Base UI’s Select, where SelectContent is Select.Popup and SelectLabel is Select.GroupLabel. See the Base UI Select documentation for items, value, onValueChange, name, multiple, modal, and OffsetFunction.

SelectTrigger

PropTypeDefaultDescription
size'sm' | 'default''default'The height

SelectContent

PropTypeDefaultDescription
side'top' | 'bottom' | 'left' | 'right' | 'inline-start' | 'inline-end''bottom'The side of the trigger the list opens on
sideOffsetnumber | OffsetFunction4The gap between the trigger and the list, in pixels
align'start' | 'center' | 'end''start'The edge of the trigger the list is aligned with
alignOffsetnumber | OffsetFunction0A shift along that edge, in pixels
alignItemWithTriggerbooleanfalseOpens the list over the trigger, with the selected option on top of it

On this page