Skip to main content
@personaai/ui is a set of pre-built React components for Persona — full chat widgets and standalone building blocks that compose on top of @personaai/react hooks. Use them to get a polished chat UI without writing message rendering, tool call cards, sidebar, files drawer, or theming from scratch. v0.7.3, current release. Requires @personaai/react ^0.3.2 and React 18+.

Install

@personaai/react is a peer dependency. You also need a <PersonaProvider> wrapping your app — see the React SDK quickstart if you haven’t set that up yet.

Import the stylesheet

Required. @personaai/ui ships a self-contained styles.css that bundles all Tailwind utility classes the components use, plus KaTeX styles for LaTeX math rendering. Import it once in your app’s entry point:
Without this import, every component renders unstyled — this is the most common setup issue.
The styles.css is built with Tailwind v4’s CLI against this package’s own source. It uses theme + utilities layers only, deliberately skipping Preflight, so it doesn’t reset your own app’s base styles.

Minimal example — PersonaChatView

PersonaChatView is the fully-assembled chat widget: sidebar, message feed, composer, files drawer, interrupt card — all wired together. Drop it into a page and you have a complete chat experience:
That’s a complete chat UI — streaming messages, sidebar with thread history, files drawer, tool call cards, markdown rendering, and theme support — all in ~20 lines.

PersonaChatLauncher — floating widget

For embedding a chat bubble on any page (support widget style), use PersonaChatLauncher. It renders a floating action button (FAB) that toggles a PersonaChatView panel:
The launcher passes every PersonaChatView prop straight through — the panel is a full PersonaChatView inside a floating container.

PersonaChatLauncher props (launcher-specific)

In addition to all PersonaChatViewProps, the launcher accepts:

Controlled launcher

Container-query responsive behavior

The launcher uses CSS container queries (@container/persona-chat) — sidebar and files drawer dock vs. overlay based on the panel’s own width, not the browser viewport. This means they correctly stay in overlay mode inside the launcher’s narrow floating panel even on a wide desktop, the same way they do on a narrow phone. No manual configuration needed.

Custom theme

Pass a theme prop to change colors. Every value maps to a CSS custom property, so passing your own var(--your-token) works too — the persona vars become indirections that pick up your existing light/dark switching:

Using your own design tokens

Since every theme value is a CSS custom property, you can pass your own tokens as values:
The components render style="--persona-primary: var(--brand-primary)" — CSS resolves the outer var first, then the inner one, correctly picking up whatever light/dark switching your app already has. No extra JS required.

Theme property reference

Every unset property falls through to the component’s built-in zinc palette defaults — an unthemed widget looks identical to one with no theme prop at all.

Starter prompts

Show quick-action buttons above the composer on the first message:
Starter prompts only appear when the message list is empty — once the user sends their first message, they disappear.

Tool call rendering

Tool calls render as expandable cards by default. You can:
  1. Disable grouping — render one card per tool call instead of clustering consecutive calls:
  2. Customize cluster labels — override the auto-generated titles for grouped tool calls:
  3. Provide custom tool renderers — render specific tools with your own React component:

Next steps