Skip to content

Combobox

A combobox looks like a field and opens a list you can search. Use it for a country, a person, a time zone, or any list too long to read at a glance.

When to use it

Use a combobox for a long list that people search by name, such as countries, people or time zones, or when an option needs a flag, a photo or a second line to be told apart. For a short list of plain options, a select is quicker.

A combobox chooses from its list. It does not accept a value that is not there.

Anatomy

The field shows the chosen option with its mark, and the chevron turns over while the list is open. The list opens 8px under the field, at the field's width.

  • Bosnia and Herzegovina
  • India
  • Nepal
  • Philippines
Field
the text field's fill, 44 px, 36 px in a toolbar with a mouse
Field focus
a 2 px outline, 2 px outside the field
--brand-blue
Flag, photo or icon
20 px, 24 px or 16 px
Gap to the list
8 px
List corner radius
12 px
--radius-xl
List padding
4 px
--space-1
List shadow
the raised shadow
--glass-shadow-raised
Search row
a 16 px icon and bare text, 36 px high
Row
36 px, 44 px on touch, 10 px text inset
Row under the pointer or the arrow keys
a light fill
--glass-fill-hover
Check on the chosen row
16 px
--brand-blue

Several choices

When a question takes several answers, such as the countries a recruiter covers, each row has a checkbox and the list stays open while you choose. The field lists the choices by name. When the names do not fit, the field ends with a count, such as “and 1 more”.

  • Bosnia and Herzegovina
  • Bulgaria
  • Croatia
  • Czechia
  • India
  • Nepal
  • North Macedonia
  • Philippines
  • Serbia
  • Slovakia
  • Sri Lanka
  • Uzbekistan

Where the list opens

The list opens below the field. It opens upward when the room below is short and there is more above, and it scrolls inside itself so it stays in the window.

Opens upward when the room below is under
280 px
Tallest list
70 percent of the window
Shortest list
176 px
Distance from the window edge
8 px

Keyboard

Focus stays in the search row while the arrow keys move a highlight through the list, so typing and choosing do not get in each other's way. The pointer and the arrow keys light a row with the same fill.

Enter, Space or Down arrow
Opens the list
Typing
Narrows the list, or jumps to a letter
Up and Down arrows
Move the highlight
Home and End
First and last option
Enter
Chooses and closes, or ticks a row when several are allowed
Escape
Closes, and focus returns to the field
Tab
Closes and keeps the choice as it was

Long names

Options wrap onto a second line, so Democratic Republic of the Congo reads in full. The field shows the chosen name on one line and ends it with an ellipsis. A screen reader still hears the whole name.

  • Croatia
  • Czechia
  • Democratic Republic of the Congo
  • Denmark
  • Dominican Republic
  • Egypt

Accessibility

The field announces its label, the chosen option and that it opens a list. Options are not tab stops.

Escape closes only the list, even inside a dialog. The dialog stays open, and focus goes back to the field.

NextDate and time picker

Combobox

Chooses one or several options from a long or rich list, with a search row that narrows it.

  • Kind: component
  • Page: https://design.werklist.com/components/combobox
  • Version: 2.1.2

When to use it

  • A long list people search by name
  • Options told apart by a flag, a photo, an icon or a hint: countries, people, time zones, stages
  • Several answers from a long list

When not to use it

  • A short list of plain options: a select
  • Free text that is not in the list

Rules

  • Show the search row when the list has more than 7 options
  • Open upward when the room below is under 280 px and the room above is larger
  • Keep the list within 70 percent of the window height, and at least 176 px tall
  • Keep 8 px from the window edge

Anatomy

  • Field: the fill of the text field, 12 px padding, 8 px between its parts. It is a button with role="combobox" (--input-border)
  • Leading mark: a flag of 20 px, a photo of 24 px, or an icon of 16 px in the muted ink
  • Chevron: 16 px, 12 px from the end. It turns over in 150 ms while the list is open (--text-muted)
  • List: as wide as the field, 8 px below it, corner radius 12 px, padding 4 px. It floats above the page and rises into place in 150 ms (--glass-fill-raised)
  • List shadow: the raised shadow, with a top highlight and a fine ring in dark (--glass-shadow-raised)
  • Search row: a 16 px search icon and bare text with no fill and no ring, 10 px from the edge, 36 px high, and 44 px high with 16 px text on a touch screen (--text-muted)
  • Row: 36 px, at least 44 px on a touch screen, padding 8 px by 10 px, corner radius 8 px, 14 px on 20 px text that wraps (--text)
  • Row hint: 12 px on 16 px at the end of the row (--text-muted)
  • Check: 16 px at the end of the chosen row (--brand-blue)
  • Empty line: No match for the typed text, 14 px, at the row inset (--text-muted)

