1
mirror of https://github.com/jakejarvis/jarv.is.git synced 2026-06-05 19:15:30 -04:00

fix flash of white in dark mode

This commit is contained in:
2025-05-21 16:56:54 -04:00
parent 83f1cc2fa9
commit 879c2b9dbe
12 changed files with 128 additions and 118 deletions
+11 -15
View File
@@ -1,22 +1,19 @@
"use client";
import { forwardRef, useState, useEffect } from "react";
import { useState, useEffect } from "react";
import copy from "copy-to-clipboard";
import { ClipboardIcon, CheckIcon } from "lucide-react";
import { cn } from "@/lib/utils";
const CopyButton = (
{
source,
timeout = 2000,
className,
...rest
}: React.ComponentProps<"button"> & {
source: string;
timeout?: number;
},
ref: React.Ref<React.ComponentRef<"button">>
) => {
const CopyButton = ({
source,
timeout = 2000,
className,
...rest
}: React.ComponentProps<"button"> & {
source: string;
timeout?: number;
}) => {
const [copied, setCopied] = useState(false);
const handleCopy: React.MouseEventHandler<React.ComponentRef<"button">> = (e) => {
@@ -48,7 +45,6 @@ const CopyButton = (
return (
<button
ref={ref}
onClick={handleCopy}
disabled={copied}
className={cn("cursor-pointer disabled:cursor-default", className)}
@@ -60,4 +56,4 @@ const CopyButton = (
);
};
export default forwardRef(CopyButton);
export default CopyButton;
+2 -2
View File
@@ -19,7 +19,7 @@ const Header = ({ className, ...rest }: React.ComponentProps<"header">) => {
<Image
src={avatarImg}
alt={`Photo of ${siteConfig.name}`}
className="border-ring/80 size-[64px] rounded-full border-2 md:size-[48px] md:border-1"
className="border-ring/40 size-[64px] rounded-full border-2 md:size-[48px] md:border-1"
width={64}
height={64}
quality={50}
@@ -30,7 +30,7 @@ const Header = ({ className, ...rest }: React.ComponentProps<"header">) => {
</span>
</Link>
<Menu className="w-full max-w-64 sm:max-w-96 md:ml-0 md:max-w-none" />
<Menu className="w-full max-w-64 sm:max-w-96 md:max-w-none" />
</header>
);
};
+11 -10
View File
@@ -1,4 +1,3 @@
import { isValidElement } from "react";
import Link from "@/components/link";
import { cn } from "@/lib/utils";
@@ -9,15 +8,21 @@ const MenuItem = ({
current,
className,
...rest
}: Omit<React.ComponentProps<typeof Link>, "href"> & {
}: React.ComponentProps<"div"> & {
text?: string;
href?: `/${string}`;
icon?: React.ReactNode;
icon: React.ReactNode;
current?: boolean;
}) => {
const item = (
<div className="[&_svg]:stroke-foreground/85 inline-flex items-center [&_svg]:size-7 [&_svg]:md:size-5">
{isValidElement(icon) && icon}
<div
className={cn(
"[&_svg]:stroke-foreground/85 inline-flex items-center [&_svg]:size-7 [&_svg]:md:size-5",
className
)}
{...rest}
>
{icon}
{text && <span className="ml-3 text-sm leading-none font-medium tracking-wide max-md:sr-only">{text}</span>}
</div>
);
@@ -30,11 +35,7 @@ const MenuItem = ({
href={href}
aria-label={text}
data-current={current || undefined}
className={cn(
"text-foreground/85 hover:border-ring data-current:border-primary/40! inline-flex items-center border-b-3 border-b-transparent hover:no-underline",
className
)}
{...rest}
className="text-foreground/85 hover:border-ring/80 data-current:border-primary/60! inline-flex items-center border-b-3 border-b-transparent hover:no-underline"
>
{item}
</Link>
+1 -4
View File
@@ -44,10 +44,7 @@ const Menu = ({ className, ...rest }: React.ComponentProps<"div">) => {
const isCurrent = item.href?.split("/")[1] === segment;
return (
<div
className="inline-block border-t-3 border-t-transparent last:-mr-2.5 max-sm:first:hidden [&_a,&_button]:p-2.5"
key={index}
>
<div className="mt-[3px] inline-block last:-mr-2.5 max-sm:first:hidden **:[a,button]:p-2.5" key={index}>
<MenuItem {...item} current={isCurrent} />
</div>
);
-13
View File
@@ -51,16 +51,3 @@ export const ThemeProvider = ({ children }: React.PropsWithChildren) => {
return <ThemeContext.Provider value={providerValues}>{children}</ThemeContext.Provider>;
};
// loaded in <head> by layout.tsx to avoid blinding flash of unstyled content (FOUC). irrelevant after the first render
// since the theme provider above takes over.
// unminified JS: https://gist.github.com/jakejarvis/79b0ec8506bc843023546d0d29861bf0
export const ThemeScript = () => (
<script
id="restore-theme"
dangerouslySetInnerHTML={{
__html:
"(()=>{try{const e=document.documentElement,t='undefined'!=typeof Storage?window.localStorage.getItem('theme'):null,a=(t&&'dark'===t)??window.matchMedia('(prefers-color-scheme: dark)').matches?'dark':'light';e.dataset.theme=a,e.style.colorScheme=a}catch(e){}})()",
}}
/>
);
+12
View File
@@ -0,0 +1,12 @@
// loaded in <head> by layout.tsx to avoid blinding flash of unstyled content (FOUC). irrelevant after the first render
// when <ThemeProvider /> takes over.
// unminified JS: https://gist.github.com/jakejarvis/79b0ec8506bc843023546d0d29861bf0
export const ThemeScript = () => (
<script
id="restore-theme"
dangerouslySetInnerHTML={{
__html:
"(()=>{try{const e=document.documentElement,t='undefined'!=typeof Storage?window.localStorage.getItem('theme'):null,a=(t&&'dark'===t)??window.matchMedia('(prefers-color-scheme: dark)').matches?'dark':'light';e.dataset.theme=a,e.style.colorScheme=a}catch(e){}})()",
}}
/>
);
+1 -1
View File
@@ -13,7 +13,7 @@ const ThemeToggle = ({ className, ...rest }: React.ComponentProps<"button">) =>
onClick={() => setTheme(theme === "light" ? "dark" : "light")}
aria-label="Toggle theme"
className={cn(
"hover:*:stroke-warning block cursor-pointer bg-transparent not-dark:[&_.lucide-moon]:hidden dark:[&_.lucide-sun]:hidden",
"hover:[&_svg]:stroke-warning block cursor-pointer bg-transparent not-dark:[&_.lucide-moon]:hidden dark:[&_.lucide-sun]:hidden",
className
)}
{...rest}