@personaai/ui exports two full widgets and a set of standalone building blocks. The widgets compose the building blocks internally — use the widgets when you want a complete chat experience, and the building blocks when you need to assemble your own layout.
Full widgets
PersonaChatView
The complete, self-contained chat widget — sidebar, message feed, composer, files drawer, interrupt card, and toolbar. All behavior wiring (thread creation, lazy message loading, file upload, present_file auto-open) is handled by usePersonaChatWidget internally.
Props
Layout structure
The widget handles
- Thread selection and lazy creation (first message creates a thread automatically)
- History loading when switching threads
- Sidebar/files-drawer toggle state
- Auto-closing sidebar on mobile viewport mount
- Present_file auto-opening the files drawer
When to use instead of building blocks
UsePersonaChatView when you want a standard chat layout with sidebar + main area + files drawer. If you need a different layout (composer at the top, sidebar on the right, no sidebar, a floating widget), compose the building blocks yourself.
PersonaChatLauncher
A floating action button (FAB) that toggles a PersonaChatView panel — for mounting a chat widget on any page rather than a dedicated chat route. Accepts every PersonaChatViewProps and passes them through.
Additional props (beyond PersonaChatViewProps)
Container-query responsive behavior
The launcher’s root is a named CSS container (@container/persona-chat). PersonaSidebar and PersonaFilesDrawer key their dock-vs-overlay breakpoints off @3xl/persona-chat (768px) and @5xl/persona-chat (1024px) — the same pixel thresholds as the normal md:/lg:, but measured against the widget’s own width instead of the browser viewport. This means sidebar and drawer correctly stay in overlay mode inside the launcher’s narrow floating panel even on a wide desktop.
Theme propagation
The FAB button is a sibling ofPersonaChatView’s subtree, not a descendant — it can’t inherit CSS variables PersonaChatView sets on its own root. The launcher computes buildThemeStyles once and applies it to a common ancestor of both the FAB and the panel, so primaryColor correctly reaches the FAB button.
Standalone building blocks
PersonaMessageFeed
The scrollable message list — renders messages, tool call cards, reasoning blocks, avatars, markdown, streaming indicators, and copy/reload buttons.
Props
Standalone usage
Rendering behavior
- User messages: plain text with
whitespace-pre-wrap, right-aligned, bubble background. - Assistant messages: Markdown-rendered (tables, LaTeX, fenced code blocks with copy button), left-aligned, full-width, no bubble background (since v0.7.1).
- Tool calls: rendered as
PersonaToolTracecards, optionally grouped intoPersonaToolGroupclusters. - Reasoning: collapsible “Thinking…” block above the answer.
- Streaming: pulsing blue dot after the content.
PersonaComposer
The message input area — auto-resizing textarea, send/stop button, file upload button, and starter prompt badges.
Props
Behavior
- Auto-resizes textarea height based on content (max 180px).
- Enter sends (Shift+Enter for newline).
- File upload button triggers a hidden
<input type="file">. - Starter prompts appear as pill badges above the input, only when input is empty.
PersonaSidebar
Thread list sidebar — search, date-grouped threads, inline rename, delete, and new-chat button.
Props
Responsive behavior
- Below
@3xl/persona-chat(768px): full-screen overlay with backdrop. - Above: docked inline panel.
- Auto-closes on mobile mount (handled by
usePersonaChatWidget). - Thread search appears when there are >5 threads.
Date grouping
Threads are grouped into: Today, Yesterday, Previous 7 Days, Older — based onupdatedAt.
PersonaFilesDrawer
Three-tab drawer: Files (uploads), Workspace (agent’s virtual filesystem + plan), Memory (persistent memory files).
Props
Responsive behavior
- Below
@5xl/persona-chat(1024px): full-screen overlay with backdrop. - Above: docked inline panel (80 wide).
PersonaToolTrace
A single tool call card — expandable accordion showing arguments, result, status, and subagent activity timeline. Special-cases present_file into a compact “Open this file” card, and write_todos into a checklist.
Props
Rendering behavior
present_file: Compact card with file icon, name, description, and Open button.write_todos: Checklist with completed/in-progress/pending icons, title shows “Plan (x/y)”.task(subagent): Nested timeline showing the subagent’s text output and tool calls.- Custom tool renderer: If
toolRenderers[toolCall.toolName]exists and the result is ready, delegates to that component instead. - Generic: Expandable accordion with JSON-formatted args and result.
PersonaToolGroup
Clusters 2+ consecutive tool calls into one collapsible card with a semantic title derived from what the cluster is doing (memory, file, search, task, plan, or mixed).
Props
Auto-open behavior
Auto-opens the moment any tool in the group starts running. Never auto-closes once opened — a card the user expanded stays open after completion.PersonaMarkdown
Renders assistant message content as Markdown — tables (GFM), LaTeX ($inline$ / $$block$$ via KaTeX), and fenced code blocks with a copy button. Used internally by PersonaMessageFeed for assistant messages.
Props
Note on user messages
User messages are deliberately rendered as plain text — rendering their literal input as Markdown could surprise them with formatting they didn’t intend.PersonaInterruptCard
Renders HITL approval requests (approve/reject buttons for tool actions) and clarification questions (option buttons or free-text input). Displayed between the message feed and composer when useChat’s interrupt is set.
Props
PersonaSkeleton
Skeleton loading primitives — shimmering placeholders used internally by PersonaMessageFeed, PersonaSidebar, and PersonaFilesDrawer when isLoading is true.
Custom tool renderers
Pass atoolRenderers map to render specific tools with your own component:
args and result (if available), plus isExecuting (true while the tool is still running) and isError (true if the tool returned an error).
usePersonaChatWidget
The behavioral hook that PersonaChatView is built on — every stateful piece (thread selection, lazy creation, sidebar/drawer state, present_file auto-open) extracted into its own hook. PersonaChatView is just one layout built on top of it.
Options
When to use
UseusePersonaChatWidget when you’re building a completely custom layout (not PersonaChatView) but want the same behavior wiring — thread management, lazy creation, sidebar state, present_file auto-open — without reimplementing it against the raw useChat/useThreads hooks.
Return value
Returns every field fromuseChat plus:
activeThreadId,setActiveThread— thread selectionsidebarOpen,setSidebarOpen— sidebar statefilesDrawerOpen,setFilesDrawerOpen— drawer statethreads,deleteThread,renameThread,threadsLoading— thread managementfiles,deleteFile,filesLoading— uploaded filesmemory,getMemoryFile,deleteMemoryFile,memoryLoading— memoryworkspaceFiles— agent workspace files (renamed fromuseChat’sfilesto avoid collision)handleSelectThread,handleNewChat,handleSend,handleUploadFile— composed handlers
Name collision
useFiles() and useChat() both name their very different files field the same thing. The hook exposes them as files (uploads) and workspaceFiles (agent workspace) respectively.