Variants

  • Single: One answer. Choosing closes the list
  • Several: Several answers. Each row has a checkbox and the list stays open. The field lists the choices by name. When the names do not fit, it ends with a count, such as “and 2 more”. The list carries aria-multiselectable

Sizes

  • md: height 44 px, padding 0 12 px, type 14 px on 20 px
  • lg: height 48 px, padding 0 12 px, type 14 px on 20 px
  • compact: height 36 px with a mouse and 44 px on a touch screen, padding 0 12 px, type 14 px on 20 px

States

  • Rest, error, disabled: As the text field, with no hover state (--input-border, --error, --text-muted)
  • Focus: The field is a button and shows focus as a button does: the fill stays, and a 2 px blue outline sits 2 px outside the field (--brand-blue)
  • Open: The chevron turns over, the list shows, and the field carries aria-expanded="true"
  • Row under the pointer or the keyboard highlight: The same fill for both (--glass-fill-hover)
  • Chosen row: A check at the end, and aria-selected="true" (--brand-blue)
  • Loading: Grey placeholder rows until the options arrive
  • No match: No match for the typed text (--text-muted)
  • No options: The field is disabled and the hint says why

Keyboard

  • Enter, Space or Down arrow on the field: Opens the list. Focus moves to the search row, or to the list when there is no search row
  • Typing: Narrows the list. Without a search row, jumps to the first option that starts with the letters
  • Up and Down arrows: Move the highlight
  • Home and End: First and last option
  • Enter: Chooses the highlighted option and closes. With several answers, ticks or clears it and keeps the list open
  • Escape: Closes this list only, so a dialog around the field stays open. Focus returns to the field
  • Tab: Closes without changing the value and moves to the next control

Accessibility

  • The field is a button with role="combobox", aria-haspopup="listbox", aria-expanded and aria-controls, named by the Field label
  • The search row is an input with role="combobox", aria-autocomplete="list", aria-controls and aria-activedescendant
  • The list has role="listbox". Options have role="option" and aria-selected, and are not tab stops
  • Escape closes only the top layer
  • Focus returns to the field however the list closes
  • The chosen name is cut short in the field only. Its accessible name stays whole
  • With reduced motion the list only fades

Content

  • Options are parallel phrases in sentence case
  • The empty line repeats the query: No match for Kenya
  • The placeholder of the search row names the list: Search countries

Tokens

  • --glass-fill-input
  • --input-border
  • --glass-fill-raised
  • --glass-blur-raised
  • --glass-shadow-raised
  • --glass-fill-hover
  • --brand-blue
  • --text
  • --text-muted
  • --radius-lg
  • --radius-xl
  • --space-1
  • --space-2
  • --layer-popover

JSON

