Add Dark Mode Toggle
Implement a persistent dark mode switch in the existing app.
The route
6 steps to Done
- 01
Create Theme Context
Provide global theme state and toggle function.
Preview prompt + verify gate ▾ Hide ▴
Create a new file src/theme/ThemeContext.{js,tsx} that: 1. Imports createContext, useState, useEffect from React. 2. Defines a ThemeContext via createContext({ theme: 'light', toggleTheme: () => {} }). 3. Exports a ThemeProvider component that: a. Initializes theme state from localStorage key 'appTheme' (fallback 'light'). b. Provides toggleTheme that switches between 'light' and 'dark', updates state, and writes the new value to localStorage. c. Wraps its children with ThemeContext.Provider passing { theme, toggleTheme }. 4. Export both ThemeContext and ThemeProvider. Ensure no JSX placeholders; actual functional code only.
- ✓ Can the app import { ThemeProvider } without syntax errors?
- ✓ Does localStorage.getItem('appTheme') return a value on first load?
- ✓ Does calling toggleTheme switch the stored value between 'light' and 'dark'?
- 02
Define Light/Dark CSS Variables
Enable UI styling based on the theme value.
Preview prompt + verify gate ▾ Hide ▴
In the main stylesheet (e.g., src/index.css or src/global.scss): 1. Define CSS variables inside :root for --bg-color, --text-color, etc., using light theme defaults. 2. Create a .dark selector that redefines those variables with dark theme values. 3. Ensure the stylesheet is imported at the app root. 4. Do not include any placeholder comments; provide concrete color values.
- ✓ Inspect compiled CSS: does .dark change background color?
- ✓ Changing the <html> or <body> class to 'dark' updates variables?
- 03
Build DarkModeToggle Component
Provide UI for users to switch themes.
Preview prompt + verify gate ▾ Hide ▴
In src/components/DarkModeToggle.{js,tsx}: 1. Import React, useContext, and ThemeContext. 2. Render a button showing an icon or text indicating the current theme (e.g., ☀️ for light, 🌙 for dark). 3. On click, invoke toggleTheme from context. 4. Export the component as default. 5. Do not include placeholder UI; provide real button markup.
- ✓ Can import DarkModeToggle without errors?
- ✓ Clicking the button flips the theme value in context?
- 04
Apply Theme Class at Root
Bind the CSS dark class to the current theme state.
Preview prompt + verify gate ▾ Hide ▴
In src/index.js (or wherever <App/> is rendered): 1. Import ThemeProvider and ThemeContext. 2. Wrap <App/> with <ThemeProvider>. 3. Inside a top‑level component (e.g., App or a Layout), use useContext(ThemeContext) to get theme. 4. Apply className={theme === 'dark' ? 'dark' : ''} to the topmost <div> that contains the app. 5. Ensure the class updates instantly on toggle. 6. No placeholder comments; fully functional code.
- ✓ Inspect DOM after toggle: does <div> have class 'dark'?
- ✓ Background color changes correspond to CSS variables?
- 05
Integrate Toggle into UI
Place the DarkModeToggle where users can access it.
Preview prompt + verify gate ▾ Hide ▴
In src/components/Header.{js,tsx}: 1. Import DarkModeToggle. 2. Add <DarkModeToggle /> to the JSX, preferably on the right side of the header. 3. Ensure the header still renders correctly and the toggle is visible. 4. No placeholder comments; component must be used in real JSX.
- ✓ Is the toggle visible in the header?
- ✓ Does clicking it change the theme instantly?
- 06
Validate Persistence Across Sessions
Ensure the chosen theme remains after page reloads.
Preview prompt + verify gate ▾ Hide ▴
Manually test the app: 1. Click DarkModeToggle to switch to dark mode. 2. Observe the root element gains 'dark' class. 3. Refresh the browser. 4. Verify that the 'dark' class is still present and the UI remains dark. 5. Repeat for light mode. 6. No code to write; just produce a verification script. If you prefer automated verification, add a small test in src/__tests__/theme.test.{js,tsx} that: - Mocks localStorage, renders the app, toggles theme, unmounts, re-renders, and asserts the persisted value.
- ✓ localStorage.getItem('appTheme') matches UI theme after reload
- ✓ Automated test suite reports PASS for theme persistence