🚀 Big News: Socket Acquires Coana to Bring Reachability Analysis to Every Appsec Team.Learn more
Socket
Sign inDemoInstall
Socket

@telegraph/combobox

Package Overview
Dependencies
Maintainers
2
Versions
77
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@telegraph/combobox

A styled menu, triggered by a Select, that combines an Input and Single- or Multi-select.

0.0.81
latest
Source
npm
Version published
Maintainers
2
Created
Source

Telegraph by Knock

npm version

@telegraph/combobox

A styled menu, triggered by a Select, that combines an Input and Single- or Multi-select.

Installation Instructions

npm install @telegraph/combobox

Add stylesheet

@import "@telegraph/combobox"

Basic Usage

A combobox component that combines input and select functionality with a searchable dropdown menu.

<Combobox/>

import { Combobox } from "@telegraph/combobox";
import { useState } from "react";

// Single select example
const SingleSelectExample = () => {
  const [value, setValue] = useState<string>("");

  return (
    <Combobox.Root value={value} onValueChange={setValue}>
      <Combobox.Trigger placeholder="Select an option..." />
      <Combobox.Content>
        <Combobox.Search />
        <Combobox.Options>
          <Combobox.Option value="option1">Option 1</Combobox.Option>
          <Combobox.Option value="option2">Option 2</Combobox.Option>
        </Combobox.Options>
      </Combobox.Content>
    </Combobox.Root>
  );
};

// Multi select example
const MultiSelectExample = () => {
  const [values, setValues] = useState<string[]>([]);

  return (
    <Combobox.Root value={values} onValueChange={setValues}>
      <Combobox.Trigger placeholder="Select options..." />
      <Combobox.Content>
        <Combobox.Search />
        <Combobox.Options>
          <Combobox.Option value="option1">Option 1</Combobox.Option>
          <Combobox.Option value="option2">Option 2</Combobox.Option>
        </Combobox.Options>
      </Combobox.Content>
    </Combobox.Root>
  );
};

Type Examples

Single Select Types

// String values (recommended)
const [value, setValue] = useState<string>("");

Multi Select Types

// String array values (recommended)
const [values, setValues] = useState<string[]>([]);

Accessibility

The combobox implements the ARIA Combobox Pattern, providing:

  • Proper ARIA roles and attributes
  • Keyboard navigation:
    • / : Navigate options
    • Enter / Space: Select option
    • Escape: Close dropdown
    • Tab: Move focus
  • Screen reader announcements for selection changes
  • Focus management

Common Patterns

Form Integration

import { useForm } from "react-hook-form";

const MyForm = () => {
  const { register, setValue } = useForm();

  return (
    <form>
      <Combobox.Root onValueChange={(value) => setValue("field", value)}>
        {/* ... */}
      </Combobox.Root>
    </form>
  );
};

Custom Filtering

const MyCombobox = () => {
  const [searchQuery, setSearchQuery] = useState("");
  const options = useMemo(
    () =>
      allOptions.filter((opt) =>
        opt.toLowerCase().includes(searchQuery.toLowerCase()),
      ),
    [searchQuery],
  );

  return (
    <Combobox.Root>
      <Combobox.Content>
        <Combobox.Search value={searchQuery} onValueChange={setSearchQuery} />
        <Combobox.Options>
          {options.map((opt) => (
            <Combobox.Option key={opt} value={opt}>
              {opt}
            </Combobox.Option>
          ))}
        </Combobox.Options>
      </Combobox.Content>
    </Combobox.Root>
  );
};

Async Loading

