Skip to content

bug: two conflicting dark modes — CSS variable dark mode and Tailwind dark: utilities produce different backgrounds #693

@magic-peach

Description

@magic-peach

Bug Description

Reframe currently renders two visually distinct dark modes depending on which code path applies the theme. The two screenshots below show the same page in dark mode but with noticeably different background colours:

  • Dark mode A — deep black/navy (matches the CSS variable --bg: #0f172a defined in globals.css)
  • Dark mode B — lighter charcoal/slate gray (appears to come from Tailwind dark:bg-* utility classes overriding or bypassing the CSS variable system)

This inconsistency makes the app look broken and unpolished. The upload card, the output size panel, and the preset grid all shift noticeably between the two states.

Root Cause (suspected)

The project defines dark mode via a CSS class strategy in src/app/globals.css:

.dark {
  --bg: #0f172a;
  --surface: #1e293b;
  --border: #334155;
  --text: #f1f5f9;
  --muted: #94a3b8;
  --accent: #3b82f6;
}

However, several components likely use Tailwind dark: utility classes (e.g. dark:bg-slate-900, dark:bg-gray-800) which use Tailwind's own dark mode detection and do not read from the CSS variables. When both systems are active, they produce different shades, causing the split appearance.

Additionally, the ThemeProvider in src/components/ThemeProvider.tsx may be toggling the dark class on <html> or <body> inconsistently, or there may be a race condition between the server-rendered class and the client-side hydration.

Steps to Reproduce

  1. Clone the repo and run bun run dev
  2. Toggle dark mode using the theme toggle button
  3. Toggle back and forth several times
  4. Observe that the background shade changes between two distinct values

Also compare: hard-refresh in dark mode vs. toggling from light → dark — the initial render may use a different shade than the post-toggle render.

Expected Behaviour

One single, consistent dark background throughout the entire UI. All components should read from the CSS variable var(--bg) and var(--surface), not hard-coded Tailwind dark: values.

What to Fix

  1. Audit all components in src/components/ for Tailwind dark:bg-*, dark:text-*, dark:border-* utilities — replace every one with the equivalent CSS variable token:
Replace With
dark:bg-slate-900 / dark:bg-gray-900 bg-[var(--bg)]
dark:bg-slate-800 / dark:bg-gray-800 bg-[var(--surface)]
dark:text-white / dark:text-slate-100 text-[var(--text)]
dark:text-slate-400 text-[var(--muted)]
dark:border-slate-700 border-[var(--border)]
  1. Verify ThemeProvider — ensure the dark class is only ever toggled on the <html> element, and that the initial class is set synchronously before first paint (to avoid a flash of wrong theme).

  2. Remove any duplicate theme toggling logic — there should be exactly one source of truth for the theme state.

Files to Check

  • src/components/ThemeProvider.tsx
  • src/components/ThemeToggle.tsx
  • src/app/globals.css
  • src/app/layout.tsx
  • All component files in src/components/

Acceptance Criteria

  • Toggling dark mode always produces the exact same background shade (#0f172a for --bg)
  • No Tailwind dark: utilities remain in component files — all colours come from CSS variables
  • Hard refresh in dark mode and toggle from light → dark produce identical appearance
  • Both light and dark modes look correct after the fix
  • bun run lint and bunx tsc --noEmit pass

Screen Recording Required

Your PR for this issue must include a screen recording showing dark mode toggling consistently on your local machine (bun run devhttp://localhost:3000) — record toggling light → dark → light → dark several times to prove the background shade is stable.

See CONTRIBUTING.md for how to record on your OS.

Metadata

Metadata

Assignees

Labels

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions