Composer: Deduplicate gallery data with spec examples#1006
Open
lukasmoschitz wants to merge 16 commits intogoogle:mainfrom
Open
Composer: Deduplicate gallery data with spec examples#1006lukasmoschitz wants to merge 16 commits intogoogle:mainfrom
lukasmoschitz wants to merge 16 commits intogoogle:mainfrom
Conversation
- Swap dependency from @copilotkit/a2ui-renderer to @a2ui/react@^0.8.0 - Add adapter layer (src/lib/a2ui.tsx) as single import point for all renderer consumers, enabling future v0.8/v0.9 version switching - Add composerTheme extending litTheme with additionalStyles to fix button text color (--n-10/--n-35 remap to white inside buttons) - Add A2UI color palettes (--p-*, --n-*, --s-*) in globals.css to replace the palette that Lit's themed-a2ui-surface provided via Shadow DOM - Fix nested <button> hydration error in gallery-widget by changing outer wrapper from <button> to <div role="button"> - Update all 9 import sites to use adapter instead of package directly
…ng margins - Add viewerTheme.ts: exact port of the production viewer-theme used by A2UIViewer on a2ui-composer.ag-ui.com (from private_a2ui_demo repo) - Add appTheme.ts: the app-level theme used for chat view (for future use) - Switch adapter to use viewerTheme instead of composerTheme - Fix card background in gallery: define --a2ui-card-bg at :root level and reference it via --p-100 so the gallery wrapper can override it to transparent (matching Lit's themed-a2ui-surface behavior) - Fix heading margins: add layout-m-0 to markdown.h4 and markdown.h5 to prevent browser default margins on h4/h5 elements
- Add specVersion field ('0.8' | '0.9') to Widget type
- Add all existing gallery widgets as specVersion: '0.8'
- Create V09Viewer wrapper that builds SurfaceModel from v0.9
component definitions and renders via A2uiSurface
- Update adapter (a2ui.tsx) to switch between v0.8 A2UIViewer
and v0.9 V09Viewer based on specVersion prop
- Pass specVersion through preview-pane and gallery-widget
- Switch @a2ui/react to local file dependency for v0.9 exports
- Add @a2ui/web_core dependency for MessageProcessor
- Add SpecVersionContext with localStorage persistence - Add VersionSelector toggle (v0.8/v0.9) in sidebar - Reorganize gallery data into v08/ and v09/ subdirectories - Gallery page switches widget set based on selected version - Fix v0.8 gallery data: action string shorthand → object format, invalid 'baseline' alignment → 'center' - Add v0.9 Contact Card sample widget - Fix SSR error: dynamically import V09Viewer (client-only) - Pass specVersion through widget-preview-modal
Convert all v0.8 gallery widgets to v0.9 format:
- Flat component structure (component: 'TypeName' discriminator)
- Property renames (usageHint→variant, alignment→align, distribution→justify)
- Value unwrapping (literalString→string, explicitList→array)
- Action format (action: { event: { name, context } })
- Native JSON data (no ValueMap arrays)
All samples render via V09Viewer → MessageProcessor → A2uiSurface.
Gallery switches between v0.8 and v0.9 sets via the sidebar toggle.
- Create page uses specVersion context for default components and widget creation (v0.8 or v0.9 format based on sidebar toggle) - AI prompt rewritten to document both v0.8 and v0.9 formats - User messages prefixed with [A2UI v0.8] or [A2UI v0.9] tag so the AI generates the correct component format - Start Blank also respects the selected version
…n-agnostic
Two agents:
- v08 agent with actual v0.8 catalog spec from specification/v0_8/
- v09 agent with actual v0.9 catalog spec + rules from specification/v0_9/
- Client selects agent via useAgent({ agentId }) based on specVersion
- Editor chat uses widget.specVersion to pick the right agent
- No version mixing possible — each agent only knows its format
Version-agnostic component type:
- Replace v0.8-specific ComponentInstance with A2UIComponent
(Record<string, unknown> & { id: string }) in Widget type
- Editor, preview, create all use the agnostic type
- Only the adapter interprets component structure for routing
- Remove as any[] casts from v0.9 gallery widgets
Also:
- Editor header shows version badge (v0.8/v0.9)
- Delete old combined a2ui-prompt.ts
- Components page switches docs/previews between v0.8 and v0.9 based on global spec version toggle - Add components-data-v09.ts with v0.9 property names, usage examples, and preview components for all 16 component types - Add error boundary around preview pane — invalid components show fallback instead of crashing the editor - Remove unused composerTheme.ts and appTheme.ts - Disable ChoicePicker preview (requires live data binding)
- Icons page renders with correct renderer based on spec version toggle - Add .material-symbols-outlined CSS class in globals.css — the v0.9 Icon component uses this class but Google Fonts only provides @font-face rules, not the class definition - Includes overflow: hidden to prevent icon name text from overflowing during font load
- TextField: rename 'text' prop to 'value', fix variant enum (remove 'date', add 'obscured', default 'shortText') - ChoicePicker: fix variant enum to 'multipleSelection'/'mutuallyExclusive', add displayStyle and filterable props - Image: fix 'scale-down' to 'scaleDown' in fit enum - Row/Column: add 'stretch' to justify enum - Button: add 'default' to variant enum - List: add missing 'align' prop - DateTimeInput: add missing label, min, max props - Slider: add missing label prop, add default for min - Divider: remove non-spec color/thickness props
- Add variant: 'primary' to main CTA buttons in 9 v0.9 gallery widgets - Change default spec version to v0.9 - Move version selector above navigation in sidebar - Fix music player: replace non-existent ProgressBar with Slider (max: 262, values in seconds)
- Add web_core and react renderer build steps before composer install - Add renderer paths to CI trigger so composer rebuilds when renderers change (local file dependency)
- Fix hydration mismatch: use useEffect + isLoaded flag to defer
version-dependent rendering until client has loaded localStorage
- Fix type: replace any[] with A2UIComponent[] for v0.9 defaults
- Fix accessibility: make role/tabIndex conditional on onClick
- Add license header to pnpm-lock.yaml for CI check
Replace 58 hand-written gallery widget files with a prebuild script that generates them from the canonical spec examples: - specification/v0_8/json/catalogs/basic/examples/ (29 widgets) - specification/v0_9/json/catalogs/basic/examples/ (33 widgets) The script (scripts/sync-gallery.mjs) runs automatically before build and dev via package.json pre-hooks. Generated files are gitignored — CI regenerates them from the spec on each build. Includes v0.8 sanitization for values the renderer doesn't support (e.g. textFieldType 'obscured' mapped to 'shortText').
Contributor
There was a problem hiding this comment.
Code Review
This pull request introduces support for A2UI v0.9 by adding a version selector, updating the renderer adapter, and providing new system prompts. It also includes a script to sync gallery data from the specification and updates existing components to be version-aware. My feedback highlights the need to handle array values in the sync script, improve error logging in the preview boundary, and ensure consistent prop handling across renderers.
- Add valueArray handling in v0.8 ValueMap conversion (sync script) - Add componentDidCatch to preview error boundary for console logging
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Follow-up to #992. Replaces the 58 hand-written gallery widget files with a prebuild script that generates them directly from the canonical spec examples in
specification/v0_8/andspecification/v0_9/.How it works
A Node script (
scripts/sync-gallery.mjs) reads the JSON examples, extracts components and data from the message format, and writes TypeScript files that the gallery imports. It runs automatically viaprebuild/predevhooks in package.json. The generated files are gitignored — CI regenerates them on each build.specification/v0_8/json/catalogs/basic/examples/specification/v0_9/json/catalogs/basic/examples/(includes 4 new examples)v0.8 sanitization
The spec examples contain some values the v0.8 renderer doesn't support (e.g.
textFieldType: 'obscured',alignment: 'baseline',action: 'string'). The sync script maps these to valid values so the gallery renders without errors.Discovered renderer issues
skip_previousbut the spec usesskipPrevious, causing icons to render as textTest plan
pnpm buildregenerates and succeeds)