Skip to content

Protocol Theme (createSurface.theme)

Besides injecting a full A2UITheme with provideA2UI({ theme }), you can attach a theme object on the v0.9 createSurface message to override primary color and font for a single Surface.

<A2UISurface> reads that payload and sets CSS variables on the Surface root:

FieldEffect
primaryColorBuilds a full --p-* ramp
fontSets --font-family / --font-family-flex

This matches the Surface Theme example in the examples app: surface-theme-example.json.

Live Preview

The two panels share the same component tree and differ only in createSurface.theme.primaryColor / font (rose vs blue):

Message Example

json
{
  "version": "v0.9",
  "createSurface": {
    "surfaceId": "example-surface-theme-rose",
    "catalogId": "https://a2ui.org/specification/v0_9/basic_catalog.json",
    "theme": {
      "primaryColor": "#e11d48",
      "font": "Georgia, 'Times New Roman', serif"
    }
  }
}

Follow up with updateComponents / updateDataModel on the same surfaceId. The preview (and the examples app) also create a second Surface with primaryColor: "#2563eb" for comparison.

vs App-Level Theme

LayerEntryScope
App themeprovideA2UI({ theme })App-wide: utility classes + additionalStyles
Surface themecreateSurface.theme--p-* / font on one Surface

They can stack: the app theme maps components to tokens; the protocol theme overrides the primary ramp on that Surface.

If Button does not follow primaryColor

The default theme hardcodes additionalStyles.Button.background as a gradient, which overrides color-bgc-p30 (var(--p-30)). To let Button pick up primaryColor, set:

ts
Button: {
  ...defaultTheme.additionalStyles?.Button,
  background: undefined,
}

The preview above and the examples Surface Theme page already do this.

Try It in Examples

bash
cd packages/vue-renderer
npm run dev

Open Surface Theme in the nav. Implementation:

Released under the MIT License.