Skip to the solution
EasyMachine Coding12 min read

Build a Dark Mode Toggle

1.1k views

The problem

Question presented to candidate: "Add a dark mode toggle to our site. On a first visit it should follow the operating system setting. If the user flips the toggle, remember their choice across reloads. Give them a way to go back to following the system. Bonus points if the page never flashes the wrong theme."

Requirements:

  • A toggle that switches between light and dark, applied to the whole page (an attribute on <html> plus CSS variables).
  • First visit: follow prefers-color-scheme, and keep following it live if the OS setting changes.
  • An explicit choice is saved to localStorage and wins over the OS setting after a reload.
  • A "Use system setting" action that forgets the saved choice.
  • Accessible toggle semantics; storage and matchMedia failures must not crash the app.

What a strong answer should cover:

  • The state model: a stored choice (light, dark or system) plus the live OS preference; the applied theme is derived from the two.
  • window.matchMedia("(prefers-color-scheme: dark)") with a change listener, cleaned up on unmount.
  • Persisting only the explicit choice, wrapped in try/catch.
  • Applying the theme with a data-theme attribute and CSS custom properties, plus color-scheme for native controls.
  • The flash of the wrong theme and the fix: a tiny inline script in <head> that sets the attribute before first paint.

Clarifying questions expected:

  • "Two states or three: is 'follow the system' a choice the user can return to?"
  • "Is the app server-rendered? That changes how we avoid the flash."
  • "Should the choice sync across open tabs?"

Code / implementation expected: Yes. A hook, composable or service plus a toggle, roughly 60-90 lines.

  • React
  • Theme
  • State

Try it yourself

Sketch your approach before you read the solution. That is what the interview tests.

Stuck? Get a hint.

A short nudge toward the approach. It will not give the answer away.

Solution

The solution is hidden so you can try first

12 min read ยท 10 sections

React solution

Every file of the working solution. Open it in the playground to run and change it.

ReactComplete solution
import { useTheme } from "./src/hooks/useTheme";

export default function App() {
  const { theme, choice, setChoice } = useTheme();
  const dark = theme === "dark";

  return (
    <main className="page">
      <header className="bar">
        <h1>Dark Mode</h1>
        <button
          type="button"
          role="switch"
          aria-checked={dark}
          aria-label="Dark mode"
          className="theme-switch"
          onClick={() => setChoice(dark ? "light" : "dark")}
        >
          <span aria-hidden="true">{dark ? "๐ŸŒ™" : "โ˜€๏ธ"}</span>
        </button>
      </header>
      <section className="card">
        <p data-testid="theme-status" aria-live="polite">
          Theme: <strong>{theme}</strong>{" "}
          {choice === "system"
            ? "(following your system)"
            : "(your choice, saved)"}
        </p>
        <button
          type="button"
          className="link"
          disabled={choice === "system"}
          onClick={() => setChoice("system")}
        >
          Use system setting
        </button>
      </section>
    </main>
  );
}

Discussion

Other approaches, follow-ups and how it went in real interviews.

Sign in to join the discussion.

No comments yet. Share how you would answer it.

Question 3 of 107 in Machine coding

Keep your momentum going.

Mark this question solved to track your progress, then take the next one while it is fresh.

Up nextEasy

Build a Generate Table (rows x columns)

Continue