AssistantModal

Floating chat bubble for support widgets and help desks.

A floating chat modal built on Radix UI Popover. Ideal for support widgets, help desks, and embedded assistants.

Getting Started

Add assistant-modal

npx shadcn@latest add https://r.assistant-ui.com/assistant-modal.json

This adds /components/assistant-ui/assistant-modal.tsx to your project, which you can adjust as needed.

Use in your application

/app/page.tsx
import { AssistantModal } from "@/components/assistant-ui/assistant-modal";

export default function Home() {
  return (
    <div className="h-full">
      <AssistantModal />
    </div>
  );
}

Anatomy

The AssistantModal component is built with the following primitives:

import { AssistantModalPrimitive } from "@assistant-ui/react";

<AssistantModalPrimitive.Root>
  <AssistantModalPrimitive.Anchor />
  <AssistantModalPrimitive.Trigger />
  <AssistantModalPrimitive.Content>
    {/* Thread component goes here */}
  </AssistantModalPrimitive.Content>
</AssistantModalPrimitive.Root>

API Reference

Root

Contains all parts of the modal. Based on Radix UI Popover.

AssistantModalPrimitiveRootProps
defaultOpen?: boolean

The initial open state when uncontrolled.

open?: boolean

The controlled open state.

onOpenChange?: (open: boolean) => void

Callback when the open state changes.

unstable_openOnRunStart?: boolean

Automatically open the modal when the assistant starts running.

Trigger

A button that toggles the modal open/closed state.

AssistantModalPrimitiveTriggerProps
asChild: boolean= false

Merge props with child element instead of rendering a wrapper button.

This primitive renders a <button> element unless asChild is set.

Content

The popover content container that holds the chat interface.

AssistantModalPrimitiveContentProps
side: 'top' | 'right' | 'bottom' | 'left'= 'top'

The preferred side of the anchor to render against.

align: 'start' | 'center' | 'end'= 'end'

The preferred alignment against the anchor.

dissmissOnInteractOutside?: boolean

Whether to close the modal when clicking outside.

asChild: boolean= false

Merge props with child element instead of rendering a wrapper div.

Anchor

An optional anchor element to position the modal relative to.

AssistantModalPrimitiveAnchorProps
asChild: boolean= false

Merge props with child element instead of rendering a wrapper div.

  • Thread - The main chat interface used inside the modal
  • AssistantSidebar - Alternative layout for side panel chat