fix(a2ui-renderer): type createCatalog renderer props as the binder resolves them by Laptopmini · Pull Request #7815 · CopilotKit/CopilotKit · GitHub
Skip to content

fix(a2ui-renderer): type createCatalog renderer props as the binder resolves them - #7815

Open
Laptopmini wants to merge 1 commit into
CopilotKit:mainfrom
Laptopmini:fix/7814-a2ui-renderer-resolved-props
Open

Laptopmini wants to merge 1 commit into
CopilotKit:mainfrom
Laptopmini:fix/7814-a2ui-renderer-resolved-props

Conversation

@Laptopmini

@Laptopmini Laptopmini commented Oct 14, 2026 •

Copy link
Copy Markdown
Contributor

What does this PR do?

CatalogRenderers typed each renderer's props as z.infer of the component schema, which is the raw A2UI input shape. A bound DynamicNumber was typed number | { path } | { call, … }, an Action prop was typed as the action object, and the set<Prop> setters didn't exist. At runtime, though, the GenericBinder passes resolved props:

  • bound values arrive as their current value;
  • Action props arrive as functions that dispatch the action with its context resolved;
  • every bindable prop gets a set<Prop> setter that writes the data model.

As a result, custom renderers had to cast to call an action or a setter. The basic catalog avoids the problem because createReactComponent types its props with ResolveA2uiProps from @a2ui/web_core.

This PR uses the same type for createCatalog, so CatalogRenderers is now ComponentRenderer<ResolveA2uiProps<z.infer<D[K]["props"]>>>. The deprecated createA2UICatalog's A2UIComponentDefinition.render gets the same change, and the RendererProps.props doc now describes what renderers receive. PropsOf is unchanged: it describes the definition, not what a renderer receives.

Tests. The new file src/react-renderer/__tests__/create-catalog-props.test.tsx is covered by both vitest and check-types:

  • A Dimmer renderer reads props.level as a number and calls props.setLevel(…) and props.changeLevel() with no casts. On main this fails check-types with 4 errors.
  • At runtime, moving the slider writes /level through the setter. The dispatched changeLevel action's context then reads the new value ({ to: 65 }). This part passes on main too: it pins the runtime behaviour the new types describe.
  • A @ts-expect-error checks that setLevel("high") is still rejected.

Checked:

  • a2ui-renderer: check-types passes, and the package's tests pass (23).
  • nx run-many -t check-types for a2ui-renderer and react-core passes, without the Nx cache.
  • The lefthook pre-commit hooks pass, including test-and-check-packages.
  • Out-of-workspace usages: the showcase integrations and examples pin published versions, so CI doesn't type-check them against this change. I type-checked all 36 distinct files that call createCatalog or use CatalogRenderers across 15 projects. Each was checked with strict: true against this branch's built declarations and against the same build with only this change reverted. 14 projects show no difference.

One case to flag. Whether this counts as breaking under VERSIONING.md is your call. ResolveA2uiProp treats any prop whose type is structurally a ChildList (string[] | { componentId, path }) as a child list and resolves it to any. examples/showcases/reskinnable-demo/src/shell/chat/inline-block-surface.dom.test.tsx declares a plain children: z.array(z.string()), so with this change props.children.map((id) => …) reports TS7006: Parameter 'id' implicitly has an 'any' type under strict. That project pins 1.71.0, so nothing breaks today. The fix on upgrade is (id: string) =>. It's the only new error in the 15 projects. If you'd prefer this marked as breaking, I'll add the ! and a BREAKING CHANGE: note.

AI disclosure: written with AI assistance (Claude Code). I reproduced the issue, reviewed the change, and ran the checks above myself.

Related PRs and Issues

Checklist

  • I have read the Contribution Guide
  • If the PR changes or adds functionality, I have updated the relevant documentation (the RendererProps.props doc comment)
  • If the PR contains a breaking change, the title has ! and the description has a BREAKING CHANGE: line (see the case flagged above; not marked)
  • "Allow edits by maintainers" is checked

Summary by CodeRabbit

  • Developer Experience
    • Improved renderer prop types to reflect resolved bindings, action handlers, and setters for bindable values.
  • Tests
    • Added coverage verifying that slider changes update bound values and pass the updated value to dispatched actions.
    • Added type checks confirming that setters reject values of the wrong type.

…esolves them

CatalogRenderers typed each renderer's props as z.infer of the schema,
the raw A2UI input shape. At runtime the GenericBinder passes resolved
props: bound values as their current value, Action props as functions,
and a set<Prop> setter for every bindable prop. Type them with
ResolveA2uiProps from @a2ui/web_core, as createReactComponent already
does for the basic catalog.

Closes CopilotKit#7814
@coderabbitai

coderabbitai Bot commented Oct 14, 2026 •

Copy link
Copy Markdown
Contributor

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

1 participant