mirror of
https://github.com/webstudio-is/webstudio.git
synced 2026-11-09 14:03:33 +09:00
## Description
Fixes Error in dev mode on every start or reload
```
react-dom.development.js:67 Warning: Prop `className` did not match. Server: "null" Client: "t-doScVt"
at html
at Root (http://localhost:3000/build/_shared/chunk-TNFZIIN2.js:36:22)
```
It works because of bug, now without bug it shows
https://github.com/webstudio-is/webstudio-builder/pull/1408
I would comment usetEffect for now
## Steps for reproduction
Run localy, see Error has gone
## Code Review
- [ ] hi @kof, I need you to do
- conceptual review (architecture, feature-correctness)
- detailed review (read every line)
- test it on preview
## Before requesting a review
- [ ] made a self-review
- [ ] added inline comments where things may be not obvious (the "why", not "what")
## Before merging
- [ ] tested locally and on preview environment (preview dev login: 5de6)
- [ ] updated [test cases](https://github.com/webstudio-is/webstudio-builder/blob/main/apps/builder/docs/test-cases.md) document
- [ ] added tests
- [ ] if any new env variables are added, added them to `.env.example` and the `builder/env-check.js` if mandatory
112 lines
2.8 KiB
TypeScript
112 lines
2.8 KiB
TypeScript
import { useLoaderData } from "@remix-run/react";
|
|
import { isFeatureEnabled } from "@webstudio-is/feature-flags";
|
|
import { darkTheme } from "@webstudio-is/design-system";
|
|
import { restThemePath } from "~/shared/router-utils";
|
|
import type { ColorScheme, ThemeSetting } from "./types";
|
|
import { useState } from "react";
|
|
|
|
// User selected theme setting.
|
|
let setting: ThemeSetting = isFeatureEnabled("dark") ? "system" : "light";
|
|
// Current systeme theme.
|
|
let system: ColorScheme;
|
|
|
|
/**
|
|
* Subscribes color scheme change event and rerenders
|
|
*/
|
|
const subscribeSystemTheme = () => {
|
|
if (typeof matchMedia === "undefined") {
|
|
return;
|
|
}
|
|
const query = matchMedia("(prefers-color-scheme: light)");
|
|
const queryColorScheme = (query: MediaQueryList | MediaQueryListEvent) =>
|
|
query.matches ? "light" : "dark";
|
|
|
|
system = queryColorScheme(query);
|
|
|
|
query.addEventListener("change", (queryEvent) => {
|
|
system = queryColorScheme(queryEvent);
|
|
renderThemeProps();
|
|
});
|
|
};
|
|
|
|
subscribeSystemTheme();
|
|
|
|
const fallbackTheme = "light";
|
|
|
|
/**
|
|
* Logic we use to decide depending on user setting which color scheme to use.
|
|
*/
|
|
const getColorScheme = (): ColorScheme => {
|
|
if (setting === "system") {
|
|
return system || fallbackTheme;
|
|
}
|
|
return setting || fallbackTheme;
|
|
};
|
|
|
|
/**
|
|
* When switching theme we need to apply the class/style manually.
|
|
*/
|
|
const renderThemeProps = () => {
|
|
const theme = getColorScheme();
|
|
const root = document.documentElement;
|
|
theme === "dark"
|
|
? root.classList.add(darkTheme.className)
|
|
: root.classList.remove(darkTheme.className);
|
|
root.style.colorScheme = theme;
|
|
root.dataset.theme = theme;
|
|
};
|
|
|
|
/**
|
|
* Apply immediately and set the cookie on the server.
|
|
*/
|
|
export const setThemeSetting = (nextSetting: ThemeSetting) => {
|
|
setting = nextSetting;
|
|
renderThemeProps();
|
|
fetch(restThemePath({ setting }));
|
|
};
|
|
|
|
/**
|
|
* Returns the class and style to applied to some root node serverside and during hydration.
|
|
*/
|
|
export const useThemeProps = () => {
|
|
const data = useLoaderData();
|
|
if (data.theme.setting) {
|
|
setting = data.theme.setting;
|
|
}
|
|
if (data.theme.system) {
|
|
system = data.theme.system;
|
|
}
|
|
|
|
const [themeProps] = useState<{
|
|
className: string | undefined;
|
|
style: { colorScheme: ColorScheme };
|
|
"data-theme": ColorScheme;
|
|
}>({
|
|
className: undefined,
|
|
style: { colorScheme: "light" },
|
|
"data-theme": "light",
|
|
});
|
|
|
|
/*
|
|
// @todo uncomment when we will decide to use theme
|
|
useEffect(() => {
|
|
const theme = getColorScheme();
|
|
|
|
setThemeProps(() => ({
|
|
className: theme === "dark" ? darkTheme.className : undefined,
|
|
style: { colorScheme: theme },
|
|
"data-theme": theme,
|
|
}));
|
|
}, []);
|
|
*/
|
|
|
|
return themeProps;
|
|
};
|
|
|
|
/**
|
|
* Currently selected by user theme setting.
|
|
*/
|
|
export const getThemeSetting = (): ThemeSetting => {
|
|
return setting;
|
|
};
|