a2ui-project / a2ui-project/a2ui

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

未关闭
#1,307 7 条评论 0 个 reaction 已指派 1 人 已被 @ditman 认领 在 GitHub 查看
component: react renderer P1 status: needs review status: needs-team-input type: bug
主要语言
TypeScript
星标
16.4k
派生
1.3k
平均合并
2 天 13 小时
30 天内合并 PR
134

描述

## 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`.

贡献指南

打开贡献指南

调研方向

Examine the tsup configuration in renderers/react/package.json scripts.build. The issue is that CSS module imports (like from './Button.module.css') are not being processed correctly during the build, resulting in empty objects in the published bundle. Check the bundle output in node_modules/@a2ui/react/v0_9/index.js for var Button_default = {};. Compare the build process for affected components (Button, TextField, ChoicePicker) versus unaffected ones (CheckBox, Slider) which use inline styles. Verify that the CSS module files are included and processed in the published tarball.

由索引模型根据 Issue 内容生成。

评估

技术栈
css, react, typescript
领域
build-system, frontend, release
Issue 类型
缺陷
难度
3/5
预计耗时
1-2 天
活跃度
活跃
描述清晰度
描述清楚
新手友好度
55/100

把新 issue 发到你的邮箱

精选适合新手参与的 GitHub issue 摘要。