From 516ade0af5a913ed4bfc709e82fdcd2605a5b57d Mon Sep 17 00:00:00 2001 From: hariombalhara Date: Thu, 10 Feb 2022 16:37:14 +0530 Subject: [PATCH] Fix/theme flicker (#1758) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Avoid Theme Flicker. Render Server Side * Add back isReady implementation * Use shorter syntax for Tag Co-authored-by: Peer Richelsen Co-authored-by: Omar López Co-authored-by: kodiakhq[bot] <49736102+kodiakhq[bot]@users.noreply.github.com> --- components/booking/pages/AvailabilityPage.tsx | 3 +- components/booking/pages/BookingPage.tsx | 3 +- ee/components/stripe/PaymentPage.tsx | 3 +- lib/hooks/useTheme.tsx | 36 ++++++++++++------- pages/[user].tsx | 3 +- pages/success.tsx | 3 +- pages/team/[slug].tsx | 3 +- 7 files changed, 36 insertions(+), 18 deletions(-) diff --git a/components/booking/pages/AvailabilityPage.tsx b/components/booking/pages/AvailabilityPage.tsx index 5e0ad180..de70765e 100644 --- a/components/booking/pages/AvailabilityPage.tsx +++ b/components/booking/pages/AvailabilityPage.tsx @@ -35,7 +35,7 @@ type Props = AvailabilityTeamPageProps | AvailabilityPageProps; const AvailabilityPage = ({ profile, eventType, workingHours }: Props) => { const router = useRouter(); const { rescheduleUid } = router.query; - const { isReady } = useTheme(profile.theme); + const { isReady, Theme } = useTheme(profile.theme); const { t } = useLocale(); const { contracts } = useContracts(); @@ -99,6 +99,7 @@ const AvailabilityPage = ({ profile, eventType, workingHours }: Props) => { return ( <> + { }); const rescheduleUid = router.query.rescheduleUid as string; - const { isReady } = useTheme(props.profile.theme); + const { isReady, Theme } = useTheme(props.profile.theme); const date = asStringOrNull(router.query.date); const timeFormat = asStringOrNull(router.query.clock) === "24h" ? "H:mm" : "h:mma"; @@ -275,6 +275,7 @@ const BookingPage = (props: BookingPageProps) => { return (
+ {rescheduleUid diff --git a/ee/components/stripe/PaymentPage.tsx b/ee/components/stripe/PaymentPage.tsx index 7614d52d..0587031c 100644 --- a/ee/components/stripe/PaymentPage.tsx +++ b/ee/components/stripe/PaymentPage.tsx @@ -23,7 +23,7 @@ const PaymentPage: FC<PaymentPageProps> = (props) => { const { t } = useLocale(); const [is24h, setIs24h] = useState(false); const [date, setDate] = useState(dayjs.utc(props.booking.startTime)); - const { isReady } = useTheme(props.profile.theme); + const { isReady, Theme } = useTheme(props.profile.theme); useEffect(() => { setDate(date.tz(localStorage.getItem("timeOption.preferredTimeZone") || dayjs.tz.guess())); @@ -34,6 +34,7 @@ const PaymentPage: FC<PaymentPageProps> = (props) => { return isReady ? ( <div className="h-screen bg-neutral-50 dark:bg-neutral-900"> + <Theme /> <Head> <title> {t("payment")} | {eventName} | Cal.com diff --git a/lib/hooks/useTheme.tsx b/lib/hooks/useTheme.tsx index ec56b322..2b9ff7e5 100644 --- a/lib/hooks/useTheme.tsx +++ b/lib/hooks/useTheme.tsx @@ -1,24 +1,36 @@ -import { useLayoutEffect, useState } from "react"; +import Head from "next/head"; +import { useEffect, useState } from "react"; import { Maybe } from "@trpc/server"; // makes sure the ui doesn't flash export default function useTheme(theme?: Maybe<string>) { const [isReady, setIsReady] = useState(false); - - useLayoutEffect(() => { - if (!theme && window.matchMedia("(prefers-color-scheme: dark)").matches) { - document.documentElement.classList.add("dark"); - } else if (!theme) { - /** Uncovered case */ - } else { - document.documentElement.classList.add(theme); - } - + useEffect(() => { setIsReady(true); - }, [theme]); + }, []); + function Theme() { + const themeString = theme ? `"${theme}"` : null; + return ( + <Head> + <script + dangerouslySetInnerHTML={{ + __html: `(function (theme) { + if (!theme && window.matchMedia("(prefers-color-scheme: dark)").matches) { + document.documentElement.classList.add("dark"); + } else if (!theme) { + /** Uncovered case */ + } else { + document.documentElement.classList.add(theme); + } + })(${themeString})`, + }}></script> + </Head> + ); + } return { isReady, + Theme, }; } diff --git a/pages/[user].tsx b/pages/[user].tsx index 193f2818..2abdbc76 100644 --- a/pages/[user].tsx +++ b/pages/[user].tsx @@ -26,7 +26,7 @@ interface EvtsToVerify { } export default function User(props: inferSSRProps<typeof getServerSideProps>) { - const { isReady } = useTheme(props.user.theme); + const { isReady, Theme } = useTheme(props.user.theme); const { user, eventTypes } = props; const { t } = useLocale(); const router = useRouter(); @@ -38,6 +38,7 @@ export default function User(props: inferSSRProps<typeof getServerSideProps>) { return ( <> + <Theme /> <HeadSeo title={nameOrUsername} description={(user.bio as string) || ""} diff --git a/pages/success.tsx b/pages/success.tsx index be4d595b..a82b1793 100644 --- a/pages/success.tsx +++ b/pages/success.tsx @@ -37,7 +37,7 @@ export default function Success(props: inferSSRProps<typeof getServerSideProps>) const [is24h, setIs24h] = useState(false); const [date, setDate] = useState(dayjs.utc(asStringOrThrow(router.query.date))); - const { isReady } = useTheme(props.profile.theme); + const { isReady, Theme } = useTheme(props.profile.theme); useEffect(() => { setDate(date.tz(localStorage.getItem("timeOption.preferredTimeZone") || dayjs.tz.guess())); @@ -90,6 +90,7 @@ export default function Success(props: inferSSRProps<typeof getServerSideProps>) return ( (isReady && ( <div className="h-screen bg-neutral-100 dark:bg-neutral-900" data-testid="success-page"> + <Theme /> <HeadSeo title={needsConfirmation ? t("booking_submitted") : t("booking_confirmed")} description={needsConfirmation ? t("booking_submitted") : t("booking_confirmed")} diff --git a/pages/team/[slug].tsx b/pages/team/[slug].tsx index f79238f3..3f00d0fe 100644 --- a/pages/team/[slug].tsx +++ b/pages/team/[slug].tsx @@ -23,7 +23,7 @@ import Text from "@components/ui/Text"; export type TeamPageProps = inferSSRProps<typeof getServerSideProps>; function TeamPage({ team }: TeamPageProps) { - const { isReady } = useTheme(); + const { isReady, Theme } = useTheme(); const showMembers = useToggleQuery("members"); const { t } = useLocale(); @@ -63,6 +63,7 @@ function TeamPage({ team }: TeamPageProps) { return ( isReady && ( <div> + <Theme /> <HeadSeo title={teamName} description={teamName} /> <div className="px-4 pt-24 pb-12"> <div className="mx-auto mb-8 max-w-96 text-center">