|
| 1 | +# @a2ui/react |
| 2 | + |
| 3 | +A React renderer for the A2UI protocol with ShadCN-style components and Tailwind CSS. |
| 4 | + |
| 5 | +## Installation |
| 6 | + |
| 7 | +```bash |
| 8 | +npm install @a2ui/react |
| 9 | +``` |
| 10 | + |
| 11 | +### Peer Dependencies |
| 12 | + |
| 13 | +This package requires the following peer dependencies: |
| 14 | + |
| 15 | +```bash |
| 16 | +npm install react react-dom tailwindcss |
| 17 | +``` |
| 18 | + |
| 19 | +## Quick Start |
| 20 | + |
| 21 | +### 1. Set up Tailwind CSS |
| 22 | + |
| 23 | +Ensure your project has Tailwind CSS configured. Add the A2UI React components to your `tailwind.config.js`: |
| 24 | + |
| 25 | +```js |
| 26 | +module.exports = { |
| 27 | + content: [ |
| 28 | + // ... your content paths |
| 29 | + "./node_modules/@a2ui/react/**/*.{js,ts,jsx,tsx}", |
| 30 | + ], |
| 31 | + // ... rest of config |
| 32 | +}; |
| 33 | +``` |
| 34 | + |
| 35 | +### 2. Wrap your app with providers |
| 36 | + |
| 37 | +```tsx |
| 38 | +import { A2UIProvider, ThemeProvider } from "@a2ui/react"; |
| 39 | + |
| 40 | +function App() { |
| 41 | + const handleAction = (action) => { |
| 42 | + // Send action to your server |
| 43 | + console.log("Action:", action); |
| 44 | + }; |
| 45 | + |
| 46 | + return ( |
| 47 | + <A2UIProvider onAction={handleAction}> |
| 48 | + <ThemeProvider> |
| 49 | + <YourApp /> |
| 50 | + </ThemeProvider> |
| 51 | + </A2UIProvider> |
| 52 | + ); |
| 53 | +} |
| 54 | +``` |
| 55 | + |
| 56 | +### 3. Process messages and render |
| 57 | + |
| 58 | +```tsx |
| 59 | +import { useA2UI, A2UIRenderer } from "@a2ui/react"; |
| 60 | +import { useEffect } from "react"; |
| 61 | + |
| 62 | +function YourApp() { |
| 63 | + const { processMessages } = useA2UI(); |
| 64 | + |
| 65 | + useEffect(() => { |
| 66 | + // Fetch A2UI messages from your server |
| 67 | + fetch("/api/a2ui") |
| 68 | + .then((res) => res.json()) |
| 69 | + .then((messages) => processMessages(messages)); |
| 70 | + }, [processMessages]); |
| 71 | + |
| 72 | + return <A2UIRenderer surfaceId="main" />; |
| 73 | +} |
| 74 | +``` |
| 75 | + |
| 76 | +## API Reference |
| 77 | + |
| 78 | +### Providers |
| 79 | + |
| 80 | +#### `<A2UIProvider>` |
| 81 | + |
| 82 | +Main context provider for A2UI state management. |
| 83 | + |
| 84 | +```tsx |
| 85 | +<A2UIProvider onAction={(action) => console.log(action)}> |
| 86 | + {children} |
| 87 | +</A2UIProvider> |
| 88 | +``` |
| 89 | + |
| 90 | +Props: |
| 91 | +- `onAction`: Callback when user triggers an action (e.g., button click) |
| 92 | +- `children`: React children |
| 93 | + |
| 94 | +#### `<ThemeProvider>` |
| 95 | + |
| 96 | +Provides CSS class mappings for styling components. |
| 97 | + |
| 98 | +```tsx |
| 99 | +<ThemeProvider theme={customTheme}> |
| 100 | + {children} |
| 101 | +</ThemeProvider> |
| 102 | +``` |
| 103 | + |
| 104 | +Props: |
| 105 | +- `theme`: Optional custom theme object (defaults to ShadCN-style theme) |
| 106 | +- `children`: React children |
| 107 | + |
| 108 | +### Hooks |
| 109 | + |
| 110 | +#### `useA2UI()` |
| 111 | + |
| 112 | +Main hook for interacting with A2UI. |
| 113 | + |
| 114 | +```tsx |
| 115 | +const { |
| 116 | + surfaces, // Map of all surfaces |
| 117 | + getSurface, // Get a specific surface |
| 118 | + processMessages, // Process incoming A2UI messages |
| 119 | + sendAction, // Send an action to the server |
| 120 | + getComponentTree, // Get the root component tree for a surface |
| 121 | + clearSurfaces, // Clear all surfaces |
| 122 | +} = useA2UI(); |
| 123 | +``` |
| 124 | + |
| 125 | +#### `useDataBinding(node, surfaceId)` |
| 126 | + |
| 127 | +Hook for resolving data bindings in custom components. |
| 128 | + |
| 129 | +```tsx |
| 130 | +const { |
| 131 | + resolveString, // Resolve a StringValue |
| 132 | + resolveNumber, // Resolve a NumberValue |
| 133 | + resolveBoolean, // Resolve a BooleanValue |
| 134 | + setValue, // Set a value in the data model |
| 135 | + getValue, // Get a value from the data model |
| 136 | +} = useDataBinding(node, surfaceId); |
| 137 | +``` |
| 138 | + |
| 139 | +### Components |
| 140 | + |
| 141 | +#### `<A2UIRenderer>` |
| 142 | + |
| 143 | +Main renderer component that renders an entire A2UI surface. |
| 144 | + |
| 145 | +```tsx |
| 146 | +<A2UIRenderer |
| 147 | + surfaceId="main" |
| 148 | + className="my-surface" |
| 149 | + fallback={<Loading />} |
| 150 | +/> |
| 151 | +``` |
| 152 | + |
| 153 | +Props: |
| 154 | +- `surfaceId`: The ID of the surface to render |
| 155 | +- `className`: Optional CSS class for the root element |
| 156 | +- `fallback`: Optional fallback when surface is not found |
| 157 | + |
| 158 | +### Standard Components |
| 159 | + |
| 160 | +All 18 standard A2UI components are implemented: |
| 161 | + |
| 162 | +**Content:** |
| 163 | +- `Text` - Text with markdown support and typography hints |
| 164 | +- `Image` - Images with fit and usage hints |
| 165 | +- `Icon` - Icons from Lucide React |
| 166 | +- `Video` - Video player |
| 167 | +- `AudioPlayer` - Audio player with description |
| 168 | +- `Divider` - Horizontal/vertical separator |
| 169 | + |
| 170 | +**Layout:** |
| 171 | +- `Row` - Horizontal flex container |
| 172 | +- `Column` - Vertical flex container |
| 173 | +- `List` - Scrollable list (horizontal/vertical) |
| 174 | +- `Card` - Card container |
| 175 | +- `Tabs` - Tab navigation |
| 176 | +- `Modal` - Modal dialog |
| 177 | + |
| 178 | +**Interactive:** |
| 179 | +- `Button` - Clickable button with action support |
| 180 | +- `CheckBox` - Checkbox with label |
| 181 | +- `TextField` - Text input (various types) |
| 182 | +- `DateTimeInput` - Date/time picker |
| 183 | +- `MultipleChoice` - Select dropdown |
| 184 | +- `Slider` - Range slider |
| 185 | + |
| 186 | +## Custom Theming |
| 187 | + |
| 188 | +You can customize the appearance by providing a custom theme: |
| 189 | + |
| 190 | +```tsx |
| 191 | +import { ThemeProvider, defaultTheme } from "@a2ui/react"; |
| 192 | + |
| 193 | +const customTheme = { |
| 194 | + ...defaultTheme, |
| 195 | + components: { |
| 196 | + ...defaultTheme.components, |
| 197 | + Button: { |
| 198 | + "bg-blue-500": true, |
| 199 | + "text-white": true, |
| 200 | + "px-4": true, |
| 201 | + "py-2": true, |
| 202 | + "rounded": true, |
| 203 | + }, |
| 204 | + }, |
| 205 | +}; |
| 206 | + |
| 207 | +<ThemeProvider theme={customTheme}> |
| 208 | + {children} |
| 209 | +</ThemeProvider> |
| 210 | +``` |
| 211 | + |
| 212 | +## Streaming Messages |
| 213 | + |
| 214 | +For streaming A2UI messages (e.g., from Server-Sent Events): |
| 215 | + |
| 216 | +```tsx |
| 217 | +function StreamingApp() { |
| 218 | + const { processMessages } = useA2UI(); |
| 219 | + |
| 220 | + useEffect(() => { |
| 221 | + const eventSource = new EventSource("/api/a2ui/stream"); |
| 222 | + |
| 223 | + eventSource.onmessage = (event) => { |
| 224 | + const message = JSON.parse(event.data); |
| 225 | + processMessages([message]); |
| 226 | + }; |
| 227 | + |
| 228 | + return () => eventSource.close(); |
| 229 | + }, [processMessages]); |
| 230 | + |
| 231 | + return <A2UIRenderer surfaceId="main" />; |
| 232 | +} |
| 233 | +``` |
| 234 | + |
| 235 | +## TypeScript |
| 236 | + |
| 237 | +This package is written in TypeScript and includes full type definitions. Types are re-exported from `@a2ui/lit`: |
| 238 | + |
| 239 | +```tsx |
| 240 | +import { Types, Primitives, Data } from "@a2ui/react"; |
| 241 | + |
| 242 | +// Use types |
| 243 | +const surface: Types.Surface = ...; |
| 244 | +const message: Types.ServerToClientMessage = ...; |
| 245 | +``` |
| 246 | + |
| 247 | +## License |
| 248 | + |
| 249 | +Apache-2.0 |
0 commit comments