Skip to content
Cloaked Design SystemForms

Autocomplete

A controlled search field with inline, sheet, or fullscreen result presentation and explicit loading, error, empty, and disabled states.

Implementation preview
COMPLETE STORYBOOK REFERENCE

Every example. In one place.

Explore every named example, including states, compositions, and theme variants.

8 stories
SELECTED EXAMPLE

Playground

Open controls
Playground selectedOpen canvas
Example sourcepackages/design-system/src/components/forms/Autocomplete/Autocomplete.stories.tsxExport Playground

Implementation preview Local Storybook build 0.2.0-preview.1. Source specification status does not approve this runtime.

Stories + source JSON ↗

Local specification source status: preview. Implementation preview pending sign-off.

A controlled search field with inline, sheet, or fullscreen result presentation and explicit loading, error, empty, and disabled states.

Design-owned component contract ↗Version 0.2.0-preview.1 · Implementation preview pending sign-off
Implementation API 1 entry point · source-derived preview

Read the actual callable API and preserve its composition constraints. Each union branch is a complete alternative; props marked forbidden cannot be supplied.

import { Autocomplete } from '@cloakedinc/design-system';
AutocompleteAutocompleteProps

packages/design-system/src/components/forms/Autocomplete/Autocomplete.tsx:80

PropTypePresenceNotes
querystringRequiredText shown in the search field. Display only: `items` is never filtered by it.
onQueryChange(query: string) => voidRequiredCalled with the new text on each keystroke, and with `''` when the clear action fires.
itemsAutocompleteItem[]RequiredResults to render, already filtered and ordered by the app.
onSelect(item: AutocompleteItem) => voidRequiredCalled with the tapped item. Disabled items never reach it.
loadingboolean | undefinedOptionalReplaces the list with a spinner and sets `aria-busy`. Wins over `error` and `items`.
errorReact.ReactNodeOptionalError copy shown instead of results.
emptyStateReact.ReactNodeOptionalEmpty state shown when there are no results.Source default: 'No results found.'
displayModeAutocompleteDisplayMode | undefinedOptionalResult presentation mode. Defaults to `inline`.Source default: 'inline'
placeholderstring | undefinedOptionalPlaceholder in the search field. Defaults to `Search`.Source default: 'Search'
sizeAutocompleteSizeRequiredSearch field and result row size.
surfaceimport("@cloakedinc/design-system").InputSurface | undefinedOptionalSearch field background treatment. Defaults to `default`; use `raised` inside a raised form.Source default: 'default'
enterBehaviorInputEnterBehavior | undefinedOptionalReturn-key behavior for the search field. Left unset, `SearchField`'s `callback` applies.
enterKeyHintInputEnterKeyHint | undefinedOptionalNative on-screen keyboard return key hint for the search field.
ariaLabelstringRequiredAccessible label for the search field.
disabledboolean | undefinedOptionalPrevents query and selection interaction.
hapticHapticFeedback | undefinedOptionalHaptic feedback for result selection. Defaults to `true` (`selection`).Source default: true
classNamestring | undefinedOptional
styleReact.CSSProperties | undefinedOptional
testIdstring | undefinedOptionalOptional test selector. Result rows derive `${testId}-${item.value}`.

Only explicit destructured parameter initializers are extracted. Other runtime defaults remain in implementation source.

Overview

A controlled type-ahead field: a search input over a role="listbox" of results. You own the query state, debouncing, and fetching, and feed it items; it renders the loading, error, and emptyState for you.

When to use

Reach for Autocomplete when the option set is too long or too dynamic to show at once and the user needs to type to narrow it — broker search, address lookup, anything backed by a query. It is presentation only: fetching and filtering stay in the app.

  • Short, fixed list of a handful of options? Use Select — no typing needed.
  • A list of one-off commands rather than values to filter? That's a Menu (selectionMode="none").

error and emptyState are distinct: error means the fetch failed, emptyState means it succeeded with no matches. In-app it powers the address lookup in the data-removal profile (AddressesField.tsx), where it also joins keyboard next-field navigation.

Component specification