const AsyncCombobox = () => {
  const [isLoading, setIsLoading] = useState(false);
  const [options, setOptions] = useState([]);

  const loadOptions = async (query) => {
    setIsLoading(true);
    const results = await fetchOptions(query);
    setOptions(results);
    setIsLoading(false);
  };

  return (
    <Combobox.Root>
      <Combobox.Content>
        <Combobox.Search onValueChange={loadOptions} />
        <Combobox.Options>
          {isLoading ? (
            <Box p="4" textAlign="center">
              Loading...
            </Box>
          ) : (
            options.map((opt) => (
              <Combobox.Option key={opt} value={opt}>
                {opt}
              </Combobox.Option>
            ))
          )}
        </Combobox.Options>
      </Combobox.Content>
    </Combobox.Root>
  );
};

Error States

const ErrorCombobox = () => {
  const [error, setError] = useState("");

  return (
    <Stack gap="1">
      <Combobox.Root errored={!!error}>{/* ... */}</Combobox.Root>
      {error && (
        <Text color="red" size="1">
          {error}
        </Text>
      )}
    </Stack>
  );
};

Component Parts

<Combobox.Root/>

The root component that manages the state and context for the combobox.

Props
NameTypeDefaultDescription
valuestring | string[] | Option | Option[]undefinedThe selected value(s)
onValueChange(value: string | string[] | Option | Option[]) => voidundefinedCallback when selection changes
layout"truncate" | "wrap""truncate"How to display multiple selections
openbooleanundefinedControlled open state
defaultOpenbooleanfalseInitial open state
erroredbooleanfalseShows error styling
placeholderstringundefinedPlaceholder text
onOpenChange(open: boolean) => voidundefinedCallback when open state changes
modalbooleantrueWhether to render in a modal
closeOnSelectbooleantrueClose menu after selection
clearablebooleanfalseShow clear button
disabledbooleanfalseDisable the combobox
legacyBehaviorbooleanfalseUse legacy object format

<Combobox.Trigger/>

The button that triggers the combobox dropdown.

For advanced customization of the trigger's internal components (indicator, clear button, text display, etc.), see the Trigger Primitives section below.

Props
NameTypeDefaultDescription
size"1" | "2" | "3""2"Size of the trigger
placeholderstringundefinedPlaceholder text
childrenReactNodeundefinedCustom trigger content

<Combobox.Content/>

The dropdown menu content container.

Props

Accepts all props from TelegraphMenu.Content

<Combobox.Options/>

Container for the option items.

Props

Accepts all props from Stack component

<Combobox.Option/>

Individual selectable option item.

Props
NameTypeDefaultDescription
valuestringrequiredOption value
labelstringundefinedDisplay label
selectedbooleanundefinedForce selected state

<Combobox.Search/>

Search input field for filtering options.

Props
NameTypeDefaultDescription
labelstring"Search"Accessibility label
placeholderstring"Search"Input placeholder

<Combobox.Empty/>

Empty state component shown when no options match search.

Props
NameTypeDefaultDescription
iconIconProps | nullSearchIconEmpty state icon
messagestring | null"No results found"Empty state message

<Combobox.Create/>

Option to create new values when none match search.

Props
NameTypeDefaultDescription
leadingTextstring"Create"Text before search value
valuesstring[] | Option[]undefinedExisting values
onCreate(value: string | Option) => voidundefinedCreation callback

Primitives

The combobox includes several primitive components for advanced customization. These primitives allow you to build custom trigger layouts and behaviors while maintaining the combobox's core functionality.

Trigger Primitives

<Combobox.Primitives.TriggerIndicator/>

The dropdown chevron icon that rotates based on the combobox's open state.

Props
NameTypeDefaultDescription
iconIconPropsChevronDownThe icon to display
aria-hiddenbooleantrueWhether to hide from screen readers
<Combobox.Primitives.TriggerIndicator icon={CustomIcon} aria-hidden={false} />
<Combobox.Primitives.TriggerClear/>

A button to clear the current selection(s). Only shown when clearable is true and there are selections.

Props
NameTypeDefaultDescription
tooltipPropsTgphComponentPropsundefinedProps for the tooltip

Accepts all props from Button

<Combobox.Primitives.TriggerClear tooltipProps={{ delay: 300 }} />
<Combobox.Primitives.TriggerText/>

