Skip to content

add light theme support #78

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 3 commits into from
Jul 3, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
69 changes: 60 additions & 9 deletions components/Header.vue
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,12 @@ const route = useRoute();

<template>
<nav class="container mx-auto py-5">
<div class="flex items-center text-gray-200">
<div class="flex items-center text-gray-700 dark:text-gray-200">
<div class="flex-1" />
<div class="flex items-center space-x-2">
<HeadlessMenu as="div" class="relative z-50 inline-block text-left">
<div>
<HeadlessMenuButton class="text-white hover:text-orange-500">
<HeadlessMenuButton class="text-gray-700 dark:text-white hover:text-orange-500">
<div class="text-2xl">&bull;&bull;&bull;</div>
</HeadlessMenuButton>
</div>
Expand All @@ -25,14 +25,14 @@ const route = useRoute();
leave-to-class="transform scale-95 opacity-0"
>
<HeadlessMenuItems
class="absolute right-0 mt-2 w-36 origin-top-right divide-y divide-gray-100 rounded-md bg-black/80 text-white shadow-lg ring-1 ring-black ring-opacity-5 backdrop-blur-sm focus:outline-none"
class="absolute right-0 mt-2 w-36 origin-top-right divide-y divide-gray-100 dark:divide-gray-100 rounded-md bg-white/90 dark:bg-black/80 text-gray-900 dark:text-white shadow-lg ring-1 ring-black ring-opacity-5 backdrop-blur-sm focus:outline-none"
>
<div class="px-1 py-1">
<HeadlessMenuItem v-slot="{ active }">
<NuxtLink to="/">
<button
:class="[
active ? 'bg-orange-500/50 text-white' : 'text-white',
active ? 'bg-orange-500/50 text-white dark:text-white' : 'text-gray-700 dark:text-white',
$route.path === '/' ? 'bg-orange-500' : '',
'group flex w-full items-center rounded-md px-2 py-2 text-sm',
]"
Expand Down Expand Up @@ -84,7 +84,7 @@ const route = useRoute();
<a href="/articles">
<button
:class="[
active ? 'bg-orange-500/50 text-white' : 'text-white',
active ? 'bg-orange-500/50 text-white dark:text-white' : 'text-gray-700 dark:text-white',
$route.path === '/articles' ? 'bg-orange-500' : '',
'group flex w-full items-center rounded-md px-2 py-2 text-sm',
]"
Expand Down Expand Up @@ -112,7 +112,7 @@ const route = useRoute();
<a href="/playground">
<button
:class="[
active ? 'bg-orange-500/50 text-white' : 'text-white',
active ? 'bg-orange-500/50 text-white dark:text-white' : 'text-gray-700 dark:text-white',
$route.path === '/playground' ? 'bg-orange-500' : '',
'group flex w-full items-center rounded-md px-2 py-2 text-sm',
]"
Expand Down Expand Up @@ -140,7 +140,7 @@ const route = useRoute();
<a href="/talks">
<button
:class="[
active ? 'bg-orange-500/50' : '',
active ? 'bg-orange-500/50 text-white dark:text-white' : 'text-gray-700 dark:text-white',
$route.path === '/talks' ? 'bg-orange-500' : '',
'group flex w-full items-center rounded-md px-2 py-2 text-sm',
]"
Expand All @@ -166,7 +166,7 @@ const route = useRoute();
<a href="https://github.com/cmpadden">
<button
:class="[
active ? 'bg-orange-500/50 text-white' : 'text-white',
active ? 'bg-orange-500/50 text-white dark:text-white' : 'text-gray-700 dark:text-white',
'group flex w-full items-center rounded-md px-2 py-2 text-sm',
]"
>
Expand All @@ -189,7 +189,7 @@ const route = useRoute();
<a href="https://bsky.app/profile/colton.boo">
<button
:class="[
active ? 'bg-orange-500/50 text-white' : 'text-white',
active ? 'bg-orange-500/50 text-white dark:text-white' : 'text-gray-700 dark:text-white',
'group flex w-full items-center rounded-md px-2 py-2 text-sm',
]"
>
Expand All @@ -208,6 +208,57 @@ const route = useRoute();
</a>
</HeadlessMenuItem>
</div>

<!-- Divider -->
<div class="border-t border-gray-300 dark:border-gray-600"></div>