{
  "title": "Combobox",
  "path": "/components/combobox",
  "url": "https://design.werklist.com/components/combobox",
  "text": "https://design.werklist.com/agent/components/combobox",
  "summary": "A field that opens a searchable list, for long lists and for options with flags, photos or hints.",
  "version": "2.1.2",
  "kind": "component",
  "name": "Combobox",
  "purpose": "Chooses one or several options from a long or rich list, with a search row that narrows it.",
  "use": [
    "A long list people search by name",
    "Options told apart by a flag, a photo, an icon or a hint: countries, people, time zones, stages",
    "Several answers from a long list"
  ],
  "avoid": [
    "A short list of plain options: a select",
    "Free text that is not in the list"
  ],
  "variants": [
    {
      "name": "Single",
      "use": "One answer. Choosing closes the list"
    },
    {
      "name": "Several",
      "use": "Several answers. Each row has a checkbox and the list stays open. The field lists the choices by name. When the names do not fit, it ends with a count, such as “and 2 more”. The list carries aria-multiselectable"
    }
  ],
  "anatomy": [
    {
      "part": "Field",
      "measure": "the fill of the text field, 12 px padding, 8 px between its parts. It is a button with role=\"combobox\"",
      "token": "--input-border"
    },
    {
      "part": "Leading mark",
      "measure": "a flag of 20 px, a photo of 24 px, or an icon of 16 px in the muted ink"
    },
    {
      "part": "Chevron",
      "measure": "16 px, 12 px from the end. It turns over in 150 ms while the list is open",
      "token": "--text-muted"
    },
    {
      "part": "List",
      "measure": "as wide as the field, 8 px below it, corner radius 12 px, padding 4 px. It floats above the page and rises into place in 150 ms",
      "token": "--glass-fill-raised"
    },
    {
      "part": "List shadow",
      "measure": "the raised shadow, with a top highlight and a fine ring in dark",
      "token": "--glass-shadow-raised"
    },
    {
      "part": "Search row",
      "measure": "a 16 px search icon and bare text with no fill and no ring, 10 px from the edge, 36 px high, and 44 px high with 16 px text on a touch screen",
      "token": "--text-muted"
    },
    {
      "part": "Row",
      "measure": "36 px, at least 44 px on a touch screen, padding 8 px by 10 px, corner radius 8 px, 14 px on 20 px text that wraps",
      "token": "--text"
    },
    {
      "part": "Row hint",
      "measure": "12 px on 16 px at the end of the row",
      "token": "--text-muted"
    },
    {
      "part": "Check",
      "measure": "16 px at the end of the chosen row",
      "token": "--brand-blue"
    },
    {
      "part": "Empty line",
      "measure": "No match for the typed text, 14 px, at the row inset",
      "token": "--text-muted"
    }
  ],
  "sizes": [
    {
      "name": "md",
      "height": "44 px",
      "padding": "0 12 px",
      "type": "14 px on 20 px"
    },
    {
      "name": "lg",
      "height": "48 px",
      "padding": "0 12 px",
      "type": "14 px on 20 px"
    },
    {
      "name": "compact",
      "height": "36 px with a mouse and 44 px on a touch screen",
      "padding": "0 12 px",
      "type": "14 px on 20 px"
    }
  ],
  "states": [
    {
      "name": "Rest, error, disabled",
      "change": "As the text field, with no hover state",
      "tokens": [
        "--input-border",
        "--error",
        "--text-muted"
      ]
    },
    {
      "name": "Focus",
      "change": "The field is a button and shows focus as a button does: the fill stays, and a 2 px blue outline sits 2 px outside the field",
      "tokens": [
        "--brand-blue"
      ]
    },
    {
      "name": "Open",
      "change": "The chevron turns over, the list shows, and the field carries aria-expanded=\"true\""
    },
    {
      "name": "Row under the pointer or the keyboard highlight",
      "change": "The same fill for both",
      "tokens": [
        "--glass-fill-hover"
      ]
    },
    {
      "name": "Chosen row",
      "change": "A check at the end, and aria-selected=\"true\"",
      "tokens": [
        "--brand-blue"
      ]
    },
    {
      "name": "Loading",
      "change": "Grey placeholder rows until the options arrive"
    },
    {
      "name": "No match",
      "change": "No match for the typed text",
      "tokens": [
        "--text-muted"
      ]
    },
    {
      "name": "No options",
      "change": "The field is disabled and the hint says why"
    }
  ],
  "keys": [
    {
      "key": "Enter, Space or Down arrow on the field",
      "action": "Opens the list. Focus moves to the search row, or to the list when there is no search row"
    },
    {
      "key": "Typing",
      "action": "Narrows the list. Without a search row, jumps to the first option that starts with the letters"
    },
    {
      "key": "Up and Down arrows",
      "action": "Move the highlight"
    },
    {
      "key": "Home and End",
      "action": "First and last option"
    },
    {
      "key": "Enter",
      "action": "Chooses the highlighted option and closes. With several answers, ticks or clears it and keeps the list open"
    },
    {
      "key": "Escape",
      "action": "Closes this list only, so a dialog around the field stays open. Focus returns to the field"
    },
    {
      "key": "Tab",
      "action": "Closes without changing the value and moves to the next control"
    }
  ],
  "accessibility": [
    "The field is a button with role=\"combobox\", aria-haspopup=\"listbox\", aria-expanded and aria-controls, named by the Field label",
    "The search row is an input with role=\"combobox\", aria-autocomplete=\"list\", aria-controls and aria-activedescendant",
    "The list has role=\"listbox\". Options have role=\"option\" and aria-selected, and are not tab stops",
    "Escape closes only the top layer",
    "Focus returns to the field however the list closes",
    "The chosen name is cut short in the field only. Its accessible name stays whole",
    "With reduced motion the list only fades"
  ],
  "content": [
    "Options are parallel phrases in sentence case",
    "The empty line repeats the query: No match for Kenya",
    "The placeholder of the search row names the list: Search countries"
  ],
  "tokens": [
    "--glass-fill-input",
    "--input-border",
    "--glass-fill-raised",
    "--glass-blur-raised",
    "--glass-shadow-raised",
    "--glass-fill-hover",
    "--brand-blue",
    "--text",
    "--text-muted",
    "--radius-lg",
    "--radius-xl",
    "--space-1",
    "--space-2",
    "--layer-popover"
  ],
  "rules": [
    "Show the search row when the list has more than 7 options",
    "Open upward when the room below is under 280 px and the room above is larger",
    "Keep the list within 70 percent of the window height, and at least 176 px tall",
    "Keep 8 px from the window edge"
  ]
}

Raw file: https://design.werklist.com/agent/components/combobox