From 2a902dd6fc19b005e12f48798638c866254ef7ca Mon Sep 17 00:00:00 2001 From: CodeMaverick143 Date: Wed, 5 Nov 2025 02:30:59 +0530 Subject: [PATCH] I'll implement a dark theme for the Home (Landing) Page while keeping the existing structure and design intact --- src/App.jsx | 27 ++++++----- src/components/Navbar.jsx | 39 ++++++++++------ src/components/ThemeToggle.jsx | 24 ++++++++++ src/context/ThemeContext.jsx | 83 ++++++++++++++++++++++++++++++++++ src/pages/LandingPage.jsx | 73 +++++++++++++++--------------- tailwind.config.js | 1 + 6 files changed, 184 insertions(+), 63 deletions(-) create mode 100644 src/components/ThemeToggle.jsx create mode 100644 src/context/ThemeContext.jsx diff --git a/src/App.jsx b/src/App.jsx index fcb09811b..a2aabf912 100644 --- a/src/App.jsx +++ b/src/App.jsx @@ -5,22 +5,25 @@ import BugReport from "./pages/BugReport"; import Templates from "./pages/Templates"; import LandingPage from "./pages/LandingPage"; import SettingsContextProvider from "./context/SettingsContext"; +import ThemeProvider from "./context/ThemeContext"; import NotFound from "./pages/NotFound"; export default function App() { return ( - - - - - } /> - } /> - } /> - } /> - } /> - - - + + + + + + } /> + } /> + } /> + } /> + } /> + + + + ); } diff --git a/src/components/Navbar.jsx b/src/components/Navbar.jsx index 8ef775d07..363e88890 100644 --- a/src/components/Navbar.jsx +++ b/src/components/Navbar.jsx @@ -4,20 +4,23 @@ import logo from "../assets/logo_light_160.png"; import { SideSheet } from "@douyinfe/semi-ui"; import { IconMenu } from "@douyinfe/semi-icons"; import { socials } from "../data/socials"; +import ThemeToggle from "./ThemeToggle"; +import { useTheme } from "../context/ThemeContext"; export default function Navbar() { const [openMenu, setOpenMenu] = useState(false); + const { theme } = useTheme(); return ( <> -
-
+
+
logo
document .getElementById("features") @@ -28,24 +31,25 @@ export default function Navbar() { Editor Templates Docs
- @@ -92,7 +96,7 @@ export default function Navbar() { width={window.innerWidth} > { document .getElementById("features") @@ -105,24 +109,29 @@ export default function Navbar() {
Editor
Templates
Docs +
+
+ Theme: + +
); diff --git a/src/components/ThemeToggle.jsx b/src/components/ThemeToggle.jsx new file mode 100644 index 000000000..a35e40ff6 --- /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 000000000..13f686f19 --- /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 2638d7333..031e4dbd2 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 */}
-
+
{/* Supported by */}
-
+
Supported by
@@ -121,13 +123,13 @@ export default function LandingPage() { width={260} className="m-auto mb-4" /> -
+
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() { >
{/* Features */} -
+
-
+
More than just an editor
-
+
What drawDB has to offer
{features.map((f, i) => (
-
+ className="flex rounded-xl hover:bg-zinc-100 dark:hover:bg-gray-700 border border-zinc-100 dark:border-gray-700 shadow-xs hover:-translate-y-2 transition-all duration-300 dark:bg-gray-800"> +
-
{f.title}
+
{f.title}
{f.content} -
{f.footer}
+
{f.footer}
))} @@ -216,12 +217,12 @@ export default function LandingPage() {
{/* Tweets */} -
-
+
+
What the internet says about us
@@ -244,11 +245,11 @@ export default function LandingPage() { fill="#f4f4f5" /> -
-
+
+
Reach out to us
-
+
We love hearing from you. Join our community on Discord, GitHub, and X.
@@ -295,12 +296,12 @@ export default function LandingPage() {
-
+
Attention! The diagrams are saved in your browser. Before clearing the browser make sure to back up your data.
-
-
+
+
© {new Date().getFullYear()} drawDB - All rights reserved.
diff --git a/tailwind.config.js b/tailwind.config.js index 619a0f9f6..269b905f4 100644 --- a/tailwind.config.js +++ b/tailwind.config.js @@ -3,6 +3,7 @@ export default { content: [ "./src/**/*.{js,jsx,ts,tsx}", ], + darkMode: 'class', theme: { screens: { '3xl': {'max': '2047px'},