$schema../../../specs/component-spec.schema.json
Parts
Id
root
Label
Root
Description
Stacks the search field and result surface at the selected density.
Id
search-field
Label
Search field
Description
Owns the query, search semantics, loading indicator, clear action, and the surface treatment.
Id
result-surface
Label
Result surface
Description
Provides the labelled listbox and selected display mode.
Id
option
Label
Option
Description
Pressable result row with optional leading, description, and trailing content.
Id
feedback
Label
Feedback
Description
Replaces options with loading, error, or empty-state content.
Allowed Design Choices
Variants
Base
Label
Base
Description
One controlled search-and-pick pattern configured through mode and size axes.
Sizes
Sm
Label
Small
Md
Label
Medium
Modes
Inline
Label
Inline
Description
Keeps a bounded result list directly below the search field.
Sheet
Label
Sheet
Description
Uses a taller result surface with top-only rounding for sheet composition.
Fullscreen
Label
Fullscreen
Description
Uses an unrounded, minimum-height result surface for a full-screen composition.
Variants
Id
base
Label
Base
Description
Controlled search and listbox composition with mode, size, and async feedback kept orthogonal.
Platforms
  • ios
  • android
  • web
Sizes
Id
sm
Label
Small
Description
Compact search shell, 4-unit stack gap, and tighter result-row padding.
Id
md
Label
Medium
Description
Standard search shell, 8-unit stack gap, and roomier result rows.
Measurements
Id
small-stack-gap
Label
Small search-to-results gap
Kind
exact
Token
--cds-space-4
Value
4
Unit
px
Applies To
  • root
  • sm
Id
medium-stack-gap
Label
Medium search-to-results gap
Kind
exact
Token
--cds-space-8
Value
8
Unit
px
Applies To
  • root
  • md
Id
medium-option-horizontal-padding
Label
Medium option horizontal padding
Kind
exact
Token
--cds-space-16
Value
16
Unit
px
Applies To
  • option
  • md
Layout
Alignment
The search field and result surface fill the root width; option visuals align to the row start.
Flow
Search field precedes one listbox whose contents are options or a single feedback state.
Notes
  • Keep data fetching and debouncing outside the component.
  • Leading and trailing option content never consume the flexible copy column.
Typography And Color
Typography
Label
Option label
Description
Medium rows use body text; compact rows use body-small text.
Token
--cds-type-body-size
Colors
Label
Result surface
Description
Uses the raised semantic surface.
Token
--cds-bg-surface
Label
Primary copy
Description
Uses primary text emphasis for option labels.
Token
--cds-text-primary
Label
Secondary copy
Description
Uses secondary emphasis for descriptions and neutral feedback.
Token
--cds-text-secondary
Label
Error copy
Description
Uses the semantic danger text role.
Token
--cds-status-danger-solid
States
Id
results
Label
Results
Description
Shows enabled and disabled options for the current query.
Id
loading
Label
Loading
Description
Marks the listbox busy and replaces options with a labelled spinner.
Id
empty
Label
Empty
Description
Shows calm no-results copy after a successful query with no matches.
Id
error
Label
Error
Description
Shows failure copy instead of empty-state copy or stale results.
Id
disabled
Label
Disabled
Description
Blocks query editing and every option press.
Behavior
Label
Controlled query
Description
Request each query update while the parent owns filtering, fetching, and the rendered query.
Label
Selection
Description
Emit the complete selected item exactly once and ignore disabled options.
Label
Presentation modes
Description
Change only result-surface composition; mode does not alter search or selection semantics.
Label
Surface treatment
Description
The search field forwards a surface treatment (default or raised). Use raised inside a raised form so the field reads as an input rather than blending into the container.
Accessibility
Label
Search name
Description
Require a stable accessible name for the search field.
Label
Result relationship
Description
Connect the search field to the labelled listbox and expose busy state during loading.
Label
Options
Description
Expose each result as an option and preserve native disabled behavior.
Content Adaptation
Label
Long result copy
Description
Allow labels and descriptions to wrap within the flexible copy column.
Label
Distinct feedback
Description
Use empty copy only for successful zero-result queries and error copy only for failures.
Motion Haptics
Motion
Label
Stable replacement
Description
Replace result and feedback content without moving the search field.
Haptics
Label
Selection feedback
Description
Request the selection haptic after an enabled option is chosen.
Platform Differences
Platforms
  • ios
  • android
Description
Sheet and fullscreen modes should use the host platform presentation container while web applies the documented result-surface geometry in place.
Rationale
The interaction contract is shared, but native containers provide expected focus, keyboard, and dismissal behavior.
Implementation preview

This design-owned implementation is ready to try and review. It does not establish product approval. Imported specifications retain their original review status.

Inspect version 0.2.0-preview.1