← Back to all how-tos

Sidebar controls in depth

Use the Autocomplete control

Use the Autocomplete control when editors need search-based selection from async results instead of a short fixed list.

Estimated time: 8 minRaw Markdown

In this how-to, you'll learn how to use SideEditPropType.Autocomplete.

This control is a good fit when the list of options is too large for a normal select, or when options must come from an async search.

Docs reference: Sidebar controls

When Autocomplete is the right choice

Use Autocomplete when editors need to search for:

  • authors
  • products
  • cities
  • stocks
  • entities coming from an external API

If the option list is small and known in advance, Select is usually simpler.

Example

This example lets editors search and choose an author:

import { Text, types } from 'react-bricks/rsc'
 
type AuthorOption = {
  id: string
  name: string
  role: string
}
 
interface FeaturedAuthorProps {
  title: types.TextValue
  author?: AuthorOption
}
 
const FeaturedAuthor: types.Brick<FeaturedAuthorProps> = ({ title, author }) => {
  return (
    <section>
      <Text
        propName="title"
        value={title}
        placeholder="Section title..."
        renderBlock={({ children }) => <h2>{children}</h2>}
      />
 
      {author ? (
        <p>
          Featured author: {author.name} ({author.role})
        </p>
      ) : (
        <p>No author selected yet.</p>
      )}
    </section>
  )
}
 
FeaturedAuthor.schema = {
  name: 'featured-author',
  label: 'Featured Author',
  getDefaultProps: () => ({
    title: 'Meet the author',
  }),
  sideEditProps: [
    {
      name: 'author',
      label: 'Author',
      type: types.SideEditPropType.Autocomplete,
      autocompleteOptions: {
        getOptions: async (input) => {
          if (!input || input.length < 2) return []
 
          const response = await fetch(`/api/authors?search=${input}`)
          return response.json()
        },
        getKey: (option: AuthorOption) => option.id,
        getLabel: (option: AuthorOption) => option.name,
        renderOption: ({ option }: { option: AuthorOption }) => (
          <div>
            <strong>{option.name}</strong>
            <div>{option.role}</div>
          </div>
        ),
        placeholder: 'Search an author...',
        debounceTime: 300,
        getNoOptionsMessage: (input) =>
          input
            ? `No authors found for "${input}"`
            : 'Start typing to search authors',
      },
    },
  ],
}

What each option function does

autocompleteOptions is made of small, focused pieces:

  • getOptions: fetches the matching results
  • getKey: returns a stable unique key for each result
  • getLabel: returns the plain label shown for the selected value
  • renderOption: optionally customizes how each dropdown result is rendered

You do not have to use renderOption, but it is useful when each result needs a richer preview than a single text label.

A few practical tips

  • Debounce API calls with debounceTime so the search feels responsive without being too chatty.
  • Keep the selected option shape small and serializable.
  • Return early from getOptions when the input is too short.

That last point is especially helpful when your API is large or expensive:

getOptions: async (input) => {
  if (input.length < 3) return []
  // fetch results only after 3 characters
}

Autocomplete vs Select

Choose Autocomplete when:

  • the list is large
  • search matters
  • results come from an API

Choose Select when:

  • the list is short
  • the values are known in advance
  • editors should see all options at once

Related reading