Skip to content
Highlight

V2 componentsUpdated Oct 14, 2026

Combobox

Type-to-filter selection over a list, single or multiple. Base UI handles filtering and keyboard navigation; the parts here add the Input styling, chips, and the popup chrome.

Source: packages/ui/src/components/combobox

tsx
import { Combobox } from '@highlight/ui'

Change the props; the preview and the snippet update together.

Props
Multiple
tsx
const PEOPLE = ['Lin Chen', 'Vaun Blu', 'Josh Lipson']const [value, setValue] = useState(null) <Combobox items={PEOPLE} value={value} onValueChange={setValue}>  <Combobox.Input placeholder="Assign to…" />  <Combobox.Content>    <Combobox.Empty>No one matches.</Combobox.Empty>    <Combobox.List>      {(item) => <Combobox.Item value={item}>{item}</Combobox.Item>}    </Combobox.List>  </Combobox.Content></Combobox>
tsx
import { useState } from 'react'import { Combobox } from '@highlight/ui' const PEOPLE = ['Lin Chen', 'Vaun Blu', 'Josh Lipson', 'Andrew Lytvynov', 'Sam Quezada', 'Kelsey Chen'] export default function ComboboxSingle() {  const [value, setValue] = useState<string | null>(null)  const [inputValue, setInputValue] = useState('')   return (    <Combobox      items={PEOPLE}      value={value}      onValueChange={(next) => setValue(next as string | null)}      inputValue={inputValue}      onInputValueChange={setInputValue}    >      <Combobox.Input placeholder="Assign to…" />      <Combobox.Content>        <Combobox.Empty>No one matches.</Combobox.Empty>        <Combobox.List>          {(item: string) => (            <Combobox.Item key={item} value={item}>              {item}            </Combobox.Item>          )}        </Combobox.List>      </Combobox.Content>    </Combobox>  )}
tsx
import { useState } from 'react'import { Combobox } from '@highlight/ui' const PROJECTS = ['Design foundations', 'Meeting recap v2', 'Onboarding', 'Windows parity'] export default function ComboboxClearable() {  const [value, setValue] = useState<string | null>('Design foundations')  const [inputValue, setInputValue] = useState('')   return (    <Combobox      items={PROJECTS}      value={value}      onValueChange={(next) => setValue(next as string | null)}      inputValue={inputValue}      onInputValueChange={setInputValue}    >      <div className="relative">        <Combobox.Input placeholder="Project…" className="pr-16" />        {value ? (          <div className="absolute right-8 top-1/2 -translate-y-1/2">            <Combobox.Clear />          </div>        ) : null}        <div className="absolute right-2 top-1/2 -translate-y-1/2">          <Combobox.Trigger />        </div>      </div>      <Combobox.Content>        <Combobox.Empty>No projects found.</Combobox.Empty>        <Combobox.List>          {(item: string) => (            <Combobox.Item key={item} value={item}>              {item}            </Combobox.Item>          )}        </Combobox.List>      </Combobox.Content>    </Combobox>  )}

Anchor the popup to the chips container so it stays aligned as chips wrap.

tsx
import { useRef, useState } from 'react'import { Combobox } from '@highlight/ui' const EMAILS = [  'lin@highlight.ing',  'vaun@highlight.ing',  'josh@highlight.ing',  'sam@highlight.ing',  'kelsey@highlight.ing',] export default function ComboboxMultiple() {  const [value, setValue] = useState<Array<string>>(['lin@highlight.ing'])  const anchorRef = useRef<HTMLDivElement>(null)   return (    <Combobox      items={EMAILS}      multiple      value={value}      onValueChange={(next) => setValue(next as Array<string>)}      className="w-96"    >      <Combobox.Chips ref={anchorRef}>        <Combobox.Value>          {(selected: Array<string>) => (            <>              {selected.map((email) => (                <Combobox.Chip key={email}>                  {email}                  <Combobox.ChipRemove />                </Combobox.Chip>              ))}              <Combobox.Input                variant="multiple"                placeholder={selected.length ? '' : 'Invite people…'}                className="min-w-32"              />            </>          )}        </Combobox.Value>      </Combobox.Chips>      <Combobox.Content anchor={anchorRef}>        <Combobox.Empty>No matches.</Combobox.Empty>        <Combobox.List>          {(item: string) => (            <Combobox.Item key={item} value={item}>              {item}            </Combobox.Item>          )}        </Combobox.List>      </Combobox.Content>    </Combobox>  )}

The root, then any compound sub-components. Every part accepts className and forwards the rest of its props to the element or Base UI part beneath it.

Combobox
Base UI Combobox.Root. Owns the value, the query and open state; renders nothing itself.
Combobox.Input
variant: 'single' | 'multiple'. Single matches Input; multiple is borderless inside Chips.
Combobox.Content
Portal + Positioner + Popup. anchor for a custom anchor element.
Combobox.List / Item / Empty
List takes a render function per item.
Combobox.Chips / Chip / ChipRemove / Value
Multi-select display.
Combobox.Trigger / Clear
Open and clear buttons.
Combobox.Group / GroupLabel / Collection / ItemIndicator / Icon
Base UI passthroughs.