Refactor theming (#497)

This commit is contained in:
1ilit
2025-06-18 16:08:12 +04:00
committed by GitHub
parent a62721bc55
commit 3ea88314eb
9 changed files with 36 additions and 67 deletions

View File

@@ -5,7 +5,6 @@ import BugReport from "./pages/BugReport";
import Templates from "./pages/Templates"; import Templates from "./pages/Templates";
import LandingPage from "./pages/LandingPage"; import LandingPage from "./pages/LandingPage";
import SettingsContextProvider from "./context/SettingsContext"; import SettingsContextProvider from "./context/SettingsContext";
import { useSettings } from "./hooks";
import NotFound from "./pages/NotFound"; import NotFound from "./pages/NotFound";
export default function App() { export default function App() {
@@ -15,22 +14,8 @@ export default function App() {
<RestoreScroll /> <RestoreScroll />
<Routes> <Routes>
<Route path="/" element={<LandingPage />} /> <Route path="/" element={<LandingPage />} />
<Route <Route path="/editor" element={<Editor />} />
path="/editor" <Route path="/bug-report" element={<BugReport />} />
element={
<ThemedPage>
<Editor />
</ThemedPage>
}
/>
<Route
path="/bug-report"
element={
<ThemedPage>
<BugReport />
</ThemedPage>
}
/>
<Route path="/templates" element={<Templates />} /> <Route path="/templates" element={<Templates />} />
<Route path="*" element={<NotFound />} /> <Route path="*" element={<NotFound />} />
</Routes> </Routes>
@@ -39,29 +24,6 @@ export default function App() {
); );
} }
function ThemedPage({ children }) {
const { setSettings } = useSettings();
useLayoutEffect(() => {
const theme = localStorage.getItem("theme");
if (theme === "dark") {
setSettings((prev) => ({ ...prev, mode: "dark" }));
const body = document.body;
if (body.hasAttribute("theme-mode")) {
body.setAttribute("theme-mode", "dark");
}
} else {
setSettings((prev) => ({ ...prev, mode: "light" }));
const body = document.body;
if (body.hasAttribute("theme-mode")) {
body.setAttribute("theme-mode", "light");
}
}
}, [setSettings]);
return children;
}
function RestoreScroll() { function RestoreScroll() {
const location = useLocation(); const location = useLocation();
useLayoutEffect(() => { useLayoutEffect(() => {

View File

@@ -708,15 +708,13 @@ export default function Canvas() {
{ passive: false }, { passive: false },
); );
const theme = localStorage.getItem("theme");
return ( return (
<div className="grow h-full touch-none" id="canvas"> <div className="grow h-full touch-none" id="canvas">
<div <div
className="w-full h-full" className="w-full h-full"
style={{ style={{
cursor: pointer.style, cursor: pointer.style,
backgroundColor: theme === "dark" ? darkBgTheme : "white", backgroundColor: settings.mode === "dark" ? darkBgTheme : "white",
}} }}
> >
<svg <svg

View File

@@ -36,8 +36,6 @@ export default function Relationship({ data }) {
}; };
}, [tables, data]); }, [tables, data]);
const theme = localStorage.getItem("theme");
const pathRef = useRef(); const pathRef = useRef();
const labelRef = useRef(); const labelRef = useRef();
@@ -134,14 +132,14 @@ export default function Relationship({ data }) {
<rect <rect
x={labelX - 2} x={labelX - 2}
y={labelY - labelFontSize} y={labelY - labelFontSize}
fill={theme === "dark" ? darkBgTheme : "white"} fill={settings.mode === "dark" ? darkBgTheme : "white"}
width={labelWidth + 4} width={labelWidth + 4}
height={labelHeight} height={labelHeight}
/> />
<text <text
x={labelX} x={labelX}
y={labelY} y={labelY}
fill={theme === "dark" ? "lightgrey" : "#333"} fill={settings.mode === "dark" ? "lightgrey" : "#333"}
fontSize={labelFontSize} fontSize={labelFontSize}
fontWeight={500} fontWeight={500}
ref={labelRef} ref={labelRef}

View File

@@ -1357,25 +1357,11 @@ export default function ControlPanel({
children: [ children: [
{ {
name: t("light"), name: t("light"),
function: () => { function: () => setSettings((prev) => ({ ...prev, mode: "light" })),
const body = document.body;
if (body.hasAttribute("theme-mode")) {
body.setAttribute("theme-mode", "light");
}
localStorage.setItem("theme", "light");
setSettings((prev) => ({ ...prev, mode: "light" }));
},
}, },
{ {
name: t("dark"), name: t("dark"),
function: () => { function: () => setSettings((prev) => ({ ...prev, mode: "dark" })),
const body = document.body;
if (body.hasAttribute("theme-mode")) {
body.setAttribute("theme-mode", "dark");
}
localStorage.setItem("theme", "dark");
setSettings((prev) => ({ ...prev, mode: "dark" }));
},
}, },
], ],
function: () => {}, function: () => {},

View File

@@ -28,6 +28,10 @@ export default function SettingsContextProvider({ children }) {
} }
}, []); }, []);
useEffect(() => {
document.body.setAttribute("theme-mode", settings.mode);
}, [settings.mode]);
useEffect(() => { useEffect(() => {
localStorage.setItem("settings", JSON.stringify(settings)); localStorage.setItem("settings", JSON.stringify(settings));
}, [settings]); }, [settings]);

View File

@@ -12,3 +12,4 @@ export { default as useTransform } from "./useTransform";
export { default as useTypes } from "./useTypes"; export { default as useTypes } from "./useTypes";
export { default as useUndoRedo } from "./useUndoRedo"; export { default as useUndoRedo } from "./useUndoRedo";
export { default as useEnums } from "./useEnums"; export { default as useEnums } from "./useEnums";
export { default as useThemedPage } from "./useThemedPage";

View File

@@ -0,0 +1,13 @@
import { useLayoutEffect } from "react";
import useSettings from "./useSettings";
/**
* Adds the `theme-mode` attribute to the body element for semi-ui dark theme
*/
export default function useThemedPage() {
const { settings } = useSettings();
useLayoutEffect(() => {
document.body.setAttribute("theme-mode", settings.mode);
}, [settings]);
}

View File

@@ -12,6 +12,7 @@ import { CLEAR_EDITOR_COMMAND } from "lexical";
import { Link } from "react-router-dom"; import { Link } from "react-router-dom";
import { socials } from "../data/socials"; import { socials } from "../data/socials";
import { send } from "../api/email"; import { send } from "../api/email";
import { useSettings, useThemedPage } from "../hooks";
function Form({ theme }) { function Form({ theme }) {
const [editor] = useLexicalComposerContext(); const [editor] = useLexicalComposerContext();
@@ -85,7 +86,7 @@ function Form({ theme }) {
value={data.title} value={data.title}
onChange={(v) => setData((prev) => ({ ...prev, title: v }))} onChange={(v) => setData((prev) => ({ ...prev, title: v }))}
/> />
<RichEditor theme={theme} placeholder={"Describe the bug"} /> <RichEditor theme={theme} placeholder="Describe the bug" />
<Upload <Upload
action="#" action="#"
ref={uploadRef} ref={uploadRef}
@@ -123,13 +124,16 @@ function Form({ theme }) {
} }
export default function BugReport() { export default function BugReport() {
const [theme, setTheme] = useState(""); const {
settings: { mode: theme },
} = useSettings();
useEffect(() => { useEffect(() => {
setTheme(localStorage.getItem("theme"));
document.title = "Report a bug | drawDB"; document.title = "Report a bug | drawDB";
document.body.setAttribute("class", "theme"); document.body.setAttribute("class", "theme");
}, [setTheme]); }, []);
useThemedPage();
return ( return (
<> <>

View File

@@ -10,8 +10,11 @@ import TasksContextProvider from "../context/TasksContext";
import SaveStateContextProvider from "../context/SaveStateContext"; import SaveStateContextProvider from "../context/SaveStateContext";
import EnumsContextProvider from "../context/EnumsContext"; import EnumsContextProvider from "../context/EnumsContext";
import WorkSpace from "../components/Workspace"; import WorkSpace from "../components/Workspace";
import { useThemedPage } from "../hooks";
export default function Editor() { export default function Editor() {
useThemedPage();
return ( return (
<LayoutContextProvider> <LayoutContextProvider>
<TransformContextProvider> <TransformContextProvider>