<!-- Theme Toggle Section -->
<div class="px-1 py-1">
<HeadlessMenuItem v-slot="{ active }">
<button
@click="$colorMode.preference = $colorMode.value === 'dark' ? 'light' : 'dark'"
:class="[
active ? 'bg-orange-500/50 text-white dark:text-white' : 'text-gray-700 dark:text-white',
'group flex w-full items-center rounded-md px-2 py-2 text-sm',
]"
>
<!-- Sun icon for when we're in dark mode (clicking switches to light) -->
<svg
v-if="$colorMode.value === 'dark'"
class="mr-2 inline h-5 w-5"
fill="none"
stroke="currentColor"
viewBox="0 0 24 24"
xmlns="http://www.w3.org/2000/svg"
>
<path
stroke-linecap="round"
stroke-linejoin="round"
stroke-width="2"
d="M12 3v1m0 16v1m9-9h-1M4 12H3m15.364 6.364l-.707-.707M6.343 6.343l-.707-.707m12.728 0l-.707.707M6.343 17.657l-.707.707M16 12a4 4 0 11-8 0 4 4 0 018 0z"
/>
</svg>

<!-- Moon icon for when we're in light mode (clicking switches to dark) -->
<svg
v-else
class="mr-2 inline h-5 w-5"
fill="none"
stroke="currentColor"
viewBox="0 0 24 24"
xmlns="http://www.w3.org/2000/svg"
>
<path
stroke-linecap="round"
stroke-linejoin="round"
stroke-width="2"
d="M20.354 15.354A9 9 0 018.646 3.646 9.003 9.003 0 0012 21a9.003 9.003 0 008.354-5.646z"
/>
</svg>
<span class="translate-y-0.5">{{ $colorMode.value === 'dark' ? 'Light Mode' : 'Dark Mode' }}</span>
</button>
</HeadlessMenuItem>
</div>
</HeadlessMenuItems>
</transition>
</HeadlessMenu>
Expand Down
2 changes: 1 addition & 1 deletion components/MoreLink.vue
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ const props = defineProps({
<div class="flex justify-end">
<NuxtLink
:to="props.to"
class="flex items-center text-sm font-bold text-white hover:text-orange-500"
class="flex items-center text-sm font-bold text-gray-700 dark:text-white hover:text-orange-500"
>
<span class="translate-y-0.5">See More</span>
<CursorArrowRaysIcon class="ml-1 h-5 w-5" aria-hidden="true" />
Expand Down
49 changes: 49 additions & 0 deletions components/ThemeToggle.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
<template>
<button
@click="toggleTheme"
class="flex items-center justify-center w-8 h-8 rounded-md transition-colors duration-200 hover:bg-orange-500/20 bg-gray-100/10 dark:bg-gray-800/20"
:title="$colorMode.value === 'dark' ? 'Switch to light mode' : 'Switch to dark mode'"
>
<!-- Sun icon for light mode -->
<svg
v-if="$colorMode.value === 'dark'"
class="w-5 h-5 text-yellow-500 dark:text-yellow-400"
fill="none"
stroke="currentColor"
viewBox="0 0 24 24"
xmlns="http://www.w3.org/2000/svg"
>
<path
stroke-linecap="round"
stroke-linejoin="round"
stroke-width="2"
d="M12 3v1m0 16v1m9-9h-1M4 12H3m15.364 6.364l-.707-.707M6.343 6.343l-.707-.707m12.728 0l-.707.707M6.343 17.657l-.707.707M16 12a4 4 0 11-8 0 4 4 0 018 0z"
/>
</svg>

<!-- Moon icon for dark mode -->
<svg
v-else
class="w-5 h-5 text-gray-700 dark:text-gray-300"
fill="none"
stroke="currentColor"
viewBox="0 0 24 24"
xmlns="http://www.w3.org/2000/svg"
>
<path
stroke-linecap="round"
stroke-linejoin="round"
stroke-width="2"
d="M20.354 15.354A9 9 0 018.646 3.646 9.003 9.003 0 0012 21a9.003 9.003 0 008.354-5.646z"
/>
</svg>
</button>
</template>

<script setup>
const { $colorMode } = useNuxtApp()

const toggleTheme = () => {
$colorMode.preference = $colorMode.value === 'dark' ? 'light' : 'dark'
}
</script>
8 changes: 4 additions & 4 deletions components/section/BlogPosts.vue
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,14 @@ const props = defineProps({
</script>

<template>
<section class="bg-gradient-to-b from-background to-transparent py-2">
<section class="bg-gradient-to-b from-background dark:from-background-dark to-transparent py-2">
<div class="container mx-auto space-y-4">

<div class="mb-4 grid grid-cols-1 gap-4 md:grid-cols-2">
<div v-for="(article, ix) of articles" :key="ix">
<NuxtLink :to="article.path">
<div
class="h-full space-y-4 rounded-lg bg-white/20 p-4 text-white drop-shadow-lg hover:ring-1 hover:ring-white"
class="h-full space-y-4 rounded-lg bg-white/80 dark:bg-white/20 p-4 text-gray-700 dark:text-white drop-shadow-lg hover:ring-1 hover:ring-gray-300 dark:hover:ring-white"
>
<div>
<div class="flex-1 text-lg font-bold md:text-xl">
Expand All @@ -22,13 +22,13 @@ const props = defineProps({
<NuxtTime
v-if="show_dates"
:datetime="article.date"
class="text-sm font-light text-gray-400"
class="text-sm font-light text-gray-600 dark:text-gray-400"
year="numeric"
month="short"
day="2-digit"
/>
</div>
<div class="line-clamp-3 text-sm text-gray-300">
<div class="line-clamp-3 text-sm text-gray-700 dark:text-gray-300">
{{ article.description }}
</div>
</div>
Expand Down
12 changes: 6 additions & 6 deletions components/section/Playground.vue
Original file line number Diff line number Diff line change
Expand Up @@ -99,12 +99,12 @@ const filtered_links = computed(() => {
</script>

<template>
<section class="bg-gradient-to-b from-transparent to-background text-white">
<div class="container mx-auto space-y-4 py-8 text-white">
<section class="bg-gradient-to-b from-transparent to-background dark:to-background-dark text-gray-700 dark:text-white">
<div class="container mx-auto space-y-4 py-8 text-gray-700 dark:text-white">

<div class="mb-4 grid grid-cols-1 gap-4 sm:grid-cols-2 lg:grid-cols-3">
<nuxt-link
class="relative rounded-lg drop-shadow-lg hover:ring-1 hover:ring-white"
class="relative rounded-lg drop-shadow-lg hover:ring-1 hover:ring-gray-300 dark:hover:ring-white"
v-for="link in filtered_links"
:key="link.title"
:to="link.link"
Expand All @@ -116,12 +116,12 @@ const filtered_links = computed(() => {
<div
class="absolute bottom-0 flex w-full items-center justify-center"
>
<div class="min-h-24 w-full rounded-b-lg bg-gray-800/80 px-6 py-2">
<h3 class="text-xl font-bold text-white">
<div class="min-h-24 w-full rounded-b-lg bg-white/90 dark:bg-gray-800/80 px-6 py-2">
<h3 class="text-xl font-bold text-gray-700 dark:text-white">
{{ link.title }}
</h3>
<div
class="line-clamp-2 text-sm text-gray-300"
class="line-clamp-2 text-sm text-gray-700 dark:text-gray-300"
v-html="link.description"
></div>
</div>
Expand Down
2 changes: 1 addition & 1 deletion layouts/default.vue
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
<template>
<div class="bg-gradient-to-b from-orange-500 to-red-500">
<div class="p-[10px]">
<main class="flex h-[calc(100vh-20px)] flex-col rounded-3xl bg-background font-display">
<main class="flex h-[calc(100vh-20px)] flex-col rounded-3xl bg-background dark:bg-background-dark font-display">
<Header />
<main class="flex-1 overflow-scroll no-scrollbar">
<slot />
Expand Down
21 changes: 18 additions & 3 deletions nuxt.config.ts
Original file line number Diff line number Diff line change
@@ -1,16 +1,28 @@
// https://nuxt.com/docs/api/configuration/nuxt-config
export default defineNuxtConfig({
components: true,
modules: ["@nuxt/content", "@nuxtjs/tailwindcss", "nuxt-headlessui"],
modules: ["@nuxt/content", "@nuxtjs/tailwindcss", "@nuxtjs/color-mode", "nuxt-headlessui"],

app: {
head: {
bodyAttrs: {
class: 'bg-background'
class: 'bg-background dark:bg-background-dark'
}
}
},

// Color mode configuration
colorMode: {
preference: 'system', // default value of $colorMode.preference
fallback: 'dark', // fallback value if not system preference found
hid: 'nuxt-color-mode-script',
globalName: '__NUXT_COLOR_MODE__',
componentName: 'ColorScheme',
classPrefix: '',
classSuffix: '',
storageKey: 'nuxt-color-mode'
},

// Optionally change the default prefix.
headlessui: {
prefix: "Headless",
Expand All @@ -22,7 +34,10 @@ export default defineNuxtConfig({
// Disable highlighting until interoperability with by the Tailwind Typography plugin is sorted
// highlight: false
highlight: {
theme: 'github-dark',
theme: {
light: 'github-light',
default: 'github-dark'
},
preload: [
'bash',
'js',
Expand Down
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
"webpack": "^5.99.9"
},
"dependencies": {
"@nuxtjs/color-mode": "^3.5.2",
"chords.ts": "^0.1.0",
"p5": "^1.11.7",
"tailwindcss": "^3.4.17"
Expand Down
16 changes: 8 additions & 8 deletions pages/articles/[...slug].vue
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,8 @@ const { data: page } = await useAsyncData(route.path, () => {
</script>

<template>
<div class="container mx-auto text-white" v-if="page">
<article class="mb-10 space-y-6 shadow-lg">
<div class="container mx-auto text-gray-700 dark:text-white" v-if="page">
<article class="mb-10 space-y-6 shadow-sm dark:shadow-lg">
<!-- title -->
<div class="flex">
<!-- https://content.nuxt.com/components/content-slot -->
Expand All @@ -34,10 +34,10 @@ const { data: page } = await useAsyncData(route.path, () => {
<!-- Meta -->
<div class="flex space-x-2">
<div>
<div class="mb-2 text-xs uppercase text-gray-400">Category</div>
<div class="mb-2 text-xs uppercase text-gray-600 dark:text-gray-400">Category</div>
<div class="flex flex-row space-x-2">
<NuxtLink
class="mr-2 w-min rounded-md bg-background text-sm font-bold hover:cursor-pointer hover:text-orange-500"
class="mr-2 w-min rounded-md bg-background dark:bg-background-dark text-sm font-bold hover:cursor-pointer hover:text-orange-500"
v-for="(category, ix) in page.categories"
:key="ix"
:to="`/articles?category=${category}`"
Expand All @@ -47,13 +47,13 @@ const { data: page } = await useAsyncData(route.path, () => {
</div>
</div>

<div class="border-r border-gray-400"></div>
<div class="border-r border-gray-400 dark:border-gray-400"></div>

<div>
<div class="mb-2 text-xs uppercase text-gray-400">Tags</div>
<div class="mb-2 text-xs uppercase text-gray-600 dark:text-gray-400">Tags</div>
<div class="flex flex-row md:space-x-2">
<NuxtLink
class="mr-2 w-min rounded-md bg-background text-sm font-bold hover:cursor-pointer hover:text-orange-500"
class="mr-2 w-min rounded-md bg-background dark:bg-background-dark text-sm font-bold hover:cursor-pointer hover:text-orange-500"
v-for="(tag, ix) in page.tags"
:key="ix"
:to="`/articles?tag=${tag}`"
Expand All @@ -69,7 +69,7 @@ const { data: page } = await useAsyncData(route.path, () => {
- Use prose-pre:bg-white to work with @nuxt/content syntax highlighting, otherwise background-color defaults to `.prose:where(pre)`
-->
<article
class="prose max-w-none text-gray-300 prose-h2:mt-8 prose-a:font-bold prose-a:text-orange-400 prose-a:no-underline hover:prose-a:text-orange-500 prose-blockquote:text-gray-400 prose-code:text-white prose-pre:bg-black"
class="prose max-w-none text-gray-700 dark:text-gray-300 prose-h2:mt-8 prose-a:font-bold prose-a:text-orange-400 prose-a:no-underline hover:prose-a:text-orange-500 prose-blockquote:text-gray-600 dark:prose-blockquote:text-gray-400 prose-code:text-gray-900 dark:prose-code:text-white prose-pre:bg-gray-100 dark:prose-pre:bg-black"
>
<ContentRenderer v-if="page" :value="page" />
</article>
Expand Down
Loading