Skip to content
Highlight

ComponentsUpdated Sep 9, 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.

Import

Source: packages/ui/src/components/combobox

tsx
import { Combobox } from '@highlight/ui'
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>
  )
}

Multiple with chips

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>
  )
}

Parts

Compound sub-components. Every part accepts className and forwards the rest of its props to Base UI.

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.