Fix unstyled modals in dev: re-read document styles after page load (#4242)

## Problem

Since #4229, modals render unstyled in `npm run dev` (no black backdrop,
no Tailwind styling). Production/staging is unaffected.

`documentStylesSheet()` reads the document's `<style>` tags once, at
module-eval time. In dev, Vite injects the Tailwind styles *during*
module evaluation — after that read — so the shared constructed
stylesheet ended up with 7 CSS rules instead of the full Tailwind sheet.
In production the styles come from a `<link rel=stylesheet>` that is
fetched by URL, so timing doesn't matter there.

## Fix

If the document hasn't finished loading when the sheet is first created,
re-populate it once on the window `load` event (which fires after the
entry module graph — and therefore all style injection — completes).
Constructed stylesheets are live, so already-rendered components pick
the styles up without re-rendering. The existing HMR re-populate hook is
unchanged.

## Test plan

- [x] Reproduced in dev with headless Chromium: shared sheet had 7
rules, modal unstyled
- [x] After fix: sheet has full Tailwind rules, solo modal renders with
correct dark styling (screenshot-verified)
- [x] `npx tsc --noEmit`, ESLint clean
- [x] Client test suite: 458 tests pass

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
Evan
2026-06-12 09:26:21 -07:00
committed by GitHub
parent 27054bde83
commit eeb5f7e850
@@ -39,6 +39,16 @@ export function documentStylesSheet(): CSSStyleSheet {
if (sheet === null) {
sheet = new CSSStyleSheet();
void populate(sheet);
// In dev this module evaluates before Vite injects the page's <style>
// tags, so the read above sees almost nothing — re-read once the page
// has fully loaded (constructed sheets are live, so components pick up
// the styles without re-rendering).
if (document.readyState !== "complete") {
const populated = sheet;
window.addEventListener("load", () => void populate(populated), {
once: true,
});
}
}
return sheet;
}