Skip to content

Commit

Permalink
feat: add theme support
Browse files Browse the repository at this point in the history
  • Loading branch information
mickasmt committed Sep 9, 2023
1 parent da9cabd commit 109f2f8
Show file tree
Hide file tree
Showing 6 changed files with 198 additions and 7 deletions.
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
"class-variance-authority": "^0.7.0",
"clsx": "^2.0.0",
"date-fns": "^2.30.0",
"framer-motion": "^10.16.4",
"lucide-react": "^0.274.0",
"react": "^18.0.0",
"react-dom": "^18.0.0",
Expand Down
39 changes: 39 additions & 0 deletions pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

34 changes: 33 additions & 1 deletion src/components/layout/base-head.astro
Original file line number Diff line number Diff line change
Expand Up @@ -59,5 +59,37 @@ const headTitle = title ? `${title} | ${siteConfig.name}` : title;
<meta property="twitter:description" content={description} />
<meta property="twitter:image" content={new URL(image, Astro.url)} />

<!-- View Transitions -->
<ViewTransitions />

<script is:inline>
const theme = (() => {
if (typeof localStorage !== "undefined" && localStorage.getItem("theme")) {
return localStorage.getItem("theme");
}
if (window.matchMedia("(prefers-color-scheme: dark)").matches) {
return "dark";
}
return "light";
})();

if (theme === "light") {
document.documentElement.classList.remove("dark");
} else {
document.documentElement.classList.add("dark");
}
window.localStorage.setItem("theme", theme);
</script>

<!-- Prevent flash between navigations for the dark mode -->
<script is:inline>
const setDarkMode = () => {
if (localStorage.theme) {
document.documentElement.classList.add(theme);
}
};

// Runs on initial navigation
setDarkMode();
// Runs on view transitions navigation
document.addEventListener('astro:after-swap', setDarkMode);
</script>
11 changes: 6 additions & 5 deletions src/components/layout/footer.astro
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
import { siteConfig } from "@/config/site";
import { cn } from "@/lib/utils";
import { Icon } from "astro-icon";
import { ThemeToggle } from "@/components/theme-toggle";
type Props = {
className?: string;
Expand Down Expand Up @@ -29,7 +30,7 @@ const { className } = Astro.props;
>
mickasmt
</a>
. Based on{" "}
. Based on{" "}
<a
href="https://github.com/shadcn-ui/taxonomy"
target="_blank"
Expand All @@ -38,7 +39,7 @@ const { className } = Astro.props;
>
shadcn-ui/taxonomy
</a>
. Hosted on{" "}
. Hosted on{" "}
<a
href="https://vercel.com"
target="_blank"
Expand All @@ -47,7 +48,7 @@ const { className } = Astro.props;
>
Vercel
</a>
. The source code is available on{" "}
. The source code is available on{" "}
<a
href={siteConfig.links.github}
target="_blank"
Expand All @@ -59,7 +60,7 @@ const { className } = Astro.props;
.
</p>
</div>
<!-- <ModeToggle /> -->
<span>toggle</span>

<ThemeToggle client:idle />
</div>
</footer>
118 changes: 118 additions & 0 deletions src/components/theme-toggle.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,118 @@
import { useMounted } from "@/hooks/use-mounted";
import { AnimatePresence, motion } from "framer-motion";
import { useEffect, useState } from "react";

const SunIcon = () => (
<>
<motion.svg
width="22"
height="22"
viewBox="0 0 24 24"
fill="none"
stroke="currentColor"
strokeWidth="2"
strokeLinecap="round"
strokeLinejoin="round"
initial={{ scale: 0.5, opacity: 0, rotate: 90 }}
animate={{
scale: 1,
opacity: 1,
rotate: 0,
transition: { duration: 0.2, type: "spring", stiffness: 100 },
}}
exit={{
scale: 0.5,
opacity: 0,
rotate: 90,
transition: { duration: 0.2 },
}}
>
<circle cx="12" cy="12" r="5"></circle>
<line x1="12" y1="1" x2="12" y2="3"></line>
<line x1="12" y1="21" x2="12" y2="23"></line>
<line x1="4.22" y1="4.22" x2="5.64" y2="5.64"></line>
<line x1="18.36" y1="18.36" x2="19.78" y2="19.78"></line>
<line x1="1" y1="12" x2="3" y2="12"></line>
<line x1="21" y1="12" x2="23" y2="12"></line>
<line x1="4.22" y1="19.78" x2="5.64" y2="18.36"></line>
<line x1="18.36" y1="5.64" x2="19.78" y2="4.22"></line>
</motion.svg>
</>
);

const MoonIcon = () => (
<>
<motion.svg
width="22"
height="22"
viewBox="0 0 24 24"
fill="none"
stroke="currentColor"
strokeWidth="2"
strokeLinecap="round"
strokeLinejoin="round"
initial={{ scale: 0.5, opacity: 0, rotate: 90 }}
animate={{
scale: 1,
opacity: 1,
rotate: 0,
transition: { duration: 0.2, type: "spring", stiffness: 100 },
}}
exit={{
scale: 0.5,
opacity: 0,
rotate: 90,
transition: { duration: 0.2 },
}}
>
<path d="M21 12.79A9 9 0 1 1 11.21 3 7 7 0 0 0 21 12.79z"></path>
</motion.svg>
</>
);

export function ThemeToggle() {
const [theme, setTheme] = useState(() => {
if (import.meta.env.SSR) {
return undefined;
}
if (typeof localStorage !== "undefined" && localStorage.getItem("theme")) {
return localStorage.getItem("theme");
}
if (window.matchMedia("(prefers-color-scheme: dark)").matches) {
return "dark";
}
return "light";
});

const toggleTheme = () => {
const t = theme === "light" ? "dark" : "light";
localStorage.setItem("theme", t);
setTheme(t);
};

const mounted = useMounted();

useEffect(() => {
const root = document.documentElement;
if (theme === "light") {
root.classList.remove("dark");
} else {
root.classList.add("dark");
}
}, [theme]);

return mounted ? (
<button
role="button"
onClick={toggleTheme}
className="min-h-[40px] -mr-2 block focus:outline-none"
>
<span className="sr-only">Toggle mode</span>
<AnimatePresence initial={false}>
{theme !== "dark" ? <SunIcon /> : <MoonIcon />}
</AnimatePresence>
</button>
) : (
<div />
);
}
2 changes: 1 addition & 1 deletion src/layouts/blog-post.astro
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ const { title, description, pubDate, updatedDate, coverImage, category } =
See all posts
</a>

<article class="prose max-w-none">
<article class="prose dark:prose-invert max-w-none">
<a href={`/blog/category/${category}`}>
<Badge
radius="md"
Expand Down

0 comments on commit 109f2f8

Please sign in to comment.