React UI Base
Loading...

Overview

Reference for unstyled base primitives in @tambo-ai/react-ui-base.

The @tambo-ai/react-ui-base package exposes behavior-focused primitives. These components are intentionally unstyled and designed for composition in your own UI layer.

The same components — Message, MessageInput, and their sub-parts — can produce wildly different interfaces just by changing styles. Use the Theme control below to see three variations built with the exact same primitives.

U
What's the weather in Tokyo?
A
It's currently 18°C and clear in Tokyo. Perfect weather for cherry blossom viewing!
U
How about this weekend?
A
This weekend looks great — Saturday will be 20°C with sunshine, and Sunday drops to 16°C with light clouds.
import { Message } from "@tambo-ai/react-ui-base/message";import { MessageInput } from "@tambo-ai/react-ui-base/message-input";import type { TamboThreadMessage } from "@tambo-ai/react";const messages: TamboThreadMessage[] = [  { id: "1", role: "user", content: [{ type: "text", text: "What's the weather in Tokyo?" }] },  { id: "2", role: "assistant", content: [{ type: "text", text: "It's 18°C and clear!" }] },];// Modern minimal: rounded bubbles, avatars, role-based colorsexport function MinimalChat() {  return (    <div style={{ borderRadius: 12, border: "1px solid #e5e7eb", overflow: "hidden" }}>      <div style={{ padding: 16, display: "flex", flexDirection: "column", gap: 12 }}>        {messages.map((msg) => (          <Message.Root key={msg.id} message={msg} role={msg.role}            style={{ display: "flex", gap: 8, ...(msg.role === "user" ? { flexDirection: "row-reverse" } : {}) }}>            <div style={{              width: 28, height: 28, borderRadius: "50%", display: "flex",              alignItems: "center", justifyContent: "center", fontSize: 12, fontWeight: 700,              backgroundColor: msg.role === "user" ? "#3b82f6" : "#e5e7eb",              color: msg.role === "user" ? "#fff" : "#4b5563",            }}>{msg.role === "user" ? "U" : "A"}</div>            <div style={{              padding: "9px 14px", borderRadius: 18,              backgroundColor: msg.role === "user" ? "#3b82f6" : "#f3f4f6",              color: msg.role === "user" ? "#fff" : "#1f2937",            }}>              <Message.Content style={{ fontSize: 14, lineHeight: 1.5 }} />            </div>          </Message.Root>        ))}      </div>      <MessageInput.Root style={{ borderTop: "1px solid #e5e7eb", padding: "10px 12px" }}>        <MessageInput.Content style={{ display: "flex", gap: 8 }}>          <MessageInput.Textarea placeholder="Type a message..."            style={{ flex: 1, border: "1px solid #d1d5db", borderRadius: 20, padding: "8px 14px", fontSize: 14, outline: "none" }} />          <MessageInput.SubmitButton style={{ padding: "8px 16px", borderRadius: 20, border: "none", backgroundColor: "#3b82f6", color: "#fff", fontWeight: 600, cursor: "pointer" }}>            Send          </MessageInput.SubmitButton>        </MessageInput.Content>      </MessageInput.Root>    </div>  );}

Primitives

Ownership model

  • @tambo-ai/react-ui-base: behavior, state, and composition contracts.
  • @tambo-ai/ui-registry: styled components and block-level orchestration.

Key patterns

Role-based styling

Each component exposes data-role attributes. Style user and assistant messages differently:

<Message.Root message={message} role={message.role}
  style={{ flexDirection: message.role === "user" ? "row-reverse" : "row" }}>

No CSS framework required

The examples above use plain inline styles — no Tailwind, no CSS modules, no styled-components. The base components work with any styling approach.