EXEPERTAI LAB

Research alpha

Time Machine
EXEPERTAI LAB
GALLERY / COLLECTION
← Browse Astryx gallery
Typeahead·component·@astryxdesign/core

Typeahead

Styled typeahead with label, description, validation, and all field features. Wraps BaseTypeahead with Field for the primary use case.

Open in Playground @astryxdesign/core/Typeahead

Showcases and examples

5 documented examples

Typeahead

Typeahead API entry

Preview loads on approachPreview loads on approach
Exact source · typeahead-showcase
// Copyright (c) Meta Platforms, Inc. and affiliates.

'use client';

import {useState} from 'react';
import {Typeahead} from '@astryxdesign/core/Typeahead';
import type {SearchableItem, SearchSource} from '@astryxdesign/core/Typeahead';

const fruits: SearchableItem[] = [
  {id: '1', label: 'Apple'},
  {id: '2', label: 'Banana'},
  {id: '3', label: 'Cherry'},
  {id: '4', label: 'Date'},
  {id: '5', label: 'Elderberry'},
  {id: '6', label: 'Fig'},
  {id: '7', label: 'Grape'},
  {id: '8', label: 'Honeydew'},
];

const fruitSource: SearchSource = {
  search: (query: string) =>
    fruits.filter(f => f.label.toLowerCase().includes(query.toLowerCase())),
  bootstrap: () => fruits.slice(0, 5),
};

export default function TypeaheadShowcase() {
  const [value, setValue] = useState<SearchableItem | null>(null);
  return (
    <div style={{width: 320}}>
      <Typeahead
        label="Fruit"
        placeholder="Search fruits..."
        searchSource={fruitSource}
        value={value}
        onChange={setValue}
      />
    </div>
  );
}

Usage

A searchable input for selecting a single item from a large or dynamic dataset. Results appear as the user types, with support for async data sources, debounced search, and custom item rendering. Use it when the option list is too large for a Selector dropdown.

  • Provide descriptive placeholder text that hints at what users can search for.
  • Show suggestions on focus when users benefit from seeing popular or recent options before typing.
  • Add a search delay for remote data sources to avoid excessive network requests.
  • Use inside InputGroup when the typeahead needs a single-line prefix or suffix addon.
  • Use for short, static option lists; use Selector for better discoverability.
  • Use for multi-selection; use Tokenizer instead.
  • Place multiple Typeaheads adjacent to each other without clear labels differentiating them.
  • Wrap a disabled Typeahead in Tooltip to explain why it is disabled; disabled triggers swallow the hover events the wrapper needs. Use the disabledMessage prop instead.

Typed props

PropType and behavior
labelstring · required
Accessible label for the input.
searchSourceSearchSource<T> · required
Data source providing search and bootstrap methods for populating the dropdown.
valueT | null · required
Currently selected item, or null if nothing is selected.
onChange(item: T | null) => void · required
Called when the selection changes.
placeholderstring
Input placeholder text.
hasEntriesOnFocusboolean · default false
Show bootstrap results on focus before typing.
hasClearboolean · default true
Show clear button to deselect the current value.
isDisabledboolean · default false
Disables the input.
disabledMessagestring
Explains why the input is disabled. With isDisabled, shows a tooltip on hover/keyboard focus and keeps the field focusable via aria-disabled (activation stays blocked). Use this instead of wrapping a disabled Typeahead in Tooltip. Disabled controls swallow the hover events an external Tooltip needs.
maxMenuItemsnumber · default 10
Maximum number of dropdown items to display.
minQueryLengthnumber · default 1
Minimum query length before the search source is queried. Below it no search runs and the menu stays closed.
status{type: 'warning' | 'error' | 'success', message?: string}
Validation status object with type and message for error/warning/success states.
statusVariant'attached' | 'detached' · default 'attached'
How the status message is placed relative to the input. attached overlaps directly below the input (bordered treatment); detached floats below as a separate element with spacing.
renderItem(item: T) => ReactNode
Custom render function for dropdown items. Default renders TypeaheadItem.
isLabelHiddenboolean · default false
Visually hides the label while keeping it accessible.
descriptionstring
Helper text displayed below the label.
isRequiredboolean · default false
Marks the field as required.
isOptionalboolean · default false
Shows an optional indicator on the label.
labelTooltipstring
Tooltip text shown on the label.
emptySearchResultsTextstring · default 'No results found'
Text shown when search returns no results.
hasAutoFocusboolean · default false
Auto-focus the input on mount.
size'sm' | 'md' | 'lg' · default 'md'
Input and token size.
debounceMsnumber · default 150
Debounce delay in ms before triggering search. Set to 0 for synchronous sources.
onChangeQuery(query: string) => void
Callback fired when the search query text changes.
onOpenChange(isOpen: boolean) => void
Callback when the dropdown opens or closes.
widthSizeValue
Width of the field (number = pixels, string used as-is, e.g. "100%"). Sizes the whole field (label, control, and status) so they stay aligned.
startIconIconType | ReactNode
SVG icon component displayed at the start of the input.
xstyleStyleXStyles
StyleX styles for layout customization (margins, positioning, sizing). Must be a stylex.create() value: not an inline style object like style={{}}.

Anatomy

Field · optional

Standalone Field shell that provides the label and optional supporting content; omitted inside InputGroup.

Input surface · required

Painted control surface containing the editable input or the selected token.

Icon-rendered start icon · optional

Optional leading semantic icon or icon component rendered through Icon.

Caller-rendered start content · optional

Optional arbitrary React content rendered directly at the start of the input surface.

Selected token · optional

Token that presents the selected item while the control is not in edit mode.

Spinner · optional

Loading indicator shown at the end of the input surface while a search is in flight.

Clear button · optional

Shared clear action that removes the selected item when hasClear is enabled.

Dropdown · optional

Anchored listbox surface containing the current search results.

Empty state · optional

Message shown after a completed search returns no results.

Result row · optional

Stable option wrapper that owns highlight, selection, pointer, and keyboard behavior.

Default item content · optional

Standard TypeaheadItem label and supporting content rendered inside a result row when renderItem and item.element are absent.

Caller-rendered item content · optional

Caller-owned result content supplied through renderItem or item.element inside the stable result row.

Result group heading · optional

Visible heading for a labeled group of result rows.

Selected result state · optional

Selected styling and trailing check presented on the current result row.

Theming

Targets

astryx-typeahead

Visual props: status, size

astryx-typeahead-dropdown
astryx-typeahead-empty-state
astryx-typeahead-item