a2ui-project / a2ui-project/a2ui

[react@0.9.1] Published bundle ships empty CSS-module class refs — Button / TextField / ChoicePicker render unstyled

Abierto
#1,307 7 comentarios 0 reacciones 1 asignado Reclamado por @ditman Ver en GitHub
component: react renderer P1 status: needs review status: needs-team-input type: bug
Lenguaje dominante
TypeScript
Estrellas
16.4k
Forks
1.3k
Merge medio
2 d 13 h
PR fusionados (30 d)
134

Descripción

## Symptom

Components emitted by `@a2ui/react/v0_9` render with no padding, border, color, or hover state when used via the published npm tarball (`@a2ui/react@0.9.1`, sha `ea8e3a3c7d3dca12921cb230ef06144d95454098`). Three components reproduce:

- `` → `label`
- `` → `

`
- `` → similar empty class refs

``, ``, ``, ``, ``, ``, ``, ``, `` are unaffected — they use inline-style objects in source (no `.module.css` import) or rely on the `.a2uiText` / `.a2uiCaption` plain class names that DO ship in `v0_9/index.css`.

## Reproduction (minimal, deterministic)

```bash
mkdir /tmp/a2ui-repro && cd /tmp/a2ui-repro
npm init -y
npm install @a2ui/react@0.9.1
grep -A6 'var Button_default' node_modules/@a2ui/react/v0_9/index.js | head -8
```

Output (verified 2026-04-30 against the published tarball):

```js
// src/v0_9/catalog/basic/components/Button.module.css
var Button_default = {};
var Button = createComponentImplementation(ButtonApi, ({ props, buildChild }) => {
useBasicCatalogStyles();
const classes = [Button_default.button];
if (props.variant === "primary") {
classes.push(Button_default.primary);
```

`Button_default` is the JS-side object that should hold the CSS-module-hashed class names from `Button.module.css` (e.g. `{button: "Button-button-abc123", primary: "Button-primary-def456"}`). It's empty in the published tarball, so `classes.join(" ")` produces the literal string `"undefined undefined"`. Same applies to `TextField_default` and `ChoicePicker_default` (grep them in the same file to confirm).

The published `package.json` exports `"./styles/structural.css": "./structural.css"`, but `find node_modules/@a2ui/react -name structural.css` returns nothing — the file isn't actually shipped in the tarball. `node_modules/@a2ui/react/v0_9/index.css` exists but contains only `.a2uiText` / `.a2uiCaption` rules (no `.a2uiButton`, `.a2uiPrimary`, `.a2uiBorderless`, etc.).

## Why the official `samples/client/react/shell/` works (and users see broken output)

`samples/client/react/shell/package.json` declares:

```json
"@a2ui/react": "file:../../../../renderers/react"
```

This is a `file:` dep pointing at local source, so Vite handles `.module.css` natively at build time and class names get populated correctly. The shell sample never goes through the npm publish/install path, so its visual parity tests don't catch this regression. Users running `npm install @a2ui/react` get the broken bundle.

The shell's `App.css` ships **zero** `[data-a2ui-surface] button` rules — confirms the renderer is *supposed* to be self-styled by its CSS modules. There's no documented "you must also import `@a2ui/react/styles/...`" step that would compensate.

## Source vs published bundle (root cause)

Source: `renderers/react/src/v0_9/catalog/basic/components/Button.tsx`

```tsx
import styles from './Button.module.css';

export const Button = createComponentImplementation(ButtonApi, ({props, buildChild}) => {
useBasicCatalogStyles();
const classes = [styles.button];
if (props.variant === 'primary') classes.push(styles.primary);
// ...
});
```

The source `import styles from './Button.module.css'` is preserved as `var Button_default` in the bundle, but the build pipeline (`tsup` per `renderers/react/package.json` `scripts.build`) is publishing it as `{}` — the module's exports aren't being captured. CheckBox/Slider work because their source uses `const containerStyle = {...}` inline objects rather than CSS-module imports.

## Related issues

- #1306 (`[ci] npm publishing manifest format is malformed`, opened 2026-04-29) — confirms the publishing pipeline is currently broken; manifest lists `@a2ui/react: 0.9.1` and `@a2ui/web_core: 0.9.2`. Likely the upstream root cause but a different symptom.
- #1285 (`Component Style Overrides Missing in React Renderer`) — feature request for override API; orthogonal to this rendering bug.
- #977 (`Wire up theme in React renderer basic catalog`) — about `--a2ui-primary-color` theme wiring; separate concern.
- #867 (`Publish @a2ui/react to npm`) — still open as P1, suggesting stable v0.9 publish hasn't formally landed.

## Workaround for users

Two options:

1. **Use `file:` dep** like the official shell sample (requires `git clone https://github.com/google/A2UI.git` + building locally on each consumer machine):
```json
"@a2ui/react": "file:../path/to/A2UI/renderers/react"
```

2. **Element-selector CSS shim** scoped to the surface wrapper. Doesn't reproduce SDK branding exactly but restores baseline visual feedback:
```css
[data-a2ui-surface] button { padding: 0.5rem 1rem; border: 1px solid var(--border); border-radius: 0.5rem; ... }
[data-a2ui-surface] input,
[data-a2ui-surface] textarea { padding: 0.5rem 0.75rem; border: 1px solid var(--border); ... }
```

## Environment

- `@a2ui/react@0.9.1` (latest published; `0.9.0`, `0.9.0-alpha.3/4` show same shape per `npm view`)
- `@a2ui/web_core@0.9.2`
- `@a2ui/markdown-it@0.0.3`
- Next.js 16 + React 19 + Tailwind v4 host application
- Node 20.20.2 / npm 10

---

This report was prepared with AI assistance (Claude Code). Repro commands and source/bundle excerpts above were executed against the public tarball and the v0.9 source on `main`.

Guía de contribución

Abrir la guía de contribución

Evaluación

Este issue todavía no se ha evaluado.

Recibe los nuevos issues en tu correo

Un resumen breve de issues de GitHub para principiantes.