Skip to content

Composer: Deduplicate gallery data with spec examples#1006

Open
lukasmoschitz wants to merge 16 commits intogoogle:mainfrom
CopilotKit:composer-deduplicate-gallery
Open

Composer: Deduplicate gallery data with spec examples#1006
lukasmoschitz wants to merge 16 commits intogoogle:mainfrom
CopilotKit:composer-deduplicate-gallery

Conversation

@lukasmoschitz
Copy link
Copy Markdown
Contributor

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/ and specification/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 via prebuild/predev hooks in package.json. The generated files are gitignored — CI regenerates them on each build.

  • v0.8: 29 widgets from specification/v0_8/json/catalogs/basic/examples/
  • v0.9: 33 widgets from 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

  • v0.9 Icon component does not convert camelCase icon names to snake_case — Material Symbols requires skip_previous but the spec uses skipPrevious, causing icons to render as text

Test plan

  • v0.8 gallery renders all 29 widgets from spec examples
  • v0.9 gallery renders all 33 widgets from spec examples
  • Clean build from scratch (delete generated files, pnpm build regenerates and succeeds)
  • All 32 existing tests pass

- 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').
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 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
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

Status: Todo

Development

Successfully merging this pull request may close these issues.

1 participant