Composer: Deduplicate gallery data with spec examples#1006
Composer: Deduplicate gallery data with spec examples#1006nan-yu merged 17 commits intogoogle:mainfrom
Conversation
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.
nan-yu
left a comment
There was a problem hiding this comment.
Looks good. Thanks for adding support for v0.9!
|
Reminder: This PR has merge conflicts. Please rebase and resolve. |
- 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').
- Add valueArray handling in v0.8 ValueMap conversion (sync script) - Add componentDidCatch to preview error boundary for console logging
- Update theater page import from @copilotkit/a2ui-renderer to @/lib/a2ui - Align useA2UISurface types with shared A2UIComponent type - Add specVersion to Widget mocks in test files - Regenerate pnpm-lock.yaml for npm @a2ui/react and @a2ui/web_core
9b8ba12 to
a747f67
Compare
@nan-yu all rebased and cleaned up - ready for you to review! |
|
Thanks @lukasmoschitz ! The new spec version tab looks great. Merging now. Just a heads-up on the next steps:
|
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)