1
mirror of https://github.com/jakejarvis/jarv.is.git synced 2026-06-13 19:55:26 -04:00

Migrate to app router (#2254)

This commit is contained in:
2025-02-07 11:33:38 -05:00
committed by GitHub
parent e97613dda5
commit 8aabb4a66f
179 changed files with 4095 additions and 4951 deletions
@@ -0,0 +1,13 @@
.toggle {
border: 0;
padding: 0.6em;
margin-right: -0.6em;
background: none;
cursor: pointer;
color: var(--colors-mediumDark);
}
.toggle:hover,
.toggle:focus-visible {
color: var(--colors-warning);
}
+13 -21
View File
@@ -1,23 +1,12 @@
"use client";
import { useEffect, useId } from "react";
import { useSpring, animated, Globals } from "@react-spring/web";
import useMedia from "../../hooks/useMedia";
import { animated, Globals, useSpring, useReducedMotion } from "@react-spring/web";
import useFirstMountState from "../../hooks/useFirstMountState";
import useTheme from "../../hooks/useTheme";
import useHasMounted from "../../hooks/useHasMounted";
import { styled, theme } from "../../lib/styles/stitches.config";
const Button = styled("button", {
border: 0,
padding: "0.6em",
marginRight: "-0.6em",
background: "none",
cursor: "pointer",
color: theme.colors.mediumDark,
"&:hover, &:focus-visible": {
color: theme.colors.warning,
},
});
import styles from "./ThemeToggle.module.css";
export type ThemeToggleProps = {
className?: string;
@@ -27,7 +16,7 @@ const ThemeToggle = ({ className }: ThemeToggleProps) => {
const hasMounted = useHasMounted();
const { activeTheme, setTheme } = useTheme();
const isFirstMount = useFirstMountState();
const prefersReducedMotion = useMedia("(prefers-reduced-motion: reduce)", false);
const prefersReducedMotion = useReducedMotion() ?? false;
const maskId = useId(); // SSR-safe ID to cross-reference areas of the SVG
// default to light since `activeTheme` might be undefined
@@ -36,7 +25,7 @@ const ThemeToggle = ({ className }: ThemeToggleProps) => {
// accessibility: disable animation if user prefers reduced motion
useEffect(() => {
Globals.assign({
skipAnimation: !!isFirstMount || !!prefersReducedMotion,
skipAnimation: isFirstMount || prefersReducedMotion,
});
}, [isFirstMount, prefersReducedMotion]);
@@ -97,18 +86,20 @@ const ThemeToggle = ({ className }: ThemeToggleProps) => {
// render a blank div of the same size to avoid layout shifting until we're fully mounted and self-aware
if (!hasMounted) {
return (
<Button as="div">
<div className={styles.toggle}>
<div className={className} />
</Button>
</div>
);
}
return (
<Button
<button
onClick={() => setTheme(safeTheme === "light" ? "dark" : "light")}
className={styles.toggle}
title={safeTheme === "light" ? "Toggle Dark Mode" : "Toggle Light Mode"}
aria-label={safeTheme === "light" ? "Toggle Dark Mode" : "Toggle Light Mode"}
>
{/* @ts-ignore */}
<animated.svg
xmlns="http://www.w3.org/2000/svg"
width="1em"
@@ -146,6 +137,7 @@ const ThemeToggle = ({ className }: ThemeToggleProps) => {
/>
{/* sunrays pulled from https://github.com/feathericons/feather/blob/734f3f51144e383cfdc6d0916831be8d1ad2a749/icons/sun.svg?short_path=fea872c#L13 */}
{/* @ts-ignore */}
<animated.g stroke="currentColor" style={linesProps}>
<line x1="12" y1="1" x2="12" y2="3" />
<line x1="12" y1="21" x2="12" y2="23" />
@@ -157,7 +149,7 @@ const ThemeToggle = ({ className }: ThemeToggleProps) => {
<line x1="18.36" y1="5.64" x2="19.78" y2="4.22" />
</animated.g>
</animated.svg>
</Button>
</button>
);
};