Skip to content

Commit 36f480d

Browse files
committed
🤖 fix: use useLayoutEffect for synchronous theme sync in Storybook
Root cause: Writing to localStorage in decorator was causing persistence issues. Also, synchronous document writes bypassed ThemeProvider. Fix: - Use ThemeStorySync component with useLayoutEffect (not useEffect) - useLayoutEffect runs synchronously before paint, preventing flashes - Let ThemeProvider manage localStorage, don't write in decorator - Chromatic modes will trigger ThemeStorySync with correct mode This should fix the issue where both dark and light mode stories were rendering in dark mode.
1 parent d32f711 commit 36f480d

File tree

1 file changed

+19
-13
lines changed

1 file changed

+19
-13
lines changed

.storybook/preview.tsx

Lines changed: 19 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,24 @@
1-
import React from "react";
1+
import React, { useLayoutEffect } from "react";
22
import type { Preview } from "@storybook/react-vite";
3-
import { ThemeProvider, type ThemeMode } from "../src/browser/contexts/ThemeContext";
4-
import { UI_THEME_KEY } from "../src/common/constants/storage";
3+
import {
4+
ThemeProvider,
5+
useTheme,
6+
type ThemeMode,
7+
} from "../src/browser/contexts/ThemeContext";
58
import "../src/browser/styles/globals.css";
69

10+
const ThemeStorySync: React.FC<{ mode: ThemeMode }> = ({ mode }) => {
11+
const { theme, setTheme } = useTheme();
12+
13+
useLayoutEffect(() => {
14+
if (theme !== mode) {
15+
setTheme(mode);
16+
}
17+
}, [mode, setTheme, theme]);
18+
19+
return null;
20+
};
21+
722
const preview: Preview = {
823
globalTypes: {
924
theme: {
@@ -23,18 +38,9 @@ const preview: Preview = {
2338
decorators: [
2439
(Story, context) => {
2540
const mode = (context.globals.theme ?? "dark") as ThemeMode;
26-
27-
// Apply theme synchronously BEFORE React renders
28-
// This ensures Chromatic snapshots capture the correct theme without timing issues
29-
if (typeof window !== "undefined") {
30-
const serialized = JSON.stringify(mode);
31-
window.localStorage.setItem(UI_THEME_KEY, serialized);
32-
document.documentElement.dataset.theme = mode;
33-
document.documentElement.style.colorScheme = mode;
34-
}
35-
3641
return (
3742
<ThemeProvider>
43+
<ThemeStorySync mode={mode} />
3844
<Story />
3945
</ThemeProvider>
4046
);

0 commit comments

Comments
 (0)