# design-sync notes — @audi-dash/ui

## Repo shape
- Package shape (no Storybook). Build: `npm run build` (tsup) in the repo root produces `dist/index.js` (ESM), `dist/index.cjs` (CJS), `dist/index.d.ts`, `dist/styles.css`. The converter's `--entry` points at `dist/index.js`.
- Converter deps are staged/installed under `.ds-sync/` (isolated npm project, gitignored) — never mixed into the repo's own `package.json`.
- On Windows, `npm install` needs `npm approve-scripts esbuild` once per fresh `.ds-sync/`/`node_modules` (npm 11's allow-scripts gate blocks esbuild's postinstall that downloads its platform binary).

## Known render warns (triaged, safe to ignore on re-sync)
- `[RENDER_THIN]` on `IconButton`: "mounts have no text and paint nothing" — false positive. IconButton is intentionally icon-only (no text content, `aria-label` only). Screenshot confirms both cells (Default, Disabled) render the icons correctly; the heuristic just measures text content, which is legitimately empty here.

## cfg.overrides
- `Popup`: `cardMode: "single"` — it's a fixed-position overlay component that portals to `document.body`; grid mode collapsed/escaped its card.
- `Accordion`, `Feld`, `TabBar`, `StatGrid`: `cardMode: "column"` — one or more of their authored stories render wider than a grid cell (multi-field forms / full-width nav bars); column mode gives them the full card width instead of being cropped.

## Preview authoring conventions
- Every preview wraps its composition in `<div className="ads-root" data-theme="nacht">` (a local `Root` helper duplicated per file) — the library only applies text color/background via `.ads-root`, and without it previews render with browser-default black-on-white instead of the app's actual dark theme. **This is required for every future preview** — the components' color tokens are on `:root` (theme-independent) but `color`/`background` inheritance only kicks in under `.ads-root`.
- `Popup`'s children portal to `document.body`, escaping any local `.ads-root` wrapper. This doesn't break styling because `Popup`'s own CSS (`.ads-popup`, `.ads-popup-item`) sets `background`/`color` directly from `var(--tile-2)`/`var(--fg)` rather than relying on inherited color — so it renders correctly even though the wrapper technically doesn't reach it.
- `SwipeRow`'s `SwipedOpen` story shows content clipped at the left edge behind the revealed delete button — this is correct, faithful behavior (the row slides left to reveal the delete action), not a rendering defect.

## Re-sync risks
- All 20 previews are hand-authored (no floor cards) — a future re-sync only needs to touch previews for components whose source or `.tsx` actually changed; everything else carries forward via the grade cache + `_ds_sync.json` anchor.
- The `Root` wrapper pattern (data-theme="nacht") is duplicated per preview file rather than imported from a shared module — if a preview is added later without it, it will silently render unthemed (black text, no background). Check for `data-theme="nacht"` in any new preview before grading it.
- Playwright/Chromium was freshly installed for this sync (`.ds-sync/node_modules/playwright`, chromium cached at `~/AppData/Local/ms-playwright`) — not committed, machine-local. A re-sync on a different machine needs to reinstall it (package-validate.mjs will prompt if missing).
- No `docsDir`/docs were found in this repo (it's a fresh internal design system, no README-per-component docs yet) — all `.prompt.md` files are synthesized from `.d.ts` + the authored preview `.tsx`, not from hand-written docs. If per-component docs are added later, set `cfg.docsDir` to pick them up.
