Advanced

Patterns for power users — dynamic options, fully controlled state, and accessibility.

Inject field options at runtime

Supply a field's option list from your app at runtime — live data like contacts, products, or locations, or options computed from what the user typed. Overrides are keyed per field and fully replace the server's options for that field.

  1. First, make sure the field exists as a runtime-injected custom field: in Edit Logic, answer Yes to the custom data fields question, add the field's name (e.g. Product Color), and pick "I will inject the values at runtime" as its type. Save so your product regenerates with the new field.
  2. Pass optionOverrides keyed by the field's name exactly as you typed it in Edit Logic — no renaming or case conversion. A field saved as pizza_type is keyed pizza_type; one saved as "pizza type" is keyed "pizza type". Whenever that field's pill becomes active, your function is called with the text the user has typed against the pill and returns the options to show.
  3. The returned list replaces the server's options for that field entirely — return every option you want visible, and an empty array when nothing matches.
optionOverrides.tsx
// "Product Color" added as a runtime-injected custom field in Edit Logic.
// The key must match the field name exactly as typed there.
const colors = useProductColors(); // your live data
<AIAutocomplete
optionOverrides={{
"Product Color": (query) =>
colors
.filter((c) => c.toLowerCase().includes(query.toLowerCase()))
.map((c) => ({ text: c, is_tappable: true, kind: null })),
amount: (query) => {
const digits = query.replace(/\D/g, "");
if (!digits) return [{ text: "$100", is_tappable: true, kind: null }];
return [{ text: `$${digits}`, is_tappable: true, kind: null }];
},
}}
onSubmit={handleSubmit}
/>;

Controlled mode

Lift state out of the component when you need to read or push the value from elsewhere — e.g. a wizard, form library, or shared parent.

controlled.tsx
const [text, setText] = useState("");
const [params, setParams] = useState<CompletedParamState[]>([]);
<AIAutocomplete
value={text}
onChange={setText}
completedParams={params}
onParamsChange={setParams}
onSubmit={handleSubmit}
/>;

Accessibility

The component implements the ARIA combobox pattern. Things you should know:

  • The dropdown uses role="listbox" with aria-activedescendant pointing at the highlighted option.
  • Pills are buttons (role="button") and announce as part of the live input.
  • Keyboard: arrow keys navigate, Enter submits, Tab autocompletes, Escape closes the dropdown.