a2ui-react
v0.5.0
Published
Beautiful shadcn/ui components for rendering A2UI protocol messages in React
Maintainers
Readme
a2ui-react
Beautiful shadcn/ui components for rendering A2UI protocol messages in React.
Work in Progress: This library is under active development and APIs may change. We welcome feedback, bug reports, and contributions! Please open an issue if you encounter any problems or have suggestions.
Installation
npm install a2ui-react
# or
yarn add a2ui-reactSetup
Add the theme import and @source directive to your main CSS file:
/* Import the a2ui-react theme (includes Tailwind and all theme variables) */
@import 'a2ui-react/theme.css';
/* Tell Tailwind to scan the package for class usage */
@source "../node_modules/a2ui-react/dist";Both lines are required:
theme.cssprovides Tailwind, shadcn/ui theme variables, and alert color tokens@sourceensures Tailwind includes the component classes (v4 doesn't scan node_modules by default)
Quick Start
import { A2UIProvider, A2UISurface, shadcnRenderers } from 'a2ui-react'
const messages = [
{
beginRendering: {
surfaceId: 'my-surface',
root: 'root',
},
},
{
surfaceUpdate: {
surfaceId: 'my-surface',
updates: [
{
id: 'root',
component: {
type: 'Column',
id: 'root',
children: ['greeting'],
},
},
{
id: 'greeting',
component: {
type: 'Text',
id: 'greeting',
content: 'Hello, World!',
style: 'h1',
},
},
],
},
},
]
function App() {
return (
<A2UIProvider renderers={shadcnRenderers}>
<A2UISurface surfaceId="my-surface" messages={messages} />
</A2UIProvider>
)
}Features
- Complete A2UI Protocol Support - All component types from the A2UI specification
- Beautiful shadcn/ui Components - Modern, accessible, and customizable
- Streaming Ready - Process real-time streaming updates from AI models
- Two-Way Data Binding - Interactive components with automatic state management
- Fully Typed - Complete TypeScript support with exported types
- Customizable Renderers - Override any component with your own implementation
Supported Components
Layout
Row- Horizontal flex containerColumn- Vertical flex container
Display
Text- Typography with styles (h1-h5, body, caption)Image- Images with loading statesIcon- Lucide iconsDivider- Horizontal/vertical separators
Interactive
Button- Clickable buttons with actionsTextField- Text inputs (short, long, number, date, obscured)Checkbox- Boolean togglesSelect- Dropdown selectionSlider- Range inputDateTimeInput- Date/time pickersMultipleChoice- Multi-select options
Container
Card- Content cardsModal- Dialog overlaysTabs- Tabbed contentList- Data-driven lists
Custom Renderers
Override any built-in renderer with your own:
import type { A2UIRenderer, ButtonComponent } from 'a2ui-react'
import { motion } from 'framer-motion'
const AnimatedButton: A2UIRenderer<ButtonComponent> = {
type: 'Button',
render: ({ component, children, onAction }) => (
<motion.button
whileHover={{ scale: 1.05 }}
whileTap={{ scale: 0.95 }}
onClick={() => component.action && onAction({ type: component.action })}
>
{children}
</motion.button>
),
}
// Add to renderers (last one wins for same type)
const customRenderers = [...shadcnRenderers, AnimatedButton]Streaming Integration
Parse and render streaming A2UI messages:
import { createStore, parseJSONL, A2UIProvider, A2UISurface, shadcnRenderers } from 'a2ui-react'
const store = createStore()
// Process streaming response
async function handleStream(reader: ReadableStreamDefaultReader<Uint8Array>) {
for await (const message of parseJSONL(reader)) {
store.processMessage(message)
}
}
function App() {
return (
<A2UIProvider renderers={shadcnRenderers} store={store}>
<A2UISurface surfaceId="stream-surface" />
</A2UIProvider>
)
}API Reference
Components
A2UIProvider- Context provider for renderers and storeA2UISurface- Renders a surface by IDComponentRenderer- Renders individual components
Hooks
useA2UI()- Access the A2UI contextuseSurface(surfaceId)- Subscribe to a surfaceuseDataBinding(dataPath)- Two-way data bindinguseAction()- Access action handler
Store
createStore()- Create an A2UI store instancestore.processMessage(msg)- Process incoming messagesstore.getSurface(id)- Get surface statestore.getData(surfaceId, path)- Get data valuestore.setData(surfaceId, path, value)- Set data value
Parser
parseMessage(json)- Parse a single messageparseJSONL(reader)- Async generator for streaming JSONLcreateStreamParser()- Create a stateful stream parser
Requirements
- React 18.0.0+ or React 19.0.0+
- Tailwind CSS v4 (for styling)
Important Notes
Component ID Format
The id must be present both in the update wrapper AND inside the component object:
// ✅ Correct
{
id: 'greeting',
component: {
type: 'Text',
id: 'greeting', // Required inside component
content: 'Hello!'
}
}
// ❌ Won't work - missing id inside component
{
id: 'greeting',
component: {
type: 'Text',
content: 'Hello!'
}
}a2ui-go Compatibility
Works out of the box with a2ui-go - both use the A2UI v0.9 message format.
License
MIT
