>
);
diff --git a/src/components/ThemeToggle.jsx b/src/components/ThemeToggle.jsx
new file mode 100644
index 00000000..a35e40ff
--- /dev/null
+++ b/src/components/ThemeToggle.jsx
@@ -0,0 +1,24 @@
+import { useTheme } from "../context/ThemeContext";
+
+export default function ThemeToggle({ className = "" }) {
+ const { theme, toggleTheme } = useTheme();
+
+ return (
+
+ );
+}
diff --git a/src/context/ThemeContext.jsx b/src/context/ThemeContext.jsx
new file mode 100644
index 00000000..13f686f1
--- /dev/null
+++ b/src/context/ThemeContext.jsx
@@ -0,0 +1,83 @@
+import { createContext, useContext, useEffect, useState } from "react";
+
+// Create context
+export const ThemeContext = createContext();
+
+// Theme provider component
+export default function ThemeProvider({ children }) {
+ // Check for system preference and stored preference
+ const getInitialTheme = () => {
+ // Check if we're in the browser
+ if (typeof window !== "undefined") {
+ // Check localStorage first
+ const storedTheme = localStorage.getItem("theme");
+ if (storedTheme) {
+ return storedTheme;
+ }
+
+ // Check system preference
+ const userPrefersDark = window.matchMedia("(prefers-color-scheme: dark)").matches;
+ return userPrefersDark ? "dark" : "light";
+ }
+
+ // Default to light if not in browser
+ return "light";
+ };
+
+ const [theme, setTheme] = useState(getInitialTheme);
+
+ // Toggle theme function
+ const toggleTheme = () => {
+ setTheme(prevTheme => prevTheme === "light" ? "dark" : "light");
+ };
+
+ // Update localStorage and apply theme class to html element
+ useEffect(() => {
+ // Save to localStorage
+ localStorage.setItem("theme", theme);
+
+ // Apply class to html element
+ const htmlElement = document.documentElement;
+ if (theme === "dark") {
+ htmlElement.classList.add("dark");
+ } else {
+ htmlElement.classList.remove("dark");
+ }
+
+ // Also update the theme-mode attribute for semi-ui components
+ document.body.setAttribute("theme-mode", theme);
+ }, [theme]);
+
+ // Listen for system preference changes
+ useEffect(() => {
+ const mediaQuery = window.matchMedia("(prefers-color-scheme: dark)");
+ const handleChange = () => {
+ // Only update if user hasn't manually set a preference
+ if (!localStorage.getItem("theme")) {
+ setTheme(mediaQuery.matches ? "dark" : "light");
+ }
+ };
+
+ // Add listener
+ mediaQuery.addEventListener("change", handleChange);
+
+ // Clean up
+ return () => mediaQuery.removeEventListener("change", handleChange);
+ }, []);
+
+ // Provide theme context to children
+ return (
+
+ {children}
+
+ );
+}
+
+// Custom hook for using theme
+export const useTheme = () => {
+ const context = useContext(ThemeContext);
+ if (context === undefined) {
+ throw new Error("useTheme must be used within a ThemeProvider");
+ }
+ return context;
+};
diff --git a/src/pages/LandingPage.jsx b/src/pages/LandingPage.jsx
index 2638d733..031e4dbd 100644
--- a/src/pages/LandingPage.jsx
+++ b/src/pages/LandingPage.jsx
@@ -18,6 +18,7 @@ import axios from "axios";
import { languages } from "../i18n/i18n";
import { Tweet } from "react-tweet";
import { socials } from "../data/socials";
+import { useTheme } from "../context/ThemeContext";
function shortenNumber(number) {
if (number < 1000) return number;
@@ -29,6 +30,8 @@ function shortenNumber(number) {
export default function LandingPage() {
const [stats, setStats] = useState({ stars: 18000, forks: 1200 });
+ const { theme } = useTheme();
+
useEffect(() => {
const fetchStats = async () => {
await axios
@@ -36,7 +39,6 @@ export default function LandingPage() {
.then((res) => setStats(res.data));
};
- document.body.setAttribute("theme-mode", "light");
document.title =
"drawDB | Online database diagram editor and SQL generator";
@@ -44,36 +46,36 @@ export default function LandingPage() {
}, []);
return (
-
-
-
+
+
+
{/* Hero section */}
-
+
-
-
+
+
-
+
Draw, Copy, and Paste
Free and open source, simple, and intuitive database design
editor, data-modeler, and SQL generator.{" "}
-
+
No sign up
-
+
Free of charge
-
+
Quick and easy
@@ -81,7 +83,7 @@ export default function LandingPage() {
Try it for yourself
@@ -103,10 +105,10 @@ export default function LandingPage() {
{/* Learn more */}
Next-gen AI-powered intelligent terminal for all platforms
-
+
Build diagrams with a few clicks, see the full picture, export SQL
scripts, customize your editor, and more.
@@ -160,7 +162,7 @@ export default function LandingPage() {
-
+
Design for your database
@@ -183,31 +185,30 @@ export default function LandingPage() {
>