Skip to content

[dark mode] avoid FoUC on first render#6881

Merged
ckifer merged 3 commits intorecharts:mainfrom
cloud-walker:avoid-fouc-dark-mode
Jan 13, 2026
Merged

[dark mode] avoid FoUC on first render#6881
ckifer merged 3 commits intorecharts:mainfrom
cloud-walker:avoid-fouc-dark-mode

Conversation

@cloud-walker
Copy link
Contributor

@cloud-walker cloud-walker commented Jan 13, 2026

Description

At the moment the dark mode suffers from FoUC, to fix, I had to duplicated some logic unfortunately.

Related Issue

#6825

Motivation and Context

FoUC on first render

How Has This Been Tested?

Manually

Screenshots (if appropriate):

Types of changes

  • Bug fix (non-breaking change which fixes an issue)
  • New feature (non-breaking change which adds functionality)
  • Breaking change (fix or feature that would cause existing functionality to change)

Checklist:

  • My change requires a change to the documentation.
  • I have updated the documentation accordingly.
  • I have added tests to cover my changes.
  • I have added a storybook story or VR test, or extended an existing story or VR test to show my changes

Summary by CodeRabbit

  • Chores

    • Initialize color mode early on page load to prevent a flash of wrong theme, using stored preference or OS setting.
  • Documentation

    • Added notes indicating duplication of the color-mode initialization logic to keep implementations in sync and aid future updates.

✏️ Tip: You can customize this high-level summary in your review settings.

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Jan 13, 2026

Walkthrough

Adds an inline script to www/index.html that sets data-mode on the document root at load by reading localStorage (recharts-color-mode) or falling back to OS prefers-color-scheme; also adds JSDoc comments in the color-mode store noting duplication to prevent FOUC and keep behavior in sync.

Changes

Cohort / File(s) Summary
Color Mode Initialization Script
www/index.html
Added inline IIFE that on load reads recharts-color-mode from localStorage or falls back to window.matchMedia('(prefers-color-scheme: dark)') and sets document.documentElement.dataset.mode. Wrapped in try/catch. Comment notes duplication with store.
Store Documentation
www/src/components/color-mode/defineColorModeStore.ts
Added JSDoc-style notes indicating duplication with the inline HTML script to avoid FOUC and to keep both implementations synchronized. No logic changes.

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~10 minutes

Possibly related PRs

  • docs: dark mode #6828: Introduced the color-mode store and related DOM data-mode logic that this PR mirrors in an inline HTML script to prevent FOUC.

Suggested reviewers

  • ckifer
  • PavelVanecek
🚥 Pre-merge checks | ✅ 2 | ❌ 1
❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 33.33% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly and concisely describes the main change: avoiding FoUC (Flash of Unstyled Content) on first render in dark mode, which aligns with the changeset's core objective.
Description check ✅ Passed The description covers all major template sections including motivation (FoUC issue), related issue (#6825), testing approach (manual), and correctly identifies this as a bug fix. All critical sections are present and filled.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.


📜 Recent review details

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 068bfd7 and 2274133.

📒 Files selected for processing (1)
  • www/index.html
🚧 Files skipped from review as they are similar to previous changes (1)
  • www/index.html
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: Build, Test, Pack

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@codecov
Copy link

codecov bot commented Jan 13, 2026

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 94.27%. Comparing base (9bd3552) to head (2274133).
⚠️ Report is 5 commits behind head on main.

Additional details and impacted files
@@           Coverage Diff           @@
##             main    #6881   +/-   ##
=======================================
  Coverage   94.27%   94.27%           
=======================================
  Files         561      561           
  Lines       53641    53641           
  Branches     5178     5178           
=======================================
  Hits        50571    50571           
  Misses       3061     3061           
  Partials        9        9           

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@cloud-walker cloud-walker marked this pull request as ready for review January 13, 2026 18:34
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Fix all issues with AI agents
In @www/index.html:
- Around line 14-18: The script reads
localStorage.getItem('recharts-color-mode') into storedMode but uses it
directly, which can be invalid; update the logic that sets mode (the var
storedMode / var mode block) to validate storedMode === 'light' || storedMode
=== 'dark' and only use it when valid, otherwise compute mode from
window.matchMedia('(prefers-color-scheme: dark)').matches ? 'dark' : 'light';
then set document.documentElement.setAttribute('data-mode', mode) as before.
📜 Review details

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 4298cd8 and 068bfd7.

📒 Files selected for processing (2)
  • www/index.html
  • www/src/components/color-mode/defineColorModeStore.ts
🧰 Additional context used
📓 Path-based instructions (2)
**/*.{ts,tsx}

📄 CodeRabbit inference engine (CONTRIBUTING.md)

**/*.{ts,tsx}: Never use any type (implicit or explicit) in TypeScript code
Prefer unknown over any and refine the type in TypeScript
Type function parameters and return values explicitly in TypeScript, do not rely on implicit any or inference; exceptions are React components and trivial functions
Do not use as type assertions in TypeScript; the only exception is as const

All imports from recharts must use the public API entry point (e.g., import { TooltipIndex } from 'recharts'). Imports from internal paths like recharts/types/* or recharts/src/* are not allowed and will fail the linter.

Files:

  • www/src/components/color-mode/defineColorModeStore.ts
**/*.{js,ts,tsx}

📄 CodeRabbit inference engine (CONTRIBUTING.md)

Ensure code lints by running npm run lint and follows Airbnb's Style Guide

Files:

  • www/src/components/color-mode/defineColorModeStore.ts
🧠 Learnings (1)
📚 Learning: 2025-11-16T09:14:24.918Z
Learnt from: PavelVanecek
Repo: recharts/recharts PR: 6640
File: src/cartesian/Bar.tsx:156-159
Timestamp: 2025-11-16T09:14:24.918Z
Learning: In recharts, SSR (Server-Side Rendering) is not yet supported—charts don't render at all in SSR environments. The `isAnimationActive: 'auto'` mode is preparatory work for future SSR support, so testing of this mode should be deferred until SSR support is actually implemented.

Applied to files:

  • www/index.html
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: Build, Test, Pack
🔇 Additional comments (2)
www/src/components/color-mode/defineColorModeStore.ts (1)

9-12: LGTM! Helpful duplication notes added.

The JSDoc comments clearly document the intentional duplication with index.html and remind future maintainers to keep both locations in sync. This is good practice for avoiding FOUC-related bugs during refactoring.

Also applies to: 55-58

www/index.html (1)

8-23: Effective approach to prevent FOUC.

Placing the color mode initialization script in <head> as a blocking script ensures the correct data-mode attribute is set before any CSS is applied, effectively preventing the flash of unstyled content. The IIFE pattern and try/catch wrapper are appropriate for this use case.

@ckifer ckifer merged commit 70df1a6 into recharts:main Jan 13, 2026
39 checks passed
@cloud-walker cloud-walker deleted the avoid-fouc-dark-mode branch January 13, 2026 20:45
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.

2 participants