A2UI for React
Render Google A2UI with Material 3 Expressive.
Material 3 Expressive for A2UI is a React renderer for Google’s A2UI protocol. It maps every component of the A2UI basic catalog to Google’s Material 3 Expressive design system, so the interfaces your agents generate share one theme with the rest of your app.
Stream surfaces as messages arrive, bind inputs to the data model, validate with checks, and send actions back to the agent.
Try it here
Stream an agent surface.
Scripted demo. No LLM or API key required.
Choose a scenario
Every message is scripted. You can stop playback at any time.
Streaming a surface
The agent names the card before it sends the content, so a placeholder appears first. Data bindings, formatting functions, and a later value update fill it in.
Show me my trip to Lisbon.
Play the scenario to stream the surface.
How it works
From a message stream to Material components.
The renderer sits between Google’s protocol runtime and the design system. It adds no runtime dependencies and no transport.
Messages arrive
Your agent streams A2UI JSON messages over A2A, HTTP, or a WebSocket. You parse each line and pass it to processMessages.
web_core keeps the models
Google’s @a2ui/web_core validates every message, owns the surface and data models, and evaluates bindings and catalog functions.
Surfaces render
A2uiSurface subscribes to each component and renders it with a Material 3 Expressive component. Children named before they arrive show as placeholders.
Actions go back
Inputs write into the data model. A button dispatches its event with the resolved context to your onAction callback, ready to send to the agent.
Supported components
The whole A2UI basic catalog.
All 18 components of the v0.9.1 basic catalog render with Material 3 Expressive components and tokens. Every color, type style, corner, and motion value follows your theme in light and dark modes.
| A2UI component | Renders as | Notes |
|---|---|---|
Text | Text | h1 to h5 map to headline and title roles. Markdown subset: bold, italic, code, links, headings, lists. |
Image | Image with variant sizing | icon, avatar, smallFeature, mediumFeature, largeFeature, header. |
Icon | Icon | Catalog names render as embedded glyphs. No icon font required. |
Video | Native video player | Controls enabled. |
AudioPlayer | Native audio player | Controls enabled. |
Row | Flex row | justify, align, and child weight. |
Column | Flex column | justify, align, and child weight. |
List | List | Vertical or horizontal, static children or a template. |
Card | Card | Outlined, passive container. |
Tabs | Tabs | Keyboard operable. |
Modal | Dialog | The trigger opens the dialog and still dispatches its action. |
Divider | Divider | Horizontal or vertical. |
Button | Button | primary filled, default tonal, borderless text. Disabled while checks fail. |
TextField | TextField or TextArea | shortText, longText, obscured, number. |
CheckBox | Checkbox | Labeled. |
ChoicePicker | Radio, Checkbox, or filter Chip | Exclusive or multiple, optional filter field. |
Slider | Slider | Decimal precision follows the range. |
DateTimeInput | Native date and time input | Material tokens. ISO 8601 both ways, zone aware. |
Compatibility
Versions and limits.
The package is an independent community implementation. It is not affiliated with Google. A2UI and Material Design are Google projects.
A2UI protocol | v0.9.1 (v0.9 accepted). The basic catalog. |
|---|---|
@a2ui/web_core | ^0.10.7, tested with 0.10.7. |
@language-lit/material3-expressive | ^1.2.0. |
React and React DOM | 18 or 19. |
@a2ui/react | The catalog is tested under 0.11.0. Not a dependency; it needs React 19 itself. |
Known limits
- The basic catalog only, by default. Register other catalogs with
createMaterial3Catalog. - Icon names outside the catalog fall back to a Material Symbols ligature, which needs that font.
- The Markdown subset has no tables, images, raw HTML, or nested lists.
DateTimeInputuses the platform picker until the design system ships one.primaryColorfrom the agent is exposed as a custom property. It does not re-theme the surface.- Transport, authentication, persistence, and orchestration stay in your application.
Start building
Add A2UI to your React app.
Install the renderer and its peers in a React 18 or 19 app.
npm install @language-lit/material3-expressive-a2ui @language-lit/material3-expressive @a2ui/web_coreImport both stylesheets in this order, then own a processor with useA2ui and render each surface inside your Material3Provider.
import '@language-lit/material3-expressive/styles.css'
import '@language-lit/material3-expressive-a2ui/styles.css'import { Material3Provider } from '@language-lit/material3-expressive'
import { A2uiSurface, useA2ui } from '@language-lit/material3-expressive-a2ui'
export function AgentPanel({ send }) {
const { surfaces, processMessages } = useA2ui({
onAction: (action) => send(action),
})
// Call processMessages(messages) with each batch your agent delivers.
return (
<Material3Provider>
{surfaces.map((surface) => (
<A2uiSurface key={surface.id} surface={surface} />
))}
</Material3Provider>
)
}Already rendering with Google’s React surface?
material3Catalog from @language-lit/material3-expressive-a2ui is a web_core catalog in the render-only shape that @a2ui/react consumes. Register it with your existing processor and keep your own surface, transport, and fallback policy.
Build your own agent surfaces.
Start with the setup guide, then read how each component renders and how to extend the catalog. The protocol itself is documented by the A2UI project.
Getting started with A2UI
Install the renderer, stream A2UI messages into surfaces, and send actions back to the agent.
A2UI components and rendering rules
How each basic-catalog component renders, plus binding, validation, templates, theming, and catalog extension.