From c79b108e66bc9fb6f522ff66edbf03392e09fcf5 Mon Sep 17 00:00:00 2001 From: Yudho <149754501+yudhomax@users.noreply.github.com> Date: Fri, 1 Nov 2024 15:26:57 +0530 Subject: [PATCH] fix(app): dark mode page flash in app router (#598) --- .../app/Address/Contract/VerifiedData.tsx | 4 +- .../components/app/Advertise/ThemeImage.tsx | 4 +- .../src/components/app/Apis/ApiActions.tsx | 4 +- apps/app/src/components/app/Charts/Chart.tsx | 4 +- .../src/components/app/Charts/TpsChart.tsx | 4 +- .../components/app/Contact/FormContact.tsx | 4 +- .../app/src/components/app/Layouts/Footer.tsx | 4 +- .../app/src/components/app/Layouts/Header.tsx | 17 +++++--- .../app/src/components/app/Layouts/Layout.tsx | 42 ++++++++++++------- .../components/app/Layouts/LayoutActions.tsx | 6 ++- .../src/components/app/Layouts/RpcMenu.tsx | 2 +- .../app/NodeExplorer/Delegators.tsx | 4 +- .../app/NodeExplorer/NodeListActions.tsx | 4 +- .../components/app/Transactions/Overview.tsx | 13 +++--- apps/app/src/components/app/common/QrCode.tsx | 4 +- apps/app/src/components/common/Links.tsx | 4 +- apps/app/src/hooks/app/useTheme.ts | 32 ++++++++++++++ apps/app/src/stores/theme.ts | 11 +++++ 18 files changed, 114 insertions(+), 53 deletions(-) create mode 100644 apps/app/src/hooks/app/useTheme.ts create mode 100644 apps/app/src/stores/theme.ts diff --git a/apps/app/src/components/app/Address/Contract/VerifiedData.tsx b/apps/app/src/components/app/Address/Contract/VerifiedData.tsx index 0f3f46a15..30cc67de0 100644 --- a/apps/app/src/components/app/Address/Contract/VerifiedData.tsx +++ b/apps/app/src/components/app/Address/Contract/VerifiedData.tsx @@ -1,5 +1,4 @@ import React, { useState, useEffect, useRef } from 'react'; -import { useTheme } from 'next-themes'; import { Prism as SyntaxHighlighter } from 'react-syntax-highlighter'; import { oneDark } from 'react-syntax-highlighter/dist/cjs/styles/prism'; import { oneLight } from 'react-syntax-highlighter/dist/cjs/styles/prism'; @@ -13,6 +12,7 @@ import { VerifierData } from '@/utils/types'; import ErrorMessage from '@/components/common/ErrorMessage'; import FaInbox from '@/components/Icons/FaInbox'; import { verifierConfig } from '@/utils/app/config'; +import { useThemeStore } from '@/stores/theme'; type VerifiedDataProps = { verifierData: VerifierData; @@ -49,7 +49,7 @@ const VerifiedData: React.FC = ({ {}, ); - const { theme } = useTheme(); + const theme = useThemeStore((store) => store.theme); useEffect(() => { const fetchCode = async () => { diff --git a/apps/app/src/components/app/Advertise/ThemeImage.tsx b/apps/app/src/components/app/Advertise/ThemeImage.tsx index 7bae51ae9..d15c598f8 100644 --- a/apps/app/src/components/app/Advertise/ThemeImage.tsx +++ b/apps/app/src/components/app/Advertise/ThemeImage.tsx @@ -1,9 +1,9 @@ 'use client'; -import { useTheme } from 'next-themes'; +import { useThemeStore } from '@/stores/theme'; import Image from 'next/legacy/image'; export default function ThemeImage() { - const { theme } = useTheme(); + const theme = useThemeStore((store) => store.theme); return ( { - const { theme } = useTheme(); + const theme = useThemeStore((store) => store.theme); const [interval, setInterval] = useState(true); const [subject, _setSubject] = useState('API'); diff --git a/apps/app/src/components/app/Charts/Chart.tsx b/apps/app/src/components/app/Charts/Chart.tsx index 674d3c2c7..4fc34773e 100644 --- a/apps/app/src/components/app/Charts/Chart.tsx +++ b/apps/app/src/components/app/Charts/Chart.tsx @@ -5,12 +5,12 @@ import SwitchButton from '../SwitchButton'; import { yoctoToNear } from '@/utils/libs'; import { ChartConfig, ChartStat, ChartTypeInfo } from '@/utils/types'; import { Tooltip } from '@reach/tooltip'; -import { useTheme } from 'next-themes'; import Skeleton from '../skeleton/common/Skeleton'; import Image from 'next/legacy/image'; import { useTranslations } from 'next-intl'; import { Link } from '@/i18n/routing'; import { useConfig } from '@/hooks/app/useConfig'; +import { useThemeStore } from '@/stores/theme'; interface Props { chartTypes?: string; @@ -24,7 +24,7 @@ interface Props { const Chart = (props: Props) => { const { chartTypes, poweredBy, chartsData } = props; const t = useTranslations(); - const { theme } = useTheme(); + const theme = useThemeStore((store) => store.theme); const [chartConfig, setChartConfig] = useState(null); const [chartInfo, setChartInfo] = useState({ title: '', diff --git a/apps/app/src/components/app/Charts/TpsChart.tsx b/apps/app/src/components/app/Charts/TpsChart.tsx index 730013f93..0766961b8 100644 --- a/apps/app/src/components/app/Charts/TpsChart.tsx +++ b/apps/app/src/components/app/Charts/TpsChart.tsx @@ -4,12 +4,12 @@ import SwitchButton from '../SwitchButton'; import Question from '../Icons/Question'; import { chartDataInfo } from '@/utils/types'; import { Tooltip } from '@reach/tooltip'; -import { useTheme } from 'next-themes'; import Image from 'next/image'; import Skeleton from '../skeleton/common/Skeleton'; import { useTranslations } from 'next-intl'; import { Link } from '@/i18n/routing'; import { useConfig } from '@/hooks/app/useConfig'; +import { useThemeStore } from '@/stores/theme'; interface Props { chartTypes: string; @@ -21,7 +21,7 @@ interface Props { } const TpsChart = (props: Props) => { const { chartTypes, poweredBy, data } = props; - const { theme } = useTheme(); + const theme = useThemeStore((store) => store.theme); const t = useTranslations(); const { networkId } = useConfig(); diff --git a/apps/app/src/components/app/Contact/FormContact.tsx b/apps/app/src/components/app/Contact/FormContact.tsx index e6bdc7ef5..545725705 100644 --- a/apps/app/src/components/app/Contact/FormContact.tsx +++ b/apps/app/src/components/app/Contact/FormContact.tsx @@ -4,9 +4,9 @@ import { toast } from 'react-toastify'; import 'react-toastify/dist/ReactToastify.css'; import { Turnstile } from '@marsidev/react-turnstile'; import type { TurnstileInstance } from '@marsidev/react-turnstile'; -import { useTheme } from 'next-themes'; import { useTranslations } from 'next-intl'; import LoadingCircular from '@/components/common/LoadingCircular'; +import { useThemeStore } from '@/stores/theme'; interface Props { selectValue?: string; @@ -16,7 +16,7 @@ interface Props { const siteKey = process.env.NEXT_PUBLIC_TURNSTILE_SITE_KEY; const FormContact = ({ selectValue, getContactDetails }: Props) => { - const { theme } = useTheme(); + const theme = useThemeStore((store) => store.theme); const t = useTranslations('contact'); const [loading, setLoading] = useState(false); diff --git a/apps/app/src/components/app/Layouts/Footer.tsx b/apps/app/src/components/app/Layouts/Footer.tsx index 1c06ca06b..beaa09f6c 100644 --- a/apps/app/src/components/app/Layouts/Footer.tsx +++ b/apps/app/src/components/app/Layouts/Footer.tsx @@ -1,12 +1,12 @@ 'use client'; import Image from 'next/legacy/image'; import Arrow from '../Icons/Arrow'; -import { useTheme } from 'next-themes'; import { useTranslations } from 'next-intl'; import { Link } from '@/i18n/routing'; +import { useThemeStore } from '@/stores/theme'; const Footer = () => { - const { theme } = useTheme(); + const theme = useThemeStore((store) => store.theme); const currentDate = new Date(); const t = useTranslations(); diff --git a/apps/app/src/components/app/Layouts/Header.tsx b/apps/app/src/components/app/Layouts/Header.tsx index b074e14f8..b67df7641 100644 --- a/apps/app/src/components/app/Layouts/Header.tsx +++ b/apps/app/src/components/app/Layouts/Header.tsx @@ -10,12 +10,12 @@ import ActiveLink from '../ActiveLink'; import Skeleton from '@/components/skeleton/common/Skeleton'; import { dollarFormat, nanoToMilli } from '@/utils/libs'; import User from '../Icons/User'; -import { useTheme } from 'next-themes'; import { BlocksInfo, Stats } from '@/utils/types'; import { Link, routing, usePathname } from '@/i18n/routing'; import { useTranslations } from 'next-intl'; import Search from '../common/Search'; import { useConfig } from '@/hooks/app/useConfig'; +import { useThemeStore } from '@/stores/theme'; const menus = [ { @@ -165,7 +165,8 @@ const Header = ({ const t = useTranslations(); const { networkId } = useConfig(); const pathname = usePathname(); - const { theme, setTheme } = useTheme(); + const theme = useThemeStore((store) => store.theme); + const status = useMemo(() => { if (block?.block_timestamp) { const timestamp = nanoToMilli(block?.block_timestamp); @@ -180,6 +181,12 @@ const Header = ({ return true; }, [block]); + const toggleTheme = () => { + localStorage.setItem('theme', theme === 'light' ? 'dark' : 'light'); + document.documentElement.classList.toggle('dark'); + document.documentElement.classList.toggle('light'); + }; + const showSearch = pathname !== '/'; const userLoading = false; @@ -300,7 +307,7 @@ const Header = ({