The production SSH alias is old-vps; the placeholder "production" alias does not exist. Also captures research findings on theming the A2UI basic catalog without overriding component internals, for later reference. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
5.0 KiB
A2UI Theming Findings
Captured 2026-04-28 while researching how to beautify the table the agent renders via render_a2ui without overriding component internals.
TL;DR
- A2UI v0.9 docs prescribe theming through a small set of documented top-level CSS variables declared on
:where(:root)(zero specificity, so host CSS wins without!important). - Default theme uses
light-dark()so tokens self-toggle. Recommended dark-mode coupling: add the documenteda2ui-darkclass on<html>whenever Tailwind's.darkis on; that flipscolor-scheme: darkand resolves everylight-dark()to its dark branch. - In our app, this approach has near-zero visible effect. We render through
@copilotkit/a2ui-renderer(React variant), not@a2ui/lit. Inspecting the compiled React renderer (node_modules/.pnpm/@copilotkit+a2ui-renderer@1.56.4/.../catalog/basic/components/*.mjs), every component uses hardcoded inline styles; the only CSS variable consumed across the whole basic catalog is--a2ui-primary-color. - This matches open issues
google/A2UI#977and#1285("React renderer parity is incomplete").
Documented token surface (Lit / Angular)
From tech_docs/A2UI/renderers/web_core/src/v0_9/basic_catalog/styles/default.ts:
- Color palette:
--a2ui-color-background,--a2ui-color-on-background,--a2ui-color-surface,--a2ui-color-on-surface,--a2ui-color-primary,--a2ui-color-primary-light/-dark/-hover,--a2ui-color-on-primary,--a2ui-color-secondary,--a2ui-color-secondary-light/-dark/-hover,--a2ui-color-on-secondary,--a2ui-color-input,--a2ui-color-on-input,--a2ui-color-border. - Borders:
--a2ui-border,--a2ui-border-width,--a2ui-border-radius. - Typography:
--a2ui-font-family-title,--a2ui-font-family-monospace,--a2ui-font-size,--a2ui-font-scale,--a2ui-font-size-xs..2xl,--a2ui-line-height-headings,--a2ui-line-height-body. - Spacing:
--a2ui-grid-base,--a2ui-spacing-xs..xl.
Per-component tokens like --a2ui-card-background exist but the renderer README and the official theming guide explicitly frame them as catalog-internal, not stable spec. Avoid relying on them.
Dark-mode coupling
A2UI default uses light-dark(...) and supports forced modes via a2ui-light / a2ui-dark classes (see the :where(.a2ui-dark) block in default.ts). Best practice for a host that uses Tailwind .dark on <html>: toggle the matching a2ui-dark class in lockstep — one effect-driven useEffect, or add it directly to the root if the app is dark-only. No need to redeclare every token under .dark; the default rules already pick up the right branch through light-dark().
Footguns in v0.9
- The agent-supplied
themepayload (e.g.createSurface.theme.primaryColor) is not yet wired in the basic catalog. Tracked ingoogle/A2UI#979(Lit) and#977(React). Don't expect agent-side theming to recolor anything in v0.9; only the host CSS does. hintedStyles(h1–h6 mappings) require all keys when overridden — seegoogle/A2UI#602.- Tracking issues for the broader theming surface:
google/A2UI#1083,#1118.
Why this won't move the table in our app
@copilotkit/a2ui-renderer@1.56.4 (React) is what <CopilotKit a2ui={{}}> plugs in. Its components apply colors and borders as inline style props (backgroundColor: "#fff", border: "1px solid #ccc", etc.). Inline styles can only be overridden with !important in author CSS, which contradicts the "don't take its freedom" goal. So the documented --a2ui-* token contract is currently a Lit-only surface for this catalog.
Practical options for this codebase
- Quick win: set
--a2ui-primary-color: var(--primary)on:root. Real but small effect (primary buttons, links). - Prompt-side polish: instruct the agent to compose richer A2UI structures — wrap the table in a
Card, useusageHint: "h3"for the section title, insert aDivider, group columns withRow+Columnweights — so the renderer's existing inline styles produce a cleaner result. No code change. - Switch renderer: replace
@copilotkit/a2ui-rendererwith@a2ui/lit(or wait for@a2ui/reactparity). Then every documented--a2ui-*token actually applies. Non-trivial migration. - Custom catalog overrides: register replacement React components for
Row/List/CardviacreateA2UICatalog; full control, most invasive, accepts ownership of those components forever.
Source links
tech_docs/A2UI/docs/guides/theming.mdtech_docs/A2UI/renderers/web_core/src/v0_9/basic_catalog/styles/default.tstech_docs/A2UI/renderers/lit/README.md§"CSS-based Basic Catalog Theming"https://github.com/google/A2UI/issues/977(React renderer theming gap)https://github.com/google/A2UI/issues/1285(React renderer parity)https://github.com/google/A2UI/issues/1118(theming surface roadmap)https://github.com/google/A2UI/issues/979(Litthemepayload not wired)https://github.com/google/A2UI/pull/1079(v0.9 CSS-variable rollout)