Skip to content

Add initial React Renderer v0.9#827

Merged
jacobsimionato merged 71 commits intogoogle:mainfrom
jacobsimionato:react-1
Mar 23, 2026
Merged

Add initial React Renderer v0.9#827
jacobsimionato merged 71 commits intogoogle:mainfrom
jacobsimionato:react-1

Conversation

@jacobsimionato
Copy link
Copy Markdown
Collaborator

@jacobsimionato jacobsimionato commented Mar 12, 2026

Description

This PR introduces the initial implementation of the @a2ui/react package, providing a React-based renderer for the A2UI v0.9 protocol. It follows the Unified Architecture & Implementation Guide, leveraging @a2ui/web_core for state management and data model resolution.

Key Features

  • Framework-Agnostic Core: Integrates deeply with @a2ui/web_core/v0_9, using its signal-based state models and GenericBinder.
  • Reactive Data Binding: Components automatically re-render when the underlying A2UI data model changes, powered by React's useSyncExternalStore hooked into the core model's reactive streams.
  • Generic Component Adapter: The createReactComponent utility automatically resolves A2UI DynamicValue fields (like DynamicString) into primitive JavaScript types and generates set<Property> setters for two-way data binding.
  • Minimal Catalog: Implements the v0.9 Minimal catalog, including Text, Button, Row, Column, and TextField, along with a logic-based capitalize function.
  • A2UI Explorer (Gallery App): Adds a 3-column reference application (renderers/react/a2ui_explorer) for exploring samples, inspecting the live data model, and stepping through progressive message rendering.

API Examples

Rendering a Surface

The A2uiSurface is the entry point for rendering an A2UI interface.

import { A2uiSurface, minimalCatalog } from '@a2ui/react/v0_9';
import { MessageProcessor } from '@a2ui/web_core/v0_9';

// 1. Initialize the processor with the catalog
const processor = new MessageProcessor([minimalCatalog]);

// 2. Process A2UI messages
processor.processMessages([{
  version: 'v0.9',
  createSurface: {
    surfaceId: 'my-surface',
    catalogId: 'https://a2ui.org/specification/v0_9/catalogs/minimal/minimal_catalog.json'
  }
}]);

// 3. Render in React
const MyComponent = () => {
  const surface = processor.model.getSurface('my-surface');
  return surface ? <A2uiSurface surface={surface} /> : <div>Loading...</div>;
};

Creating Custom Components

New components can be created using createReactComponent, which handles data-binding and schema validation automatically.

import { createReactComponent } from '@a2ui/react/v0_9';
import { CommonSchemas } from '@a2ui/web_core/v0_9';
import { z } from 'zod';

const MyCustomApi = {
  name: 'CustomCard',
  schema: z.object({
    title: CommonSchemas.DynamicString,
    content: CommonSchemas.ComponentId
  })
};

export const ReactCustomCard = createReactComponent(
  MyCustomApi,
  ({ props, buildChild }) => (
    <div className="custom-card">
      <h3>{props.title}</h3>
      <div className="card-body">
        {props.content && buildChild(props.content)}
      </div>
    </div>
  )
);

Implemented Components (v0.9 Minimal)

  • Layout: Row, Column
  • Display: Text
  • Inputs: Button, TextField
  • Functions: capitalize

Progress & Roadmap

  • Protocol v0.9 Initial Implementation
  • Gallery App (Explorer) Integration
  • CI/CD Workflow updates for Demo build/test
  • Full Basic Catalog implementation (v0.9)
  • Layout traits (weight, accessibility)

Copy link
Copy Markdown
Contributor

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request introduces a prototype React renderer for A2UI, including the core rendering logic, a component library for the minimal catalog, and a gallery application for demonstration and testing. The implementation is well-structured and follows the provided design document, leveraging modern React features like useSyncExternalStore for reactivity. My review includes a few suggestions to improve type safety, package configuration, and test coverage.

@jacobsimionato jacobsimionato changed the title Prototype react renderer Add initial React Renderer v0.9 Mar 20, 2026
@jacobsimionato jacobsimionato marked this pull request as ready for review March 20, 2026 02:33
@jacobsimionato
Copy link
Copy Markdown
Collaborator Author

/gemini review

@jacobsimionato
Copy link
Copy Markdown
Collaborator Author

/gemini review

@jacobsimionato
Copy link
Copy Markdown
Collaborator Author

/gemini review

gemini-code-assist[bot]

This comment was marked as outdated.

case 'h5':
return <h5>{text}</h5>;
case 'caption':
return <small>{text}</small>;
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There is technically a <caption> component, though it typically requires a way of referencing it from a figure or similar. Up to you if you want to use it here.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'll leave this for now - very keen to get the implementation in and refine the core APIs before polishing the catalog implementation.

Comment on lines +37 to +40
const context = useMemo(
() => new ComponentContext(surface, id, basePath),
[surface, id, basePath]
);
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

+1, this is worth addressing.

@jacobsimionato jacobsimionato merged commit da53d38 into google:main Mar 23, 2026
9 checks passed
@github-project-automation github-project-automation bot moved this from Todo to Done in A2UI Mar 23, 2026
wrenj pushed a commit to wrenj/A2UI that referenced this pull request Mar 25, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

Status: Done

Development

Successfully merging this pull request may close these issues.

2 participants