Description
After PR #73 merged, the tracked-library badges on /profile/contributor-status are unreadable in dark theme — dark-green text on a dark background. The light-theme fix from #73 works correctly, but dark theme is now broken.
Root cause looks structural: the repo never declared a class-based dark variant for Tailwind CSS 4, so dark:* modifiers (including the ones I added in #73) only activate via @media (prefers-color-scheme: dark), not via the .dark class that the in-app theme toggle uses. Users whose OS is in light mode and who toggle dark theme inside the app never get the dark: overrides.
Full diagnosis and three possible fix paths are in the Additional Context section below.
Steps to Reproduce
- Make sure your OS color scheme is set to light (Windows: Settings → Personalization → Colors → Light, macOS: System Settings → Appearance → Light)
- Open https://react.foundation/profile/contributor-status while signed in
- Use the header theme toggle to switch the app to dark theme
- Scroll to "Your Contributions" → expand → "Tracked Libraries"
- Look at the badges for libraries with contributions (e.g. storybookjs/storybook, pmndrs/zustand, expo/expo, TanStack/query) and at their contribution-count chips
Expected Behavior
Tracked-library badges remain readable in both themes regardless of the user's OS color-scheme preference. The in-app theme toggle should drive badge text colors via the .dark class on <html>.
Actual Behavior
In dark theme with OS=light, the contributed-library badge text and the contribution-count chip render in text-emerald-700 / text-emerald-800 (dark green) on the dark page background — effectively invisible. The library names and counts cannot be read.
Light theme (OS=light) renders correctly thanks to PR #73. Dark theme with OS=dark also renders correctly because the media-query-based dark: variant activates from OS preference.
Only the OS=light + app=dark combination is broken, but that's a common combination (users who prefer dark UI but keep a light OS).
Environment
Production https://react.foundation, Chrome on Windows 11 (OS color scheme = light), in-app theme toggle set to dark. Verified 2026-06-03, after PR #73 (commit 51ed02a) shipped to main.
Additional Context
Diagnosis
src/app/globals.css does not declare a class-based dark variant for Tailwind CSS 4. There is no @custom-variant dark (&:where(.dark, .dark *)); (or equivalent @variant dark / legacy darkMode config) anywhere in the repo:
grep -rn "@custom-variant\|@variant dark\|darkMode" . # no matches
In Tailwind 4 the default dark variant compiles to @media (prefers-color-scheme: dark), so every dark:* modifier in the codebase only activates from the OS preference, not from the .dark class that ThemeProvider toggles on <html>.
The rest of the app survives this because most dark-mode behavior is driven through the semantic CSS variables in :root / .dark (--background, --foreground, etc.) and the prose styles in globals.css use hand-written html.dark .prose … selectors instead of dark:* utilities.
Why this regression appeared after #73
Before #73:
After #73:
- Badge text:
text-emerald-700 dark:text-emerald-200. The dark:text-emerald-200 override never kicks in for users with OS=light, so the base text-emerald-700 (dark green) leaks into dark theme — invisible on dark.
The fix in #73 was correct in intent but assumed dark: was wired to the .dark class. It is not.
The same pattern exists in other files
A quick grep shows several other components using dark:* modifiers that would silently misbehave for OS=light + app=dark users:
src/components/communities/VerificationBadge.tsx
src/components/admin/LibraryDetailModal.tsx
src/components/admin/LibraryEligibilityEditor.tsx
src/app/admin/ingest/inspect/page.tsx
src/app/admin/ingest-full/page.tsx
src/app/admin/import/page.tsx
src/app/communities/[slug]/page.tsx
These mostly hide the issue because their backgrounds use semantic tokens, but the foreground text colors are still wrong in the OS=light + app=dark combination.
Possible fix paths
(A) Wire dark: to the .dark class (one-line repo-wide fix). Add to globals.css:
@custom-variant dark (&:where(.dark, .dark *));
Smallest diff, fixes the regression in #73 and also restores the intended behavior for every other dark:* modifier in the repo. May surface previously-hidden visual differences in components that have been relying on the broken behavior — worth a quick visual check on the affected files above.
(B) Replace dark:text-emerald-* in tracked-library-badge.tsx with semantic tokens. Smallest scope, only touches the component from #73. The challenge: text-success resolves to --success (emerald-500) which is identical in both themes, and on bg-success/15 in light mode the contrast against the pale-emerald background sits around the WCAG AA edge for normal text. Workable but needs a quick contrast pass.
(C) Surgical CSS variables for the badge text. Define --badge-contributed-text and --badge-count-text in :root and .dark, then use text-[hsl(var(--badge-contributed-text))] in the component. Localized and theme-correct, but adds new variables for a single component.
Question for routing
@dougbot-agent — flagging this as a regression from PR #73. (A) is the structural fix and would also clear the silent issues in the other components listed above; (B) and (C) are scoped purely to the #73 surface. Which direction is preferred here? Happy to draft the PR once we agree on scope.
Screenshots showing the broken dark theme and the working light theme are attached below.
Acceptance Criteria
No response
Non-goals
No response
Description
After PR #73 merged, the tracked-library badges on /profile/contributor-status are unreadable in dark theme — dark-green text on a dark background. The light-theme fix from #73 works correctly, but dark theme is now broken.
Root cause looks structural: the repo never declared a class-based dark variant for Tailwind CSS 4, so
dark:*modifiers (including the ones I added in #73) only activate via@media (prefers-color-scheme: dark), not via the.darkclass that the in-app theme toggle uses. Users whose OS is in light mode and who toggle dark theme inside the app never get thedark:overrides.Full diagnosis and three possible fix paths are in the Additional Context section below.
Steps to Reproduce
Expected Behavior
Tracked-library badges remain readable in both themes regardless of the user's OS color-scheme preference. The in-app theme toggle should drive badge text colors via the
.darkclass on<html>.Actual Behavior
In dark theme with OS=light, the contributed-library badge text and the contribution-count chip render in
text-emerald-700/text-emerald-800(dark green) on the dark page background — effectively invisible. The library names and counts cannot be read.Light theme (OS=light) renders correctly thanks to PR #73. Dark theme with OS=dark also renders correctly because the media-query-based
dark:variant activates from OS preference.Only the OS=light + app=dark combination is broken, but that's a common combination (users who prefer dark UI but keep a light OS).
Environment
Production https://react.foundation, Chrome on Windows 11 (OS color scheme = light), in-app theme toggle set to dark. Verified 2026-06-03, after PR #73 (commit 51ed02a) shipped to main.
Additional Context
Diagnosis
src/app/globals.cssdoes not declare a class-based dark variant for Tailwind CSS 4. There is no@custom-variant dark (&:where(.dark, .dark *));(or equivalent@variant dark/ legacydarkModeconfig) anywhere in the repo:In Tailwind 4 the default
darkvariant compiles to@media (prefers-color-scheme: dark), so everydark:*modifier in the codebase only activates from the OS preference, not from the.darkclass thatThemeProvidertoggles on<html>.The rest of the app survives this because most dark-mode behavior is driven through the semantic CSS variables in
:root/.dark(--background,--foreground, etc.) and the prose styles inglobals.cssuse hand-writtenhtml.dark .prose …selectors instead ofdark:*utilities.Why this regression appeared after #73
Before #73:
text-emerald-200(a static class, nodark:prefix). Always rendered as light emerald — invisible on the pale-emerald light-theme background (the original bug from Bug: contributor status tracked libraries are unreadable in light theme #72), but readable on the dark-theme background.After #73:
text-emerald-700 dark:text-emerald-200. Thedark:text-emerald-200override never kicks in for users with OS=light, so the basetext-emerald-700(dark green) leaks into dark theme — invisible on dark.The fix in #73 was correct in intent but assumed
dark:was wired to the.darkclass. It is not.The same pattern exists in other files
A quick grep shows several other components using
dark:*modifiers that would silently misbehave for OS=light + app=dark users:src/components/communities/VerificationBadge.tsxsrc/components/admin/LibraryDetailModal.tsxsrc/components/admin/LibraryEligibilityEditor.tsxsrc/app/admin/ingest/inspect/page.tsxsrc/app/admin/ingest-full/page.tsxsrc/app/admin/import/page.tsxsrc/app/communities/[slug]/page.tsxThese mostly hide the issue because their backgrounds use semantic tokens, but the foreground text colors are still wrong in the OS=light + app=dark combination.
Possible fix paths
(A) Wire
dark:to the.darkclass (one-line repo-wide fix). Add toglobals.css:Smallest diff, fixes the regression in #73 and also restores the intended behavior for every other
dark:*modifier in the repo. May surface previously-hidden visual differences in components that have been relying on the broken behavior — worth a quick visual check on the affected files above.(B) Replace
dark:text-emerald-*intracked-library-badge.tsxwith semantic tokens. Smallest scope, only touches the component from #73. The challenge:text-successresolves to--success(emerald-500) which is identical in both themes, and onbg-success/15in light mode the contrast against the pale-emerald background sits around the WCAG AA edge for normal text. Workable but needs a quick contrast pass.(C) Surgical CSS variables for the badge text. Define
--badge-contributed-textand--badge-count-textin:rootand.dark, then usetext-[hsl(var(--badge-contributed-text))]in the component. Localized and theme-correct, but adds new variables for a single component.Question for routing
@dougbot-agent — flagging this as a regression from PR #73. (A) is the structural fix and would also clear the silent issues in the other components listed above; (B) and (C) are scoped purely to the #73 surface. Which direction is preferred here? Happy to draft the PR once we agree on scope.
Screenshots showing the broken dark theme and the working light theme are attached below.
Acceptance Criteria
No response
Non-goals
No response