Skip to content

Commit dbb458c

Browse files
committed
original but with a preview-head.html
1 parent 5e375d1 commit dbb458c

File tree

2 files changed

+33
-25
lines changed

2 files changed

+33
-25
lines changed

.storybook/preview.tsx

Lines changed: 22 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,30 @@
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";
3+
import {
4+
ThemeProvider,
5+
useTheme,
6+
type ThemeMode,
7+
} from "../src/browser/contexts/ThemeContext";
48
import "../src/browser/styles/globals.css";
59

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+
622
const preview: Preview = {
723
globalTypes: {
824
theme: {
925
name: "Theme",
1026
description: "Choose between light and dark UI themes",
27+
defaultValue: "dark",
1128
toolbar: {
1229
icon: "mirror",
1330
items: [
@@ -20,10 +37,10 @@ const preview: Preview = {
2037
},
2138
decorators: [
2239
(Story, context) => {
23-
const mode = context.globals.theme as ThemeMode | undefined;
24-
40+
const mode = (context.globals.theme ?? "dark") as ThemeMode;
2541
return (
26-
<ThemeProvider forcedTheme={mode}>
42+
<ThemeProvider>
43+
<ThemeStorySync mode={mode} />
2744
<Story />
2845
</ThemeProvider>
2946
);

src/browser/contexts/ThemeContext.tsx

Lines changed: 11 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -51,35 +51,26 @@ function applyThemeToDocument(theme: ThemeMode) {
5151
}
5252
}
5353

54-
export function ThemeProvider(props: { children: ReactNode; forcedTheme?: ThemeMode }) {
55-
const [persistedTheme, setPersistedTheme] = usePersistedState<ThemeMode>(
56-
UI_THEME_KEY,
57-
resolveSystemTheme(),
58-
{
59-
listener: !props.forcedTheme, // Disable listener when theme is forced
60-
}
61-
);
62-
63-
const activeTheme = props.forcedTheme ?? persistedTheme;
54+
export function ThemeProvider(props: { children: ReactNode }) {
55+
const [theme, setTheme] = usePersistedState<ThemeMode>(UI_THEME_KEY, resolveSystemTheme(), {
56+
listener: true,
57+
});
6458

6559
useLayoutEffect(() => {
66-
applyThemeToDocument(activeTheme);
67-
}, [activeTheme]);
60+
applyThemeToDocument(theme);
61+
}, [theme]);
6862

6963
const toggleTheme = useCallback(() => {
70-
// Only allow toggling when not forced
71-
if (!props.forcedTheme) {
72-
setPersistedTheme((current) => (current === "dark" ? "light" : "dark"));
73-
}
74-
}, [props.forcedTheme, setPersistedTheme]);
64+
setTheme((current) => (current === "dark" ? "light" : "dark"));
65+
}, [setTheme]);
7566

7667
const value = useMemo<ThemeContextValue>(
7768
() => ({
78-
theme: activeTheme,
79-
setTheme: setPersistedTheme,
69+
theme,
70+
setTheme,
8071
toggleTheme,
8172
}),
82-
[activeTheme, setPersistedTheme, toggleTheme]
73+
[setTheme, theme, toggleTheme]
8374
);
8475

8576
return <ThemeContext.Provider value={value}>{props.children}</ThemeContext.Provider>;

0 commit comments

Comments
 (0)