Skip to content

fix(cli): sync scaffold dark mode so ui-* components follow the theme#101

Merged
vivek7405 merged 2 commits into
mainfrom
fix/scaffold-dark-mode-shadcn-sync
May 25, 2026
Merged

fix(cli): sync scaffold dark mode so ui-* components follow the theme#101
vivek7405 merged 2 commits into
mainfrom
fix/scaffold-dark-mode-shadcn-sync

Conversation

@vivek7405
Copy link
Copy Markdown
Collaborator

Bug

In a default-scaffolded app, the dark theme is broken for every copied components/ui/* component. The reported symptom: the "View docs" (outline) button renders white-on-light (invisible text) in dark mode; light mode is fine.

Root cause

The scaffold ships two unsynced theme systems:

  • Editorial chrome (--fg/--bg, dark-by-default) toggled via a data-theme attribute on <html>.
  • shadcn ui- components* (--background/--foreground/etc.) whose dark tokens key off a .dark class (@custom-variant dark (&:is(.dark *))).

Neither the head init script nor the theme-toggle ever set a .dark class, so the shadcn tokens were permanently stuck in light mode. On the dark chrome that means bg-background = white, etc. Reproduced in a browser (emulated dark):

element before (dark) after
View docs (outline) bg oklch(1 0 0) white, light text → invisible input/30 tint + light text → readable
card bg white, dark text → white box bg 0.205 dark, light text

Light mode only "worked" because both systems happened to be light.

Fix

The head init script and theme-toggle.cycle() now toggle a .dark class in sync with the effective theme (dark by default unless the OS prefers light or light is chosen), and the head script re-applies on OS theme changes. The data-theme chrome mechanism is unchanged; .dark just drives the shadcn tokens alongside it.

Verification

Browser-tested against a live scaffolded app (/usr/bin/chromium, emulated dark + light):

  • Dark: .dark now present; outline button + card + alert + badge render dark-correct (screenshot reviewed).
  • Light: unchanged, all correct.
  • npm test green via pre-commit hook (1151/1151).

Follow-up note (not in this PR)

Minor secondary gap: the scaffold chrome's --accent (brand orange) and shadcn's --accent collide by name, so ui-* hover states (hover:bg-accent) use the orange instead of shadcn's accent. Hover-only and arguably acceptable as a brand accent; flagging for a separate decision.

vivek7405 added 2 commits May 25, 2026 15:51
The default scaffold shipped two unsynced theme systems: the editorial
chrome tokens (--fg/--bg) toggled via a `data-theme` attribute, while
the copied shadcn ui-* components (button, card, alert, etc.) key their
dark tokens off a `.dark` class (`@custom-variant dark (&:is(.dark *))`).
Nothing ever set `.dark`, so every ui component was frozen in light
tokens. On the dark-default chrome this rendered, e.g., the outline
"View docs" button as white-on-light (invisible text) and cards as
white boxes. Light mode looked fine only because both systems were
light then.

Fix: the head init script and the theme-toggle now toggle a `.dark`
class in sync with the effective theme (dark by default unless the OS
prefers light or 'light' is chosen), and the head script re-applies on
OS theme changes. The chrome's `data-theme` mechanism is unchanged; the
`.dark` class simply drives the shadcn tokens alongside it.

Verified in a browser (emulated dark): outline button now renders with
the dark input tint + light text, cards render dark, and light mode is
unchanged.
Codify why dark mode broke while light worked so it can't recur silently:

- agent-docs/styling.md: new "Dark mode" section explaining the two
  theming signals (data-theme for the editorial chrome, .dark class for
  the Webjs UI kit), that a theme switch must drive both, and that light
  mode passing proves nothing about dark mode.
- agent-docs/testing.md: a "Verifying UI and theming" note: render in a
  real browser, test both themes, inspect computed styles, read the
  screenshot, and guard the wiring in a fast test.
- test/scaffolds/scaffold-integration.test.js: assert the generated
  layout head script AND theme-toggle both toggle the `.dark` class, so
  the sync mechanism can't regress unnoticed.
- templates/CONVENTIONS.md: a scaffolded-app note mirroring the
  dual-signal rule for agents working inside a user app.
@vivek7405 vivek7405 merged commit f0a1fa1 into main May 25, 2026
@vivek7405 vivek7405 deleted the fix/scaffold-dark-mode-shadcn-sync branch May 25, 2026 11:52
vivek7405 added a commit that referenced this pull request May 25, 2026
Ship the scaffold dark-mode fix (#101): newly scaffolded apps now sync
the shadcn `.dark` class with the theme, so ui-* components render
correctly in dark mode.

create-webjs and webjsdev lockstep to 0.9.1 via the release workflow.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant