logoassistant-ui

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 @assistant-ui/assistant-modal

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