From 1d59acb78f37050aab47e40c03cb9a3f6820774b Mon Sep 17 00:00:00 2001 From: Sandeep Rudola Date: Mon, 3 Nov 2025 20:57:14 +0530 Subject: [PATCH 1/7] Fix: dark mode flicker and overflow issue --- index.html | 13 +++++ src/App.tsx | 10 +++- src/components/DeveloperTestimonials.tsx | 8 +-- src/components/shared/DarkModeToggle.tsx | 73 ++++++++++++++++++------ src/pages/News/NewsPage.tsx | 24 ++++---- 5 files changed, 93 insertions(+), 35 deletions(-) diff --git a/index.html b/index.html index 6d2862a7..70b26a2d 100644 --- a/index.html +++ b/index.html @@ -16,6 +16,19 @@ } })(); +
diff --git a/src/App.tsx b/src/App.tsx index 51b9d660..97ad9a05 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -4,8 +4,14 @@ import router from '@/routes'; const App = () => { useEffect(() => { - const unsubscribe = router.subscribe(() => { - window.scrollTo(0, 0); + let lastPathname = window.location.pathname; + + const unsubscribe = router.subscribe((state) => { + // Only scroll to top on pathname changes, not on query/hash changes + if (state.location.pathname !== lastPathname) { + window.scrollTo(0, 0); + lastPathname = state.location.pathname; + } }); const handleRedirect = () => { const redirectPath = sessionStorage.getItem('gh_redirect'); diff --git a/src/components/DeveloperTestimonials.tsx b/src/components/DeveloperTestimonials.tsx index 9d8c1cab..256d3621 100644 --- a/src/components/DeveloperTestimonials.tsx +++ b/src/components/DeveloperTestimonials.tsx @@ -49,12 +49,12 @@ const ReviewCard = ({ /> {/* Feedback Text */} - - {body} - +

{body}

+ {/* User Info */}
diff --git a/src/components/shared/DarkModeToggle.tsx b/src/components/shared/DarkModeToggle.tsx index 7230338c..c7efd507 100644 --- a/src/components/shared/DarkModeToggle.tsx +++ b/src/components/shared/DarkModeToggle.tsx @@ -2,18 +2,51 @@ import { useState, useEffect } from 'react'; import { Moon, Sun } from 'lucide-react'; const DarkModeToggle = () => { - const [isDarkMode, setIsDarkMode] = useState(false); + // Initialize from the class that was already set in index.html + const [isDarkMode, setIsDarkMode] = useState(() => { + return document.documentElement.classList.contains('dark'); + }); const [isHovered, setIsHovered] = useState(false); useEffect(() => { + // Sync with localStorage and system preference on mount const theme = localStorage.getItem('theme'); + const prefersDark = window.matchMedia('(prefers-color-scheme: dark)').matches; + if (theme === 'dark') { document.documentElement.classList.add('dark'); setIsDarkMode(true); - } else { + } else if (theme === 'light') { document.documentElement.classList.remove('dark'); setIsDarkMode(false); + } else { + // If no preference saved, respect system preference + if (prefersDark) { + document.documentElement.classList.add('dark'); + setIsDarkMode(true); + } else { + document.documentElement.classList.remove('dark'); + setIsDarkMode(false); + } } + + // Listen for system theme changes (only if no manual preference is set) + const mediaQuery = window.matchMedia('(prefers-color-scheme: dark)'); + const handleThemeChange = (e: MediaQueryListEvent) => { + // Only update if user hasn't set a manual preference + if (!localStorage.getItem('theme')) { + if (e.matches) { + document.documentElement.classList.add('dark'); + setIsDarkMode(true); + } else { + document.documentElement.classList.remove('dark'); + setIsDarkMode(false); + } + } + }; + + mediaQuery.addEventListener('change', handleThemeChange); + return () => mediaQuery.removeEventListener('change', handleThemeChange); }, []); const toggleDarkMode = () => { @@ -34,24 +67,25 @@ const DarkModeToggle = () => { const translateX = isDarkMode ? trackWidth - thumbWidth - padding : padding; return ( - +
); }; diff --git a/src/pages/News/NewsPage.tsx b/src/pages/News/NewsPage.tsx index c9274d08..a5f68948 100644 --- a/src/pages/News/NewsPage.tsx +++ b/src/pages/News/NewsPage.tsx @@ -257,15 +257,17 @@ const NewsPage: React.FC = () => { >
-

+

NEWS

@@ -381,11 +383,13 @@ const NewsPage: React.FC = () => { whileTap={{ scale: 0.95 }} > {cat} - {activeCategory === cat && ( - - {(postsByCategory[cat] || []).length} - - )} + + {(postsByCategory[cat] || []).length} + ))} From 16016addb2e1d0eb70b6d85da5ae92a634911e7c Mon Sep 17 00:00:00 2001 From: Sandeep Rudola Date: Mon, 3 Nov 2025 21:12:48 +0530 Subject: [PATCH 2/7] chore: fix formatting and lint issues --- src/App.tsx | 2 +- src/components/shared/DarkModeToggle.tsx | 160 ++++++++++++----------- src/pages/News/NewsPage.tsx | 12 +- 3 files changed, 89 insertions(+), 85 deletions(-) diff --git a/src/App.tsx b/src/App.tsx index 97ad9a05..0781ec6f 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -5,7 +5,7 @@ import router from '@/routes'; const App = () => { useEffect(() => { let lastPathname = window.location.pathname; - + const unsubscribe = router.subscribe((state) => { // Only scroll to top on pathname changes, not on query/hash changes if (state.location.pathname !== lastPathname) { diff --git a/src/components/shared/DarkModeToggle.tsx b/src/components/shared/DarkModeToggle.tsx index c7efd507..7d481c26 100644 --- a/src/components/shared/DarkModeToggle.tsx +++ b/src/components/shared/DarkModeToggle.tsx @@ -11,8 +11,10 @@ const DarkModeToggle = () => { useEffect(() => { // Sync with localStorage and system preference on mount const theme = localStorage.getItem('theme'); - const prefersDark = window.matchMedia('(prefers-color-scheme: dark)').matches; - + const prefersDark = window.matchMedia( + '(prefers-color-scheme: dark)', + ).matches; + if (theme === 'dark') { document.documentElement.classList.add('dark'); setIsDarkMode(true); @@ -85,98 +87,98 @@ const DarkModeToggle = () => { aria-label={isDarkMode ? 'Switch to light mode' : 'Switch to dark mode'} role="switch" aria-checked={isDarkMode} - > -
- - - -
- - - + > +
- - - + + + + + + + +
); }; diff --git a/src/pages/News/NewsPage.tsx b/src/pages/News/NewsPage.tsx index a5f68948..10528ac0 100644 --- a/src/pages/News/NewsPage.tsx +++ b/src/pages/News/NewsPage.tsx @@ -383,11 +383,13 @@ const NewsPage: React.FC = () => { whileTap={{ scale: 0.95 }} > {cat} - + {(postsByCategory[cat] || []).length} From 71bfc9eb1aec61899370631f864aa5f59a2ae447 Mon Sep 17 00:00:00 2001 From: Sandeep Rudola Date: Wed, 5 Nov 2025 19:55:02 +0530 Subject: [PATCH 3/7] fix(ui): resolve setState in effect lint rule --- src/components/shared/DarkModeToggle.tsx | 34 +++++++++--------------- 1 file changed, 12 insertions(+), 22 deletions(-) diff --git a/src/components/shared/DarkModeToggle.tsx b/src/components/shared/DarkModeToggle.tsx index 7d481c26..d49ddf76 100644 --- a/src/components/shared/DarkModeToggle.tsx +++ b/src/components/shared/DarkModeToggle.tsx @@ -9,41 +9,31 @@ const DarkModeToggle = () => { const [isHovered, setIsHovered] = useState(false); useEffect(() => { - // Sync with localStorage and system preference on mount const theme = localStorage.getItem('theme'); const prefersDark = window.matchMedia( '(prefers-color-scheme: dark)', ).matches; - if (theme === 'dark') { - document.documentElement.classList.add('dark'); - setIsDarkMode(true); - } else if (theme === 'light') { - document.documentElement.classList.remove('dark'); - setIsDarkMode(false); - } else { - // If no preference saved, respect system preference - if (prefersDark) { + setIsDarkMode(() => { + const next = theme === 'dark' || (!theme && prefersDark); + + if (next) { document.documentElement.classList.add('dark'); - setIsDarkMode(true); } else { document.documentElement.classList.remove('dark'); - setIsDarkMode(false); } - } - // Listen for system theme changes (only if no manual preference is set) + return next; + }); + const mediaQuery = window.matchMedia('(prefers-color-scheme: dark)'); const handleThemeChange = (e: MediaQueryListEvent) => { - // Only update if user hasn't set a manual preference if (!localStorage.getItem('theme')) { - if (e.matches) { - document.documentElement.classList.add('dark'); - setIsDarkMode(true); - } else { - document.documentElement.classList.remove('dark'); - setIsDarkMode(false); - } + setIsDarkMode(() => { + const next = e.matches; + document.documentElement.classList.toggle('dark', next); + return next; + }); } }; From 2b1cd6d1b7074c90567488f99c941e9b74165a9d Mon Sep 17 00:00:00 2001 From: Sandeep Rudola Date: Wed, 5 Nov 2025 19:59:23 +0530 Subject: [PATCH 4/7] fix(ui): clean dark mode effect logic to satisfy lint rule --- src/components/shared/DarkModeToggle.tsx | 45 +++++++++--------------- 1 file changed, 16 insertions(+), 29 deletions(-) diff --git a/src/components/shared/DarkModeToggle.tsx b/src/components/shared/DarkModeToggle.tsx index d49ddf76..53711315 100644 --- a/src/components/shared/DarkModeToggle.tsx +++ b/src/components/shared/DarkModeToggle.tsx @@ -10,35 +10,22 @@ const DarkModeToggle = () => { useEffect(() => { const theme = localStorage.getItem('theme'); - const prefersDark = window.matchMedia( - '(prefers-color-scheme: dark)', - ).matches; - - setIsDarkMode(() => { - const next = theme === 'dark' || (!theme && prefersDark); - - if (next) { - document.documentElement.classList.add('dark'); - } else { - document.documentElement.classList.remove('dark'); - } - - return next; - }); - - const mediaQuery = window.matchMedia('(prefers-color-scheme: dark)'); - const handleThemeChange = (e: MediaQueryListEvent) => { - if (!localStorage.getItem('theme')) { - setIsDarkMode(() => { - const next = e.matches; - document.documentElement.classList.toggle('dark', next); - return next; - }); - } - }; - - mediaQuery.addEventListener('change', handleThemeChange); - return () => mediaQuery.removeEventListener('change', handleThemeChange); + const prefersDark = window.matchMedia('(prefers-color-scheme: dark)').matches; + + // ✅ Determine the final theme first + let shouldBeDark = + theme === 'dark' || (!theme && prefersDark); + + // ✅ Apply class WITHOUT calling setState inside effect yet + if (shouldBeDark) { + document.documentElement.classList.add('dark'); + } else { + document.documentElement.classList.remove('dark'); + } + + // ✅ Update state ONCE at the end + setIsDarkMode(shouldBeDark); + }, []); const toggleDarkMode = () => { From 818d2eaf1a3f4ba9a34bd31ae600581168b28b7f Mon Sep 17 00:00:00 2001 From: Sandeep Rudola Date: Wed, 5 Nov 2025 20:07:08 +0530 Subject: [PATCH 5/7] fix(ui): correct dark mode initialization to avoid setState in effect --- src/components/shared/DarkModeToggle.tsx | 39 ++++++++++++------------ 1 file changed, 20 insertions(+), 19 deletions(-) diff --git a/src/components/shared/DarkModeToggle.tsx b/src/components/shared/DarkModeToggle.tsx index 53711315..24b3ed98 100644 --- a/src/components/shared/DarkModeToggle.tsx +++ b/src/components/shared/DarkModeToggle.tsx @@ -4,28 +4,29 @@ import { Moon, Sun } from 'lucide-react'; const DarkModeToggle = () => { // Initialize from the class that was already set in index.html const [isDarkMode, setIsDarkMode] = useState(() => { - return document.documentElement.classList.contains('dark'); + const storedTheme = localStorage.getItem('theme'); + const prefersDark = window.matchMedia('(prefers-color-scheme: dark)').matches; + return storedTheme === 'dark' || (!storedTheme && prefersDark); }); - const [isHovered, setIsHovered] = useState(false); useEffect(() => { - const theme = localStorage.getItem('theme'); - const prefersDark = window.matchMedia('(prefers-color-scheme: dark)').matches; - - // ✅ Determine the final theme first - let shouldBeDark = - theme === 'dark' || (!theme && prefersDark); - - // ✅ Apply class WITHOUT calling setState inside effect yet - if (shouldBeDark) { - document.documentElement.classList.add('dark'); - } else { - document.documentElement.classList.remove('dark'); - } - - // ✅ Update state ONCE at the end - setIsDarkMode(shouldBeDark); - + // Listen for system theme changes (only if no manual preference is set) + const mediaQuery = window.matchMedia('(prefers-color-scheme: dark)'); + const handleThemeChange = (e: MediaQueryListEvent) => { + // Only update if user hasn't set a manual preference + if (!localStorage.getItem('theme')) { + const shouldBeDark = e.matches; + if (shouldBeDark) { + document.documentElement.classList.add('dark'); + } else { + document.documentElement.classList.remove('dark'); + } + setIsDarkMode(shouldBeDark); + } + }; + + mediaQuery.addEventListener('change', handleThemeChange); + return () => mediaQuery.removeEventListener('change', handleThemeChange); }, []); const toggleDarkMode = () => { From 0bfece8fb1fbc806a8535a1a55f725a3383dd9c3 Mon Sep 17 00:00:00 2001 From: Sandeep Rudola Date: Wed, 5 Nov 2025 20:12:05 +0530 Subject: [PATCH 6/7] chore(ui): fix dark mode toggle lint rule --- src/components/shared/DarkModeToggle.tsx | 1 + 1 file changed, 1 insertion(+) diff --git a/src/components/shared/DarkModeToggle.tsx b/src/components/shared/DarkModeToggle.tsx index 24b3ed98..43f589ad 100644 --- a/src/components/shared/DarkModeToggle.tsx +++ b/src/components/shared/DarkModeToggle.tsx @@ -8,6 +8,7 @@ const DarkModeToggle = () => { const prefersDark = window.matchMedia('(prefers-color-scheme: dark)').matches; return storedTheme === 'dark' || (!storedTheme && prefersDark); }); + const [isHovered, setIsHovered] = useState(false); useEffect(() => { // Listen for system theme changes (only if no manual preference is set) From f9e64d3ab9bd1a71191006d8bf6cb53b62e3eb1b Mon Sep 17 00:00:00 2001 From: Sandeep Rudola Date: Wed, 5 Nov 2025 20:14:04 +0530 Subject: [PATCH 7/7] fix: add missing isHovered state and fix formatting in DarkModeToggle --- src/components/shared/DarkModeToggle.tsx | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/components/shared/DarkModeToggle.tsx b/src/components/shared/DarkModeToggle.tsx index 43f589ad..657f45ee 100644 --- a/src/components/shared/DarkModeToggle.tsx +++ b/src/components/shared/DarkModeToggle.tsx @@ -5,7 +5,9 @@ const DarkModeToggle = () => { // Initialize from the class that was already set in index.html const [isDarkMode, setIsDarkMode] = useState(() => { const storedTheme = localStorage.getItem('theme'); - const prefersDark = window.matchMedia('(prefers-color-scheme: dark)').matches; + const prefersDark = window.matchMedia( + '(prefers-color-scheme: dark)', + ).matches; return storedTheme === 'dark' || (!storedTheme && prefersDark); }); const [isHovered, setIsHovered] = useState(false);