# SelectionToolbar
URL: /docs/primitives/selection-toolbar
A floating toolbar that appears when text is selected within a message.
The SelectionToolbar primitive is a floating toolbar that appears when the user selects text within a message. It lets users quote selected text into the composer. Styling and action layout are fully customizable.
```tsx
import { SelectionToolbarPrimitive } from "@assistant-ui/react";
import { QuoteIcon } from "lucide-react";
function FloatingSelectionToolbar() {
return (
Quote
);
}
```
Quick Start \[#quick-start]
A minimal selection toolbar:
```tsx
import { SelectionToolbarPrimitive } from "@assistant-ui/react";
Quote
```
`Root` renders a `
` inside a portal, positioned above the text selection. `Quote` renders a `
` that copies the selected text into the composer as a quote.
Runtime setup: primitives require runtime context. Wrap your UI in `AssistantRuntimeProvider` with a runtime (for example `useLocalRuntime(...)`). See [Pick a Runtime](/docs/runtimes/pick-a-runtime).
Core Concepts \[#core-concepts]
Automatic Positioning \[#automatic-positioning]
`Root` renders via a portal to `document.body`. In the current implementation, it positions itself with `position: fixed`, `top: rect.top - 8px`, `left: rect.left + rect.width / 2`, `transform: translate(-50%, -100%)` (placing it centered above the selection), and `z-index: 50`.
Single-Message Validation \[#single-message-validation]
The toolbar only appears when the selection is entirely within a single message. Cross-message selections are ignored. Detection works by checking for `data-message-id` attributes on ancestor elements, which `MessagePrimitive.Root` sets automatically.
`Root` returns `null` when there is no valid selection (collapsed selection, empty text, or no single-message match).
Quote Action \[#quote-action]
The `Quote` button does two things on click:
1. Calls `composer.setQuote({ text, messageId })` to populate the composer with the selected text as a quoted snippet
2. Clears the browser selection via `window.getSelection()?.removeAllRanges()`
The composer then shows the quoted text, and the user can type a follow-up message around it.
Dismissal \[#dismissal]
The toolbar hides automatically when:
* The user scrolls
* The selection collapses (click away or arrow keys)
* The selection is cleared programmatically (e.g., after quoting)
Clicking the toolbar itself does not dismiss the selection. `Root` calls `preventDefault` on `mousedown` to preserve it.
Placement in Thread \[#placement-in-thread]
The SelectionToolbar must be placed inside `ThreadPrimitive.Root` but **outside** `ThreadPrimitive.Viewport`. It positions itself via a portal based on the browser selection, independent of the scroll container:
```tsx
Quote
...
```
Parts \[#parts]
Root \[#root]
Floating toolbar container that appears for a valid text selection. Renders a `` element unless `asChild` is set.
```tsx
Quote
```
Quote \[#quote]
Quotes the currently selected text into the composer. Renders a `` element unless `asChild` is set.
```tsx
Quote
```
Patterns \[#patterns]
Basic Toolbar with Quote \[#basic-toolbar-with-quote]
```tsx
Quote
```
Toolbar with Multiple Actions \[#toolbar-with-multiple-actions]
You can add custom buttons alongside `Quote` for additional actions:
```tsx
Quote
navigator.clipboard.writeText(window.getSelection()?.toString() ?? "")}
>
Copy
```
Relationship to Components \[#relationship-to-components]
There is no pre-built shadcn component for SelectionToolbar. See the [Quoting guide](/docs/guides/quoting) for the full workflow including composer quote display and dismiss.
API Reference \[#api-reference]
For full prop details on every part, see the [SelectionToolbarPrimitive API Reference](/docs/api-reference/primitives/selection-toolbar).
Related:
* [Quoting Guide](/docs/guides/quoting)
* [ComposerPrimitive API Reference](/docs/api-reference/primitives/composer)