StartFoundationsComponentsContent

Select

A select lets people choose one option from a short, closed list. It shows the chosen value and submits it with the form.

Stable Figma
OverviewUsageAPIAccessibility
<tk-field label="Department" helper="Shown on your profile">
  <tk-select name="department" placeholder="Select a department">
    <option>Design</option>
    <option>Engineering</option>
    <option>Finance</option>
  </tk-select>
</tk-field>

Put the select in a Field to give it a label, helper, and error. Without a Field, set aria-label. Inside a Field, set required and disabled on the Field.

Anatomy

Part What it is
tk-select the element; one Tab stop
field shows the chosen value, or the prompt, and a chevron; fills its container
chevron turns over while the menu is open; hidden when read-only
menu the option list; as wide as the field; opens below it, or above near the bottom of the screen
option one row; a check marks the chosen one
group header an optional heading over a run of options; it can't be chosen

The menu shows about five and a half rows, then scrolls; the cut-off row shows there is more. It is the same menu on touch screens; there is no system picker.

Variants

<tk-select variant="filter" filter-label="Status">
  <option>Open</option>
  <option>Closed</option>
</tk-select>
<tk-select variant="filter" filter-label="Owner">
  <option selected>Me</option>
  <option>Anyone</option>
</tk-select>
  • field (default): a form field that fills its container. Name it with a Field or aria-label.
  • filter: a compact button for a filter bar. It reads "Status" until something is chosen, then "Status: Open", and gets a tinted fill. filter-label is required: it is the visible text and the accessible name. Don't put a filter in a Field.

Sizes

<tk-select aria-label="Sort by">
  <option selected>Newest first</option>
  <option>Oldest first</option>
</tk-select>
<tk-select size="large" aria-label="Show">
  <option selected>All projects</option>
  <option>Starred projects</option>
</tk-select>
size Height Padding-inline Value text Option row
medium (default) 32px space-8 Body Small (14/20) 32px
large 36px space-10 Body Medium (16/24) 36px

Option labels are Label Medium (14/20) at both sizes. A row with a description is taller. The heights match Input and Button, so a form lines up. Long values and options are cut off with an ellipsis; they never wrap.

States

<tk-select aria-label="Region" disabled>
  <option selected>Europe</option>
</tk-select>
<tk-select aria-label="Currency" readonly>
  <option selected>Euro</option>
</tk-select>

Hover doesn't change the field. Keyboard focus colors its border and thickens it; there is no ring. The filter variant tints on hover and shows a focus ring.

  • disabled: can't be focused or opened, and isn't submitted. Prefer an active field, or readonly and a helper that says why.
  • readonly: shows the value and submits it. The field stays focusable, but the menu doesn't open and the chevron is hidden.
  • Error: set error on the Field. The message appears below and the border turns red, even while focused.
<tk-field label="Plan" required error="Select a plan to continue">
  <tk-select placeholder="Select a plan">
    <option>Free</option>
    <option>Pro</option>
  </tk-select>
</tk-field>

Options

<tk-select aria-label="Plan" placeholder="Select a plan">
  <option value="free" data-description="For trying things out">Free</option>
  <option value="pro" data-description="Adds version history">Pro</option>
  <option value="team" disabled>Team (coming soon)</option>
</tk-select>
  • Write options as <option> children. value defaults to the option's text.
  • selected on an option, or value on the select, sets the starting value. Without either, the field shows the prompt; the first option is never picked for you.
  • disabled keeps an option visible but skips it. Say why in its text.
  • data-description adds a short second line. Use it to help people choose, such as a price or a limit. Don't describe every option. Screen readers read it after the option's name.
<tk-select aria-label="Office" placeholder="Select an office">
  <option>Remote</option>
  <optgroup label="Europe">
    <option>Berlin</option>
    <option>Lisbon</option>
  </optgroup>
</tk-select>

<optgroup label="…"> groups options under a header. Keyboard navigation skips headers. Other child elements are ignored.