Skip to content

Commit 5ebf5cf

Browse files
authored
Merge pull request #78 from cmpadden/add-light-theme-support
add light theme support
2 parents ed3d7b8 + 41deb55 commit 5ebf5cf

File tree

14 files changed

+182
-44
lines changed

14 files changed

+182
-44
lines changed

components/Header.vue

Lines changed: 60 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -6,12 +6,12 @@ const route = useRoute();
66

77
<template>
88
<nav class="container mx-auto py-5">
9-
<div class="flex items-center text-gray-200">
9+
<div class="flex items-center text-gray-700 dark:text-gray-200">
1010
<div class="flex-1" />
1111
<div class="flex items-center space-x-2">
1212
<HeadlessMenu as="div" class="relative z-50 inline-block text-left">
1313
<div>
14-
<HeadlessMenuButton class="text-white hover:text-orange-500">
14+
<HeadlessMenuButton class="text-gray-700 dark:text-white hover:text-orange-500">
1515
<div class="text-2xl">&bull;&bull;&bull;</div>
1616
</HeadlessMenuButton>
1717
</div>
@@ -25,14 +25,14 @@ const route = useRoute();
2525
leave-to-class="transform scale-95 opacity-0"
2626
>
2727
<HeadlessMenuItems
28-
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"
28+
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"
2929
>
3030
<div class="px-1 py-1">
3131
<HeadlessMenuItem v-slot="{ active }">
3232
<NuxtLink to="/">
3333
<button
3434
:class="[
35-
active ? 'bg-orange-500/50 text-white' : 'text-white',
35+
active ? 'bg-orange-500/50 text-white dark:text-white' : 'text-gray-700 dark:text-white',
3636
$route.path === '/' ? 'bg-orange-500' : '',
3737
'group flex w-full items-center rounded-md px-2 py-2 text-sm',
3838
]"
@@ -84,7 +84,7 @@ const route = useRoute();
8484
<a href="/articles">
8585
<button
8686
:class="[
87-
active ? 'bg-orange-500/50 text-white' : 'text-white',
87+
active ? 'bg-orange-500/50 text-white dark:text-white' : 'text-gray-700 dark:text-white',
8888
$route.path === '/articles' ? 'bg-orange-500' : '',
8989
'group flex w-full items-center rounded-md px-2 py-2 text-sm',
9090
]"
@@ -112,7 +112,7 @@ const route = useRoute();
112112
<a href="/playground">
113113
<button
114114
:class="[
115-
active ? 'bg-orange-500/50 text-white' : 'text-white',
115+
active ? 'bg-orange-500/50 text-white dark:text-white' : 'text-gray-700 dark:text-white',
116116
$route.path === '/playground' ? 'bg-orange-500' : '',
117117
'group flex w-full items-center rounded-md px-2 py-2 text-sm',
118118
]"
@@ -140,7 +140,7 @@ const route = useRoute();
140140
<a href="/talks">
141141
<button
142142
:class="[
143-
active ? 'bg-orange-500/50' : '',
143+
active ? 'bg-orange-500/50 text-white dark:text-white' : 'text-gray-700 dark:text-white',
144144
$route.path === '/talks' ? 'bg-orange-500' : '',
145145
'group flex w-full items-center rounded-md px-2 py-2 text-sm',
146146
]"
@@ -166,7 +166,7 @@ const route = useRoute();
166166
<a href="https://github.com/cmpadden">
167167
<button
168168
:class="[
169-
active ? 'bg-orange-500/50 text-white' : 'text-white',
169+
active ? 'bg-orange-500/50 text-white dark:text-white' : 'text-gray-700 dark:text-white',
170170
'group flex w-full items-center rounded-md px-2 py-2 text-sm',
171171
]"
172172
>
@@ -189,7 +189,7 @@ const route = useRoute();
189189
<a href="https://bsky.app/profile/colton.boo">
190190
<button
191191
:class="[
192-
active ? 'bg-orange-500/50 text-white' : 'text-white',
192+
active ? 'bg-orange-500/50 text-white dark:text-white' : 'text-gray-700 dark:text-white',
193193
'group flex w-full items-center rounded-md px-2 py-2 text-sm',
194194
]"
195195
>
@@ -208,6 +208,57 @@ const route = useRoute();
208208
</a>
209209
</HeadlessMenuItem>
210210
</div>
211+
212+
<!-- Divider -->
213+
<div class="border-t border-gray-300 dark:border-gray-600"></div>
214+
215+
<!-- Theme Toggle Section -->
216+
<div class="px-1 py-1">
217+
<HeadlessMenuItem v-slot="{ active }">
218+
<button
219+
@click="$colorMode.preference = $colorMode.value === 'dark' ? 'light' : 'dark'"
220+
:class="[
221+
active ? 'bg-orange-500/50 text-white dark:text-white' : 'text-gray-700 dark:text-white',
222+
'group flex w-full items-center rounded-md px-2 py-2 text-sm',
223+
]"
224+
>
225+
<!-- Sun icon for when we're in dark mode (clicking switches to light) -->
226+
<svg
227+
v-if="$colorMode.value === 'dark'"
228+
class="mr-2 inline h-5 w-5"
229+
fill="none"
230+
stroke="currentColor"
231+
viewBox="0 0 24 24"
232+
xmlns="http://www.w3.org/2000/svg"
233+
>
234+
<path
235+
stroke-linecap="round"
236+
stroke-linejoin="round"
237+
stroke-width="2"
238+
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"
239+
/>
240+
</svg>
241+
242+
<!-- Moon icon for when we're in light mode (clicking switches to dark) -->
243+
<svg
244+
v-else
245+
class="mr-2 inline h-5 w-5"
246+
fill="none"
247+
stroke="currentColor"
248+
viewBox="0 0 24 24"
249+
xmlns="http://www.w3.org/2000/svg"
250+
>
251+
<path
252+
stroke-linecap="round"
253+
stroke-linejoin="round"
254+
stroke-width="2"
255+
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"
256+
/>
257+
</svg>
258+
<span class="translate-y-0.5">{{ $colorMode.value === 'dark' ? 'Light Mode' : 'Dark Mode' }}</span>
259+
</button>
260+
</HeadlessMenuItem>
261+
</div>
211262
</HeadlessMenuItems>
212263
</transition>
213264
</HeadlessMenu>

