Skip to content

Commit

Permalink
Dark Mode (#476)
Browse files Browse the repository at this point in the history
  • Loading branch information
icco authored Mar 21, 2024
2 parents eaee62a + cb4bc03 commit 9a595c1
Show file tree
Hide file tree
Showing 13 changed files with 190 additions and 122 deletions.
File renamed without changes.
2 changes: 2 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -18,12 +18,14 @@
"@mdx-js/loader": "^3.0.0",
"@mdx-js/react": "^3.0.0",
"contentlayer-temp": "^0.4.4",
"daisyui": "^4.7.3",
"date-fns": "^3.2.0",
"feed": "^4.2.2",
"mdast-util-find-and-replace": "^3.0.0",
"next": "^14.0.0",
"next-contentlayer-temp": "^0.4.4",
"next-secure-headers": "^2.2.0",
"next-themes": "^0.3.0",
"react": "^18.2.0",
"react-dom": "^18.2.0",
"reading-time": "^1.5.0",
Expand Down
13 changes: 1 addition & 12 deletions src/app/globals.css
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,9 @@
body,
p {
font-family: var(--font-roboto);
color: theme('colors.text');
background-color: theme('colors.background');
}

pre {
background-color: theme('colors.nord1');
color: theme('colors.nord6');
padding: 1em;
overflow: scroll;
}
Expand Down Expand Up @@ -76,26 +72,22 @@ article img {
article a {
-webkit-transition: color 0.4s;
transition: color 0.4s;
color: theme('colors.link');
}

a.blue:link,
a.blue:visited,
article a:link,
article a:visited {
color: theme('colors.link');
}

a.blue:hover,
article a:hover {
color: theme('colors.accent');
}

a.blue:active,
article a:active {
-webkit-transition: color 0.3s;
transition: color 0.3s;
color: theme('colors.link');
}

section .react-mde .grip {
Expand All @@ -106,7 +98,6 @@ section .react-mde .grip {
article blockquote {
border-left-style: solid;
border-width: 0 0 0 0.5em;
border-color: theme('colors.accent');
padding: 0 2rem;
margin-left: 0;
margin-right: 1rem;
Expand All @@ -131,13 +122,11 @@ article blockquote cite {
article ol {
list-style-type: decimal;
margin-left: 1rem;
color: theme('colors.text');
}

article ul {
list-style-type: circle;
margin-left: 1rem;
color: theme('colors.text');
}

article li {
Expand All @@ -147,7 +136,7 @@ article li {

article hr {
border: 0;
border-top: 0.3rem dotted theme('colors.accent');
border-top: 0.3rem dotted;
margin: 1rem;
}

Expand Down
40 changes: 26 additions & 14 deletions src/app/layout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import { Roboto, Roboto_Mono, Roboto_Slab } from "next/font/google"

import Footer from "@/components/Footer"
import Header from "@/components/Header"
import { ThemeProvider } from "@/components/ThemeProvider"

const roboto = Roboto({
weight: "400",
Expand Down Expand Up @@ -33,26 +34,37 @@ export default function RootLayout({
}: {
children: React.ReactNode
}) {
let meticulousScript = <></>
if (
process.env.NODE_ENV === "development" ||
process.env.VERCEL_ENV === "preview"
) {
meticulousScript = (
// eslint-disable-next-line @next/next/no-sync-scripts
<script
data-project-id="HRQOYGM9Ui3pdObThsWrs6RCZ38sO96OXPNAeMSu"
data-is-production-environment="false"
src="https://snippet.meticulous.ai/v1/meticulous.js"
/>
)
}
return (
<html
lang="en"
className={`${roboto.variable} ${robotoSlab.variable} ${robotoMono.variable}`}
suppressHydrationWarning
>
<head>
{(process.env.NODE_ENV === "development" ||
process.env.VERCEL_ENV === "preview") && (
// eslint-disable-next-line @next/next/no-sync-scripts
<script
data-project-id="HRQOYGM9Ui3pdObThsWrs6RCZ38sO96OXPNAeMSu"
data-is-production-environment="false"
src="https://snippet.meticulous.ai/v1/meticulous.js"
/>
)}
</head>
<head>{meticulousScript}</head>
<body>
<Header />
<main>{children}</main>
<Footer />
<ThemeProvider
defaultTheme="system"
enableSystem
disableTransitionOnChange
>
<Header />
<main>{children}</main>
<Footer />
</ThemeProvider>
</body>
</html>
)
Expand Down
26 changes: 19 additions & 7 deletions src/app/post/[slug]/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import {
ChevronLeftIcon,
ChevronRightIcon,
PencilIcon,
} from "@heroicons/react/24/solid"
} from "@heroicons/react/24/outline"
import { format, parseISO } from "date-fns"
import type { Viewport } from "next"
import { draftMode } from "next/headers"
Expand Down Expand Up @@ -73,7 +73,7 @@ const PostLayout = ({ params }: { params: { slug: string } }) => {
<>
<article className="py-7 px-8 mx-auto max-w-5xl">
<div className="mb-8 text-center">
<div className="text-xs text-nord3">
<div className="text-xs">
<span className="mx-1 inline-block">
<Link href={post.url}>#{post.id}</Link>
</span>
Expand All @@ -83,12 +83,12 @@ const PostLayout = ({ params }: { params: { slug: string } }) => {
</time>
</div>
<h1>{post.title}</h1>
<div className="text-xs text-nord3">
<div className="text-xs">
<span className="mx-1 inline-block">
By <Link href="https://natwelch.com">Nat Welch</Link>
</span>
</div>
{post.draft && <div className="mb-1 text-xs text-nord11">DRAFT</div>}
{post.draft && <div className="mb-1 text-xs text-error">DRAFT</div>}
</div>

<div className="prose lg:prose-xl max-w-5xl">
Expand All @@ -98,23 +98,35 @@ const PostLayout = ({ params }: { params: { slug: string } }) => {
<div className="py-7 px-8 flex mx-auto max-w-5xl align-middle">
<div className="flex-none">
{prev && (
<Link href={prev.permalink} title={prev.title}>
<Link
href={prev.permalink}
title={prev.title}
className="btn btn-secondary"
>
<ChevronLeftIcon className="inline-block w-6 h-6" /> #{prev.id}
</Link>
)}
</div>
<div className="flex-grow flex">
<div className="flex-grow"></div>
<div className="flex-none">
<Link href={post.github} title="Edit this post on Github">
<Link
href={post.github}
title="Edit this post on Github"
className="btn btn-ghost"
>
<PencilIcon className="inline-block w-4 h-4" />
</Link>
</div>
<div className="flex-grow"></div>
</div>
<div className="flex-none">
{next && (
<Link href={next.permalink} title={next.title}>
<Link
href={next.permalink}
title={next.title}
className="btn btn-secondary"
>
#{next.id} <ChevronRightIcon className="inline-block w-6 h-6" />
</Link>
)}
Expand Down
60 changes: 32 additions & 28 deletions src/components/Footer.tsx
Original file line number Diff line number Diff line change
@@ -1,40 +1,44 @@
import "./rc.css"

import { CodeBracketIcon, DocumentCheckIcon } from "@heroicons/react/24/outline"
import { format } from "date-fns"
import Link from "next/link"

const Footer = () => {
return (
<footer className="text-muted px-6 lg:px-8 py-12">
<div className="max-w-screen-xl mx-auto flex flex-col md:flex-row justify-between items-center space-y-4 mt-8 lg:mt-12 border-t-2 border-border pt-8">
<nav className="flex flex-wrap justify-center space-x-6">
<div className="my-2 rc-scout" data-scout-rendered="true">
<p className="text-muted text-sm rc-scout__text">
<i className="rc-scout__logo" /> Want to become a better
programmer?{" "}
<Link
className="rc-scout__link"
href="https://www.recurse.com/scout/click?t=1a20cf01214e4c5923ab6ebd6c0f8f18"
>
Join the Recurse Center!
</Link>
</p>
</div>
</nav>
<p className="text-sm text-center md:text-right">
&copy; 2011 - {format(new Date(), "yyyy")} Nat Welch. All rights
reserved.{" "}
<Link className="blue" href="https://github.com/icco/writing">
Source code
<div className="max-w-5xl mx-auto">
<div className="divider" />
<footer className="footer items-center p-4">
<aside className="items-center grid-flow-col">
<p>
&copy; 2011 - {format(new Date(), "yyyy")} Nat Welch. All rights
reserved.
</p>
</aside>
<nav className="grid-flow-col gap-4 md:place-self-center md:justify-self-end">
<Link
href="https://www.recurse.com/scout/click?t=1a20cf01214e4c5923ab6ebd6c0f8f18"
title="Want to become a better programmer? Join the Recurse Center!"
>
<i className="rc-scout__logo" />
</Link>
<Link
className="blue ms-2"
href="https://github.com/icco/writing"
title="Source Code"
>
<CodeBracketIcon className="inline-block w-4 h-4" />
</Link>
.{" "}
<Link className="blue" href="https://natwelch.com/privacy">
Privacy
<Link
className="blue ms-2"
href="https://natwelch.com/privacy"
title="Privacy Policy"
>
<DocumentCheckIcon className="inline-block w-4 h-4" />
</Link>
.
</p>
</div>
</footer>
</nav>
</footer>
</div>
)
}

Expand Down
7 changes: 5 additions & 2 deletions src/components/Header.tsx
Original file line number Diff line number Diff line change
@@ -1,17 +1,20 @@
import Link from "next/link"

import Logo from "@/components/Logo"
import Logo from "./Logo"
import ThemeToggle from "./ThemeToggle"

export default function Header() {
return (
<nav className="flex py-8">
<div className="flex-none">
<Link href="/" className="">
<Logo size={50} className="px-8 logo" style={{ stroke: "#333" }} />
<Logo size={50} className="px-8 logo stroke-current" />
</Link>
</div>
<div className="flex-grow"></div>
<div className="flex-none">
<ThemeToggle />

<Link key="/about" href="/about" prefetch={false} className="m-8">
About
</Link>
Expand Down
6 changes: 2 additions & 4 deletions src/components/PostCard.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ export function PostCard(post: Post) {
{post.draft && (
<>
<span>&mdash;</span>
<div className="inline-block mx-1 text-xs text-nord11">DRAFT</div>
<div className="inline-block mx-1 text-xs text-error">DRAFT</div>
</>
)}
</div>
Expand All @@ -33,9 +33,7 @@ export function PostCard(post: Post) {
className="inline-block pr-1 mb-2 text-xs"
key={tag}
>
<span className="inline-block bg-accent rounded-full px-3 py-1 text-sm font-semibold text-link hover:text-text hover:bg-link mr-2 mb-2">
#{tag}
</span>
<span className="badge badge-secondary">#{tag}</span>
</Link>
)
})}
Expand Down
14 changes: 14 additions & 0 deletions src/components/ThemeProvider.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
"use client"

import { ThemeProvider as NextThemesProvider } from "next-themes"
import * as React from "react"

type ThemeProviderProps = Parameters<typeof NextThemesProvider>[0]

/**
* Your app's theme provider component.
* 'use client' is essential for next-themes to work with app-dir.
*/
export function ThemeProvider({ children, ...props }: ThemeProviderProps) {
return <NextThemesProvider {...props}>{children}</NextThemesProvider>
}
37 changes: 37 additions & 0 deletions src/components/ThemeToggle.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
"use client"

import { MoonIcon, SunIcon } from "@heroicons/react/24/outline"
import { useTheme } from "next-themes"

function ThemeToggle() {
const { resolvedTheme, theme, setTheme } = useTheme()

let isDark = resolvedTheme === "dark"

const onChange = () => {
console.log("clicked", { resolvedTheme, isDark })
setTheme(isDark ? "light" : "dark")
isDark = theme === "dark"
}

return (
<>
<label className="swap swap-rotate">
{/* this hidden checkbox controls the state */}
<input
type="checkbox"
checked={isDark}
onChange={onChange}
className="theme-controller"
value={resolvedTheme}
/>

<SunIcon className="swap-off w-4 h-4" />

<MoonIcon className="swap-on w-4 h-4" />
</label>
</>
)
}

export default ThemeToggle
Loading

0 comments on commit 9a595c1

Please sign in to comment.