` element unless `asChild` is set.
See the [Quoting guide](/docs/guides/quoting) for a complete walkthrough including the floating selection toolbar and backend handling.
Conditional Rendering \[#conditional-rendering]
Use `AuiIf` for conditional rendering based on composer state:
```tsx
import { AuiIf } from "@assistant-ui/react";
s.composer.isEditing}>
{/* rendered if message is being edited */}
s.composer.dictation != null}>
{/* rendered if dictation is active */}
```
Trigger Popover Primitives (Unstable) \[#trigger-popover-primitives-unstable]
These primitives are under the `Unstable_` prefix and may change without notice.
Unified primitives for any character-triggered popover (`@` mentions, `/` slash commands, `:` emoji, etc.). Multiple triggers coexist under a single `TriggerPopoverRoot`. See the [Mentions guide](/docs/guides/mentions) and [Slash Commands guide](/docs/guides/slash-commands) for full documentation and the [ComposerTriggerPopover component](/docs/ui/composer-trigger-popover) for a pre-built implementation.
Anatomy \[#anatomy-1]
```tsx
import { ComposerPrimitive } from "@assistant-ui/react";
import { unstable_defaultDirectiveFormatter } from "@assistant-ui/core";
const Composer = () => (
{(categories) =>
categories.map((cat) => (
{cat.label}
))
}
{(items) =>
items.map((item) => (
{item.label}
))
}
Back
);
```
Unstable\_TriggerPopoverRoot \[#unstable\_triggerpopoverroot]
Root provider that groups one or more `TriggerPopover` declarations. Owns the shared `ComposerInputPluginRegistry` that routes cursor and keyboard events to each registered trigger.
No props.
Unstable\_TriggerPopover \[#unstable\_triggerpopover]
Declares a trigger and renders its popover container. Only renders its DOM (and children) while this trigger is active in the composer input. Each declaration has an isolated scope — sub-primitives placed inside read state from this declaration only.
| Prop | Type | Default | Description |
| --------- | ------------------------- | ------- | ----------------------------------------------------------------------------------- |
| `char` | `string` | — | Character(s) that activate the trigger (e.g. `"@"`, `"/"`) — unique within the root |
| `adapter` | `Unstable_TriggerAdapter` | — | Provides categories, items, and search |
Selection behavior is declared by rendering **exactly one** behavior sub-primitive inside the `TriggerPopover`:
* [`Unstable_TriggerPopover.Directive`](#unstable_triggerpopoverdirective) — inserts `:type[label]{name=id}` into the composer on selection (mention behavior).
* [`Unstable_TriggerPopover.Action`](#unstable_triggerpopoveraction) — fires `onExecute` on selection; leaves a directive chip as an audit trail by default.
Renders a `` with `role="listbox"` when open.
Unstable\_TriggerPopover.Directive \[#unstable\_triggerpopoverdirective]
Behavior sub-primitive. Placed inside a ``. Renders nothing — registers an `"directive"` behavior with its parent. Exactly one behavior sub-primitive is allowed per `TriggerPopover`.
| Prop | Type | Default | Description |
| ------------ | ----------------------------- | ------------------------------------ | --------------------------------------------------------------------- |
| `formatter` | `Unstable_DirectiveFormatter` | `unstable_defaultDirectiveFormatter` | Serializes the selected item into composer text (and parses it back). |
| `onInserted` | `(item) => void` | — | Fires after the directive text has been inserted. |
Unstable\_TriggerPopover.Action \[#unstable\_triggerpopoveraction]
Behavior sub-primitive. Placed inside a ``. Renders nothing — registers an `"action"` behavior with its parent. Exactly one behavior sub-primitive is allowed per `TriggerPopover`.
| Prop | Type | Default | Description |
| ----------------- | ----------------------------- | ------------------------------------ | ------------------------------------------------------------------------------------ |
| `formatter` | `Unstable_DirectiveFormatter` | `unstable_defaultDirectiveFormatter` | Serializes the audit-trail chip (unused when `removeOnExecute` is true). |
| `onExecute` | `(item) => void` | — | Called the moment an item is selected — typically routes to a handler map. Required. |
| `removeOnExecute` | `boolean` | `false` | When `true`, strips the trigger text from the composer instead of leaving a chip. |
Unstable\_TriggerBehavior \[#unstable\_triggerbehavior]
Union type returned by the two behavior sub-primitives and consumed internally by the popover resources. Exported for advanced use cases (e.g. custom sub-primitives).
```ts
import type { Unstable_TriggerBehavior } from "@assistant-ui/react";
// Equivalent shape:
// Unstable_TriggerBehavior =
// | { kind: "directive"; formatter: Unstable_DirectiveFormatter; onInserted?: (item) => void }
// | { kind: "action"; formatter: Unstable_DirectiveFormatter; onExecute: (item) => void; removeOnExecute?: boolean }
```
Unstable\_TriggerPopoverCategories \[#unstable\_triggerpopovercategories]
Renders the top-level category list. Accepts a render function `(categories) => ReactNode`. Hidden when a category is selected or when in search mode.
Unstable\_TriggerPopoverCategoryItem \[#unstable\_triggerpopovercategoryitem]
A button that drills into a category. Renders `role="option"` with automatic `data-highlighted` and `aria-selected` when keyboard-navigated.
| Prop | Type | Description |
| ------------ | -------- | ------------------------------- |
| `categoryId` | `string` | The category to select on click |
Unstable\_TriggerPopoverItems \[#unstable\_triggerpopoveritems]
Renders the item list for the active category or search results. Accepts a render function `(items) => ReactNode`. Hidden when no category is selected and not in search mode.
Unstable\_TriggerPopoverItem \[#unstable\_triggerpopoveritem]
A button that selects an item. Renders `role="option"` with automatic `data-highlighted` and `aria-selected` when keyboard-navigated.
| Prop | Type | Description |
| ------- | ---------------------- | ---------------------------------------------- |
| `item` | `Unstable_TriggerItem` | The item to select on click |
| `index` | `number` | Optional index override for highlight matching |
Unstable\_TriggerPopoverBack \[#unstable\_triggerpopoverback]
A button that navigates back from items to the category list. Only renders when a category is active.
unstable\_useTriggerPopoverScopeContext \[#unstable\_usetriggerpopoverscopecontext]
Hook to access the popover state and actions for the nearest enclosing `Unstable_TriggerPopover`.
```tsx
const {
open, // boolean — whether popover is visible
query, // string — text after the trigger character
isSearchMode, // boolean — whether showing search results
highlightedIndex,
categories,
items,
activeCategoryId,
selectCategory,
selectItem,
goBack,
close,
handleKeyDown,
} = unstable_useTriggerPopoverScopeContext();
```
unstable\_useTriggerPopoverTriggers \[#unstable\_usetriggerpopovertriggers]
Hook to iterate every trigger registered under the current `Unstable_TriggerPopoverRoot`. Intended for input-level integrations (e.g. Lexical `DirectivePlugin`). Returns `ReadonlyMap`.
unstable\_useMentionAdapter \[#unstable\_usementionadapter]
Returns a spreadable `{ adapter, directive }` bundle for `@` mentions. Reads tools registered via `useAssistantTool`, accepts explicit `items`, and supports multi-category drill-down.
```tsx
import {
unstable_useMentionAdapter,
type Unstable_Mention,
} from "@assistant-ui/react";
function MyComposer() {
// Default: tools from model context as a single "Tools" category
const mention = unstable_useMentionAdapter();
return (
);
}
```
```tsx
// Multi-category + tools appended as their own category
const mention = unstable_useMentionAdapter({
categories: [
{ id: "users", label: "Users", items: [/* ... */] },
{ id: "files", label: "Files", items: [/* ... */] },
],
includeModelContextTools: true,
});
```
Options:
| Option | Type | Description |
| -------------------------- | ----------------------------------------------- | --------------------------------------------------------------------------- |
| `items` | `Unstable_Mention[]` | Flat list; ignored when `categories` is set. |
| `categories` | `{ id, label, items: Unstable_Mention[] }[]` | Drill-down groups. |
| `includeModelContextTools` | `boolean \| { category?, formatLabel?, icon? }` | Tools integration. Defaults to `true` iff neither `items` nor `categories`. |
| `formatter` | `Unstable_DirectiveFormatter` | Override directive serialization. |
| `onInserted` | `(item) => void` | Fires after the directive is inserted. |
| `iconMap` | `Record` | `metadata.icon` / category id → React component. |
| `fallbackIcon` | `Unstable_IconComponent` | Fallback when no `iconMap` entry matches. |
Returns `{ adapter, directive, iconMap?, fallbackIcon? }`.
unstable\_useSlashCommandAdapter \[#unstable\_useslashcommandadapter]
Returns a spreadable `{ adapter, action }` bundle for slash commands. Commands are declared as data + inline `execute` callbacks; `execute` lives in the hook closure and is never attached to the returned `Unstable_TriggerItem`, keeping items JSON-serializable.
```tsx
import {
unstable_useSlashCommandAdapter,
type Unstable_SlashCommand,
} from "@assistant-ui/react";
const SLASH_COMMANDS: readonly Unstable_SlashCommand[] = [
{ id: "summarize", execute: () => runSummarize(), icon: "FileText" },
{ id: "translate", execute: () => runTranslate(), icon: "Languages" },
];
function MyComposer() {
const slash = unstable_useSlashCommandAdapter({ commands: SLASH_COMMANDS });
return (
);
}
```
Pass `removeOnExecute: true` on the hook options to strip the trigger text from the composer after executing. The hook also accepts `iconMap` / `fallbackIcon` options that flow into the returned bundle — `{...slash}` spreads them into `ComposerTriggerPopover`.