components/MoreLink.vue

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ const props = defineProps({
1313
<div class="flex justify-end">
1414
<NuxtLink
1515
:to="props.to"
16-
class="flex items-center text-sm font-bold text-white hover:text-orange-500"
16+
class="flex items-center text-sm font-bold text-gray-700 dark:text-white hover:text-orange-500"
1717
>
1818
<span class="translate-y-0.5">See More</span>
1919
<CursorArrowRaysIcon class="ml-1 h-5 w-5" aria-hidden="true" />

components/ThemeToggle.vue

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
<template>
2+
<button
3+
@click="toggleTheme"
4+
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"
5+
:title="$colorMode.value === 'dark' ? 'Switch to light mode' : 'Switch to dark mode'"
6+
>
7+
<!-- Sun icon for light mode -->
8+
<svg
9+
v-if="$colorMode.value === 'dark'"
10+
class="w-5 h-5 text-yellow-500 dark:text-yellow-400"
11+
fill="none"
12+
stroke="currentColor"
13+
viewBox="0 0 24 24"
14+
xmlns="http://www.w3.org/2000/svg"
15+
>
16+
<path
17+
stroke-linecap="round"
18+
stroke-linejoin="round"
19+
stroke-width="2"
20+
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"
21+
/>
22+
</svg>
23+
24+
<!-- Moon icon for dark mode -->
25+
<svg
26+
v-else
27+
class="w-5 h-5 text-gray-700 dark:text-gray-300"
28+
fill="none"
29+
stroke="currentColor"
30+
viewBox="0 0 24 24"
31+
xmlns="http://www.w3.org/2000/svg"
32+
>
33+
<path
34+
stroke-linecap="round"
35+
stroke-linejoin="round"
36+
stroke-width="2"
37+
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"
38+
/>
39+
</svg>
40+
</button>
41+
</template>
42+
43+
<script setup>
44+
const { $colorMode } = useNuxtApp()
45+
46+
const toggleTheme = () => {
47+
$colorMode.preference = $colorMode.value === 'dark' ? 'light' : 'dark'
48+
}
49+
</script>

components/section/BlogPosts.vue

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,14 +6,14 @@ const props = defineProps({
66
</script>
77

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

1212
<div class="mb-4 grid grid-cols-1 gap-4 md:grid-cols-2">
1313
<div v-for="(article, ix) of articles" :key="ix">
1414
<NuxtLink :to="article.path">
1515
<div
16-
class="h-full space-y-4 rounded-lg bg-white/20 p-4 text-white drop-shadow-lg hover:ring-1 hover:ring-white"
16+
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"
1717
>
1818
<div>
1919
<div class="flex-1 text-lg font-bold md:text-xl">
@@ -22,13 +22,13 @@ const props = defineProps({
2222
<NuxtTime
2323
v-if="show_dates"
2424
:datetime="article.date"
25-
class="text-sm font-light text-gray-400"
25+
class="text-sm font-light text-gray-600 dark:text-gray-400"
2626
year="numeric"
2727
month="short"
2828
day="2-digit"
2929
/>
3030
</div>
31-
<div class="line-clamp-3 text-sm text-gray-300">
31+
<div class="line-clamp-3 text-sm text-gray-700 dark:text-gray-300">
3232
{{ article.description }}
3333
</div>
3434
</div>

components/section/Playground.vue

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -99,12 +99,12 @@ const filtered_links = computed(() => {
9999
</script>
100100

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

105105
<div class="mb-4 grid grid-cols-1 gap-4 sm:grid-cols-2 lg:grid-cols-3">
106106
<nuxt-link
107-
class="relative rounded-lg drop-shadow-lg hover:ring-1 hover:ring-white"
107+
class="relative rounded-lg drop-shadow-lg hover:ring-1 hover:ring-gray-300 dark:hover:ring-white"
108108
v-for="link in filtered_links"
109109
:key="link.title"
110110
:to="link.link"
@@ -116,12 +116,12 @@ const filtered_links = computed(() => {
116116
<div
117117
class="absolute bottom-0 flex w-full items-center justify-center"
118118
>
119-
<div class="min-h-24 w-full rounded-b-lg bg-gray-800/80 px-6 py-2">
120-
<h3 class="text-xl font-bold text-white">
119+
<div class="min-h-24 w-full rounded-b-lg bg-white/90 dark:bg-gray-800/80 px-6 py-2">
120+
<h3 class="text-xl font-bold text-gray-700 dark:text-white">
121121
{{ link.title }}
122122
</h3>
123123
<div
124-
class="line-clamp-2 text-sm text-gray-300"
124+
class="line-clamp-2 text-sm text-gray-700 dark:text-gray-300"
125125
v-html="link.description"
126126
></div>
127127
</div>

layouts/default.vue

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
<template>
22
<div class="bg-gradient-to-b from-orange-500 to-red-500">
33
<div class="p-[10px]">
4-
<main class="flex h-[calc(100vh-20px)] flex-col rounded-3xl bg-background font-display">
4+
<main class="flex h-[calc(100vh-20px)] flex-col rounded-3xl bg-background dark:bg-background-dark font-display">
55
<Header />
66
<main class="flex-1 overflow-scroll no-scrollbar">
77
<slot />

nuxt.config.ts

Lines changed: 18 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,28 @@
11
// https://nuxt.com/docs/api/configuration/nuxt-config
22
export default defineNuxtConfig({
33
components: true,
4-
modules: ["@nuxt/content", "@nuxtjs/tailwindcss", "nuxt-headlessui"],
4+
modules: ["@nuxt/content", "@nuxtjs/tailwindcss", "@nuxtjs/color-mode", "nuxt-headlessui"],
55

66
app: {
77
head: {
88
bodyAttrs: {
9-
class: 'bg-background'
9+
class: 'bg-background dark:bg-background-dark'
1010
}
1111
}
1212
},
1313

14+
// Color mode configuration
15+
colorMode: {
16+
preference: 'system', // default value of $colorMode.preference
17+
fallback: 'dark', // fallback value if not system preference found
18+
hid: 'nuxt-color-mode-script',
19+
globalName: '__NUXT_COLOR_MODE__',
20+
componentName: 'ColorScheme',
21+
classPrefix: '',
22+
classSuffix: '',
23+
storageKey: 'nuxt-color-mode'
24+
},
25+
1426
// Optionally change the default prefix.
1527
headlessui: {
1628
prefix: "Headless",
@@ -22,7 +34,10 @@ export default defineNuxtConfig({
2234
// Disable highlighting until interoperability with by the Tailwind Typography plugin is sorted
2335
// highlight: false
2436
highlight: {
25-
theme: 'github-dark',
37+
theme: {
38+
light: 'github-light',
39+
default: 'github-dark'
40+
},
2641
preload: [
2742
'bash',
2843
'js',

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
"webpack": "^5.99.9"
2424
},
2525
"dependencies": {
26+
"@nuxtjs/color-mode": "^3.5.2",
2627
"chords.ts": "^0.1.0",
2728
"p5": "^1.11.7",
2829
"tailwindcss": "^3.4.17"

pages/articles/[...slug].vue

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,8 @@ const { data: page } = await useAsyncData(route.path, () => {
1414
</script>
1515

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

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

5252
<div>
53-
<div class="mb-2 text-xs uppercase text-gray-400">Tags</div>
53+
<div class="mb-2 text-xs uppercase text-gray-600 dark:text-gray-400">Tags</div>
5454
<div class="flex flex-row md:space-x-2">
5555
<NuxtLink
56-
class="mr-2 w-min rounded-md bg-background text-sm font-bold hover:cursor-pointer hover:text-orange-500"
56+
class="mr-2 w-min rounded-md bg-background dark:bg-background-dark text-sm font-bold hover:cursor-pointer hover:text-orange-500"
5757
v-for="(tag, ix) in page.tags"
5858
:key="ix"
5959
:to="`/articles?tag=${tag}`"
@@ -69,7 +69,7 @@ const { data: page } = await useAsyncData(route.path, () => {
6969
- Use prose-pre:bg-white to work with @nuxt/content syntax highlighting, otherwise background-color defaults to `.prose:where(pre)`
7070
-->
7171
<article
72-
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"
72+
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"
7373
>
7474
<ContentRenderer v-if="page" :value="page" />
7575
</article>

0 commit comments

Comments
 (0)