Overview
The Modal example shows a floating action button that opens an AI assistant chat in a modal dialog. The assistant stays available without taking space from the main interface.
Features
- Floating Action Button: A button fixed to the corner of the screen
- Modal Dialog: Chat interface with focus management
- Thread List: A toggle in the header lists earlier conversations, and the plus button starts another one
- Resizable Window: Drag the top corner or use the arrow keys; the size is remembered in the browser, and a double click restores the default
- Animations: Enter/exit transitions with zoom and slide effects
- Responsive Design: Works across desktop and mobile devices
- Keyboard Navigation: Escape key to close, tab order follows the layout
Quick Start
npx assistant-ui add assistant-modalCode
The registry component builds on AssistantModalPrimitive. A minimal version, without the header, the thread list and resizing, looks like this:
import { AssistantModalPrimitive } from "@assistant-ui/react";
import { Thread } from "@/components/assistant-ui/elements/thread.aui";
import { BotIcon } from "lucide-react";
export const AssistantModal = () => {
return (
<AssistantModalPrimitive.Root>
<AssistantModalPrimitive.Anchor className="fixed right-4 bottom-4 size-11">
<AssistantModalPrimitive.Trigger asChild>
<button className="flex size-full items-center justify-center rounded-full border border-border/60 bg-background text-foreground transition-[border-color,scale] duration-150 ease-out hover:border-border active:scale-96 motion-reduce:transition-none">
<BotIcon className="size-5" />
</button>
</AssistantModalPrimitive.Trigger>
</AssistantModalPrimitive.Anchor>
<AssistantModalPrimitive.Content
sideOffset={16}
className="h-[500px] w-[400px] origin-(--radix-popover-content-transform-origin) overflow-clip rounded-xl bg-popover shadow-[0_16px_48px_-24px_rgb(0_0_0/0.25)] ring-1 ring-foreground/10 ease-[cubic-bezier(0.32,0.72,0,1)] data-[state=open]:animate-in data-[state=open]:fade-in-0 data-[state=open]:zoom-in-95 data-[state=open]:slide-in-from-bottom-2 data-[state=open]:duration-300 data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=closed]:zoom-out-95 data-[state=closed]:slide-out-to-bottom-2 data-[state=closed]:duration-200 motion-reduce:animate-none"
>
<Thread />
</AssistantModalPrimitive.Content>
</AssistantModalPrimitive.Root>
);
};Key Components
| Component | Purpose |
|---|---|
AssistantModalPrimitive.Root | Container that manages open/close state |
AssistantModalPrimitive.Anchor | Positions the trigger button |
AssistantModalPrimitive.Trigger | Button that opens the modal |
AssistantModalPrimitive.Content | The modal dialog containing the chat |
Customization Tips
- Adjust
sideOffsetto control the gap between button and modal - Modify
h-[500px] w-[400px]to change modal dimensions - Use
data-[state=open/closed]for animation states - Position the anchor with
fixed right-4 bottom-4or any corner