Option List

Let users select from multiple choices.
<OptionList  options={[      {          "id": "good",          "label": "Good",          "description": "High quality work"      },      {          "id": "fast",          "label": "Fast",          "description": "Quick turnaround"      },      {          "id": "cheap",          "label": "Cheap",          "description": "Low cost"      }  ]}  maxSelections={2}  actions={[      {          "id": "cancel",          "label": "Reset"      },      {          "id": "confirm",          "label": "Confirm",          "variant": "default"      }  ]}  onAction={(actionId, selection) => {    if (actionId === "confirm") {      console.log("Selection:", selection);    }  }}/>

Not every choice fits in a text reply. When the assistant needs the user to pick an output format, a plan tier, or a movie genre, OptionList renders the options as selectable cards with single or multi-select behavior. The selection feeds back as a tool result, and the chosen option stays visible as a receipt. No free-text parsing required.

Role: Decision. For choices that return to the assistant. See Design Guidelines for how component roles work.

Getting Started

Run this once from your project root.

npx shadcn@latest add @tool-ui/option-list

Render OptionList in your UI with tool-compatible props.

import { OptionList } from "@/components/tool-ui/option-list";export function Example({  payload,}: {  payload: React.ComponentProps<typeof OptionList>;}) {  return <OptionList {...payload} />;}

Register this renderer so tool results display as OptionList.

"use client";// Frontend tool (recommended for decision surfaces like Option List):// - The model calls the tool with SerializableOptionList props as the args// - Your UI calls addResult(selection) from onAction when actionId is "confirm"import { type Toolkit } from "@assistant-ui/react";import { OptionList } from "@/components/tool-ui/option-list";import {  safeParseSerializableOptionList,  SerializableOptionListSchema,} from "@/components/tool-ui/option-list/schema";import { createArgsToolRenderer } from "@/components/tool-ui/shared";export const toolkit: Toolkit = {  selectFormat: {    description: "Let the user choose an output format.",    parameters: SerializableOptionListSchema,    render: createArgsToolRenderer({      safeParse: safeParseSerializableOptionList,      idPrefix: "format-selection",      render: (parsedArgs, { result, addResult }) =>        result ? (          <OptionList {...parsedArgs} value={undefined} choice={result} />        ) : (          <OptionList            {...parsedArgs}            // Avoid controlled selection in LLM-driven payloads.            value={undefined}            onAction={(actionId, selection) => {              if (actionId === "confirm") {                void addResult?.(selection);              }            }}          />        ),    }),  },};

Key Features

Single or multi-select

Radio buttons for one choice, checkboxes for many

Selection constraints

Set minimum and maximum selection counts

Configurable actions

Confirm, cancel, and custom footer buttons

Receipt state

Shows only the chosen option(s) as a read-only record

Receipt State

Pass a choice prop to render this component in its receipt state. See Receipts for the pattern.

The receipt shows only the selected option(s) with a checkmark. Unselected options and action buttons are hidden.

Props

Prop

Type

Option Schema

Prop

Type

Accessibility

  • Uses a semantic listbox + option pattern (role="listbox" with role="option" on each option button)
  • Exposes selection state with aria-selected and multi-select intent with aria-multiselectable
  • Implements roving tab focus with keyboard navigation (ArrowUp/ArrowDown, Home/End, Enter/Space, Escape)
  • Keeps footer actions keyboard-accessible through native button semantics