1
mirror of https://github.com/jakejarvis/jarv.is.git synced 2026-04-17 09:28:43 -04:00

cumulative layout shift fixes

- inject theme toggle placeholder instead of loading dynamically
- explicitly set sticky header height
- set `font-display: fallback`
This commit is contained in:
2022-01-14 17:10:35 -05:00
parent 399091122c
commit 58c82a1715
9 changed files with 299 additions and 26 deletions

View File

@@ -2,6 +2,7 @@
position: sticky;
top: 0;
width: 100%;
height: 4.5em;
padding: 0.7em 1.5em;
border-bottom: 1px solid var(--kinda-light);
background-color: var(--background-header);
@@ -108,6 +109,7 @@
@media screen and (max-width: 768px) {
.header {
padding: 0.75em 1.25em;
height: 5.9em;
}
.left {

View File

@@ -1,16 +1,13 @@
import { memo } from "react";
import dynamic from "next/dynamic";
import Link from "next/link";
import Image from "next/image";
import ThemeToggle from "./ThemeToggle";
import { HomeIcon, NotesIcon, ProjectsIcon, ContactIcon } from "../icons";
import meJpg from "../../public/static/images/me.jpg";
import styles from "./Header.module.css";
// ensure the theme toggle isn't evaluated server-side
const ThemeToggle = dynamic(() => import("./ThemeToggle"), { ssr: false });
const links = [
{
icon: <HomeIcon className={`icon ${styles.icon}`} />,

View File

@@ -0,0 +1,6 @@
.button {
border: 0;
padding: 0;
background: none;
cursor: pointer;
}

View File

@@ -1,6 +1,8 @@
import { memo } from "react";
import { useEffect, useState, memo } from "react";
import { useTheme } from "next-themes";
import styles from "./ThemeToggle.module.css";
// modified from Twemoji lightbulb:
const BulbIcon = ({ on = false, className = "" }) => (
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36" className={className}>
@@ -30,21 +32,21 @@ const BulbIcon = ({ on = false, className = "" }) => (
);
const ThemeToggle = ({ className = "" }) => {
const [mounted, setMounted] = useState(false);
const { resolvedTheme, setTheme } = useTheme();
// render a dummy bulb until we're fully mounted and self-aware
useEffect(() => setMounted(true), []);
if (!mounted) return <BulbIcon on={false} className={`icon ${className}`} />;
return (
<button
onClick={() => setTheme(resolvedTheme === "dark" ? "light" : "dark")}
title={resolvedTheme === "dark" ? "Toggle Light Mode" : "Toggle Dark Mode"}
className={styles.button}
onClick={() => setTheme(resolvedTheme === "light" ? "dark" : "light")}
title={resolvedTheme === "light" ? "Toggle Dark Mode" : "Toggle Light Mode"}
aria-hidden={true}
style={{
border: 0,
padding: 0,
background: "none",
cursor: "pointer",
}}
>
<BulbIcon on={resolvedTheme !== "dark"} className={`icon ${className}`} />
<BulbIcon on={resolvedTheme === "light"} className={`icon ${className}`} />
</button>
);
};