Displays the selected value's text or label. Used in single-select mode.

Props

Accepts all props from Button.Text

<Combobox.Primitives.TriggerText color="blue" weight="medium" />
<Combobox.Primitives.TriggerPlaceholder/>

Shows placeholder text when no value is selected.

Props

Accepts all props from Button.Text

<Combobox.Primitives.TriggerPlaceholder color="gray-8" />
<Combobox.Primitives.TriggerTagsContainer/>

Container for selected value tags in multi-select mode. Handles tag layout and truncation.

Props

Accepts all props from Stack

<Combobox.Primitives.TriggerTagsContainer gap="2" wrap="wrap" />
<Combobox.Primitives.TriggerTag/>

A collection of components for building custom tags in multi-select mode:

<Combobox.Primitives.TriggerTag.Root/>

The base container for a tag.

Props:

NameTypeDefaultDescription
valuestringrequiredThe value this tag represents
<Combobox.Primitives.TriggerTag.Text/>

The text content of a tag.

Props: Accepts all props from Text

<Combobox.Primitives.TriggerTag.Button/>

The remove button for a tag.

Props: Accepts all props from Button

<Combobox.Primitives.TriggerTag.Default/>

A pre-composed tag with text and remove button.

Props:

NameTypeDefaultDescription
valuestringrequiredThe value this tag represents

Example of a custom tag layout:

<Combobox.Primitives.TriggerTag.Root value="example">
  <Icon icon={CustomIcon} />
  <Combobox.Primitives.TriggerTag.Text>
    Custom Tag
  </Combobox.Primitives.TriggerTag.Text>
  <Combobox.Primitives.TriggerTag.Button
    icon={{ icon: XIcon, alt: "Remove" }}
  />
</Combobox.Primitives.TriggerTag.Root>

Example of using the default tag:

<Combobox.Primitives.TriggerTag.Default value="example" />

Complete example using primitives for a custom trigger layout:

<Combobox.Root>
  <Combobox.Trigger>
    <Stack direction="row" justify="space-between" align="center" w="full">
      {/* Left side: Text or Tags */}
      <Box flex="1" overflow="hidden">
        <Combobox.Primitives.TriggerTagsContainer>
          <Combobox.Primitives.TriggerTag.Default value="tag1" />
          <Combobox.Primitives.TriggerTag.Default value="tag2" />
        </Combobox.Primitives.TriggerTagsContainer>
      </Box>

      {/* Right side: Clear and Indicator */}
      <Stack direction="row" gap="1" align="center">
        <Combobox.Primitives.TriggerClear />
        <Box borderLeft="1" h="4" />
        <Combobox.Primitives.TriggerIndicator />
      </Stack>
    </Stack>
  </Combobox.Trigger>
  <Combobox.Content>{/* ... */}</Combobox.Content>
</Combobox.Root>

Legacy Behavior (⚠️ Deprecated)

Warning: Legacy behavior is deprecated and will be removed in a future version. New implementations should use string values instead of objects.

The legacyBehavior prop changes how values are handled:

  • When false (default, recommended): Values are simple strings
  • When true (deprecated): Values are objects with { value: string; label?: string }

Legacy Single Select Types

// ⚠️ Deprecated - Don't use in new code
const [value, setValue] = useState<{ value: string; label?: string }>()

<Combobox.Root
  value={value}
  onValueChange={setValue}
  legacyBehavior={true}
>

Legacy Multi Select Types

// ⚠️ Deprecated - Don't use in new code
const [values, setValues] = useState<Array<{ value: string; label?: string }>>([])

<Combobox.Root
  value={values}
  onValueChange={setValues}
  legacyBehavior={true}
>

This object-based value pattern is only maintained for backwards compatibility and should not be used in new code. It will be removed in a future major version.

FAQs

Package last updated on 21 Apr 2025

Did you know?

Socket

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Install

Related posts