Skip to content

Commit b4cffb0

Browse files
✨ Add dark mode
1 parent 8ef13e1 commit b4cffb0

File tree

7 files changed

+255
-2
lines changed

7 files changed

+255
-2
lines changed

package-lock.json

Lines changed: 8 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
},
88
"devDependencies": {
99
"@alpinejs/collapse": "^3.14.9",
10+
"@alpinejs/persist": "^3.14.9",
1011
"@fontsource/poppins": "^5.2.5",
1112
"@tailwindcss/typography": "^0.5.16",
1213
"alpinejs": "^3.14.9",

resources/js/app.js

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import './fonts'
22
import './bootstrap'
33
import Alpine from 'alpinejs'
44
import collapse from '@alpinejs/collapse'
5+
import persist from '@alpinejs/persist'
56
import codeBlock from './alpine/codeBlock.js'
67
import.meta.glob(['../images/**', '../svg/**'])
78
import {
@@ -20,6 +21,7 @@ import {
2021
anticipate,
2122
spring,
2223
stagger,
24+
cubicBezier,
2325
} from 'motion'
2426

2527
// Motion
@@ -39,6 +41,7 @@ window.motion = {
3941
anticipate: anticipate,
4042
spring: spring,
4143
stagger: stagger,
44+
cubicBezier: cubicBezier,
4245
}
4346

4447
// Alpine
@@ -52,4 +55,5 @@ Alpine.magic('refAll', (el) => {
5255
})
5356

5457
Alpine.plugin(collapse)
58+
Alpine.plugin(persist)
5559
Alpine.start()

resources/views/components/layout.blade.php

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,13 @@
11
<!DOCTYPE html>
2-
<html lang="{{ str_replace('_', '-', app()->getLocale()) }}">
2+
<html
3+
lang="{{ str_replace('_', '-', app()->getLocale()) }}"
4+
x-data="{
5+
darkMode: $persist(
6+
window.matchMedia('(prefers-color-scheme: dark)').matches,
7+
),
8+
}"
9+
x-bind:class="{ 'dark': darkMode === true }"
10+
>
311
<head>
412
<meta
513
http-equiv="Content-Security-Policy"

resources/views/components/navigation-bar.blade.php

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,15 +8,18 @@ class="sticky top-0 z-50 flex flex-col items-center justify-center px-3"
88
:class="scrolled ? 'ring-gray-200/80 dark:ring-gray-800/50 translate-y-3 bg-white/50 dark:bg-white/5' : 'ring-transparent dark:bg-transparent'"
99
class="2xl:max-w-8xl mx-auto flex w-full max-w-5xl items-center justify-between gap-5 rounded-2xl px-5 py-4 ring-1 backdrop-blur-md transition duration-200 ease-out xl:max-w-7xl"
1010
>
11-
{{-- Logo --}}
11+
{{-- Left side --}}
1212
<div class="flex items-center gap-3">
13+
{{-- Logo --}}
1314
<a
1415
href="/"
1516
aria-label="NativePHP Homepage"
1617
>
1718
<x-logo class="h-5 sm:h-6" />
1819
<span class="sr-only">NativePHP</span>
1920
</a>
21+
22+
{{-- Version badge --}}
2023
<div
2124
class="hidden rounded-full bg-gray-200/60 px-2 py-1 text-xs text-gray-600 lg:block dark:bg-[#1f2032] dark:text-white/50"
2225
aria-label="Version information"
@@ -25,6 +28,7 @@ class="hidden rounded-full bg-gray-200/60 px-2 py-1 text-xs text-gray-600 lg:blo
2528
</div>
2629
</div>
2730

31+
{{-- Right side --}}
2832
<div class="flex items-center gap-3">
2933
{{-- Doc search --}}
3034
<div>
@@ -34,11 +38,16 @@ class="hidden rounded-full bg-gray-200/60 px-2 py-1 text-xs text-gray-600 lg:blo
3438
aria-label="Search documentation"
3539
></div>
3640
</div>
41+
3742
{{-- Desktop menu --}}
3843
<div
3944
class="flex items-center gap-3.5 text-sm"
4045
aria-label="Primary navigation"
4146
>
47+
{{-- Theme toggle --}}
48+
<x-theme-toggle />
49+
50+
{{-- Link --}}
4251
<a
4352
href="/"
4453
@class([
@@ -50,10 +59,14 @@ class="flex items-center gap-3.5 text-sm"
5059
>
5160
Home
5261
</a>
62+
63+
{{-- Decorative circle --}}
5364
<div
5465
class="hidden size-[3px] rotate-45 rounded-sm bg-gray-400 lg:block"
5566
aria-hidden="true"
5667
></div>
68+
69+
{{-- Link --}}
5770
<a
5871
href="{{ route('early-adopter') }}"
5972
@class([
@@ -65,6 +78,7 @@ class="hidden size-[3px] rotate-45 rounded-sm bg-gray-400 lg:block"
6578
>
6679
Mobile
6780
</a>
81+
{{-- Decorative circle --}}
6882
<div
6983
class="hidden size-[3px] rotate-45 rounded-sm bg-gray-400 lg:block"
7084
aria-hidden="true"
Lines changed: 216 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,216 @@
1+
<div
2+
class="theme-selector relative h-11 w-11 cursor-pointer select-none hover:text-slate-600 dark:text-[#ABB0DD] dark:hover:text-[#bcc1ef]"
3+
x-on:click="darkMode = !darkMode"
4+
x-data="{
5+
nightToDay: [
6+
[
7+
'.theme-selector-moon',
8+
{
9+
opacity: [1, 0],
10+
transform:
11+
'translate(0%, -50%) translate(12px, 0px) rotate(70deg) scale(0.6, 0.6)',
12+
},
13+
{ duration: 0.3, ease: motion.easeOut },
14+
],
15+
16+
[
17+
'.theme-selector-mini-star',
18+
{ opacity: [1, 0], scale: [1, 0] },
19+
{ duration: 0.3, ease: motion.easeOut, at: 0 },
20+
],
21+
22+
[
23+
'.theme-selector-micro-star',
24+
{ opacity: [1, 0], scale: [1, 0] },
25+
{ duration: 0.3, ease: motion.easeOut, at: 0 },
26+
],
27+
28+
[
29+
'.theme-selector-sunball',
30+
{ opacity: [0, 1], x: [-5, 0], y: [-5, 0], scale: [0, 1] },
31+
{
32+
duration: 0.3,
33+
ease: motion.easeOut,
34+
at: 0.15,
35+
},
36+
],
37+
38+
[
39+
'.theme-selector-sunshine',
40+
{ opacity: [0, 1], scale: [0, 1], rotate: [-180, 0] },
41+
{
42+
duration: 0.3,
43+
ease: motion.easeOut,
44+
at: 0.15,
45+
},
46+
],
47+
],
48+
dayToNight: [
49+
[
50+
'.theme-selector-sunshine',
51+
{ opacity: [1, 0], scale: [1, 0], rotate: [0, -180] },
52+
{
53+
duration: 0.3,
54+
ease: motion.easeOut,
55+
},
56+
],
57+
58+
[
59+
'.theme-selector-sunball',
60+
{ opacity: [1, 0], x: [0, -5], y: [0, -5], scale: [1, 0] },
61+
{
62+
duration: 0.3,
63+
ease: motion.easeOut,
64+
at: 0.15,
65+
},
66+
],
67+
68+
[
69+
'.theme-selector-micro-star',
70+
{ opacity: [0, 1], scale: [0, 1] },
71+
{ duration: 0.3, ease: motion.easeOut, at: 0 },
72+
],
73+
74+
[
75+
'.theme-selector-mini-star',
76+
{ opacity: [0, 1], scale: [0, 1] },
77+
{ duration: 0.3, ease: motion.easeOut, at: 0 },
78+
],
79+
80+
[
81+
'.theme-selector-moon',
82+
{
83+
opacity: [0, 1],
84+
transform: 'translate(0%, -50%) translate(12px, 0px)',
85+
},
86+
{ duration: 0.3, ease: motion.easeOut, at: 0 },
87+
],
88+
],
89+
setInitialState() {
90+
// Set initial state directly without animation
91+
if (! darkMode) {
92+
document.querySelector('.theme-selector-sunball').style.opacity =
93+
'0'
94+
document.querySelector('.theme-selector-sunshine').style.opacity =
95+
'0'
96+
} else {
97+
document.querySelector('.theme-selector-moon').style.opacity = '0'
98+
document.querySelector('.theme-selector-mini-star').style.opacity =
99+
'0'
100+
document.querySelector('.theme-selector-micro-star').style.opacity =
101+
'0'
102+
}
103+
},
104+
init() {
105+
motion.animate($el, { scale: 1 }, { duration: 0.1 })
106+
107+
this.setInitialState()
108+
109+
// Watch for dark mode changes
110+
$watch('darkMode', (value) => {
111+
if (value) {
112+
motion.animate(this.nightToDay)
113+
} else {
114+
motion.animate(this.dayToNight)
115+
}
116+
})
117+
},
118+
}"
119+
>
120+
{{-- Moon --}}
121+
<div
122+
class="theme-selector-moon absolute right-1/2 top-1/2 -translate-y-1/2 translate-x-1/2"
123+
>
124+
<div class="-scale-x-100 transition duration-300">
125+
<svg
126+
xmlns="http://www.w3.org/2000/svg"
127+
width="24"
128+
height="24"
129+
viewBox="0 0 16 16"
130+
>
131+
<path
132+
fill="currentColor"
133+
d="M6 .278a.768.768 0 0 1 .08.858a7.208 7.208 0 0 0-.878 3.46c0 4.021 3.278 7.277 7.318 7.277c.527 0 1.04-.055 1.533-.16a.787.787 0 0 1 .81.316a.733.733 0 0 1-.031.893A8.349 8.349 0 0 1 8.344 16C3.734 16 0 12.286 0 7.71C0 4.266 2.114 1.312 5.124.06A.752.752 0 0 1 6 .278z"
134+
/>
135+
</svg>
136+
</div>
137+
</div>
138+
{{-- Mini star --}}
139+
<div class="theme-selector-mini-star absolute left-[.6rem] top-[.6rem]">
140+
<div class="transition duration-300">
141+
<svg
142+
xmlns="http://www.w3.org/2000/svg"
143+
width="7"
144+
height="7"
145+
viewBox="0 0 256 256"
146+
>
147+
<path
148+
fill="currentColor"
149+
d="M240 128a15.79 15.79 0 0 1-10.5 15l-63.44 23.07L143 229.5a16 16 0 0 1-30 0L89.93 166L26.5 143a16 16 0 0 1 0-30L90 89.93l23-63.43a16 16 0 0 1 30 0L166.07 90l63.43 23a15.79 15.79 0 0 1 10.5 15Z"
150+
/>
151+
</svg>
152+
</div>
153+
</div>
154+
{{-- Micro star --}}
155+
<div class="theme-selector-micro-star absolute left-[1rem] top-[1rem]">
156+
<div class="transition duration-300">
157+
<svg
158+
xmlns="http://www.w3.org/2000/svg"
159+
width="5"
160+
height="5"
161+
viewBox="0 0 256 256"
162+
>
163+
<path
164+
fill="currentColor"
165+
d="M240 128a15.79 15.79 0 0 1-10.5 15l-63.44 23.07L143 229.5a16 16 0 0 1-30 0L89.93 166L26.5 143a16 16 0 0 1 0-30L90 89.93l23-63.43a16 16 0 0 1 30 0L166.07 90l63.43 23a15.79 15.79 0 0 1 10.5 15Z"
166+
/>
167+
</svg>
168+
</div>
169+
</div>
170+
{{-- Sun ball --}}
171+
<div class="absolute right-1/2 top-1/2 -translate-y-1/2 translate-x-1/2">
172+
<div class="theme-selector-sunball">
173+
<div
174+
class="h-4 w-4 rounded-full bg-current transition duration-300"
175+
></div>
176+
</div>
177+
</div>
178+
{{-- sunShine --}}
179+
<div class="theme-selector-sunshine absolute inset-0 grid h-full w-full">
180+
<div class="relative h-full w-full">
181+
{{-- Top --}}
182+
<div
183+
class="absolute right-1/2 top-[0.5rem] h-[0.22rem] w-0.5 translate-x-1/2 rounded-full bg-current transition duration-300"
184+
></div>
185+
{{-- Right --}}
186+
<div
187+
class="absolute right-[0.5rem] top-1/2 h-[0.22rem] w-0.5 -translate-y-1/2 rotate-[90deg] rounded-full bg-current transition duration-300"
188+
></div>
189+
{{-- Bottom --}}
190+
<div
191+
class="absolute bottom-[0.5rem] right-1/2 h-[0.22rem] w-0.5 translate-x-1/2 rounded-full bg-current transition duration-300"
192+
></div>
193+
{{-- Left --}}
194+
<div
195+
class="absolute left-[0.5rem] top-1/2 h-[0.22rem] w-0.5 -translate-y-1/2 rotate-[90deg] rounded-full bg-current transition duration-300"
196+
></div>
197+
{{-- Top Right --}}
198+
<div
199+
class="absolute right-[0.75rem] top-[0.75rem] h-[0.22rem] w-0.5 rotate-[45deg] rounded-full bg-current transition duration-300"
200+
></div>
201+
{{-- Top Left --}}
202+
<div
203+
class="absolute left-[0.75rem] top-[0.75rem] h-[0.22rem] w-0.5 rotate-[-45deg] rounded-full bg-current transition duration-300"
204+
></div>
205+
206+
{{-- Bottom Right --}}
207+
<div
208+
class="absolute bottom-[0.75rem] right-[0.75rem] h-[0.22rem] w-0.5 rotate-[-45deg] rounded-full bg-current transition duration-300"
209+
></div>
210+
{{-- Bottom Left --}}
211+
<div
212+
class="absolute bottom-[0.75rem] left-[0.75rem] h-[0.22rem] w-0.5 rotate-[45deg] rounded-full bg-current transition duration-300"
213+
></div>
214+
</div>
215+
</div>
216+
</div>

tailwind.config.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@
22
const { fontFamily } = require('tailwindcss/defaultTheme')
33

44
export default {
5+
darkMode: 'selector',
6+
57
content: [
68
'./resources/**/*.{js,blade.php}',
79
'./vendor/laravel/framework/src/Illuminate/Pagination/resources/views/*.blade.php',

0 commit comments

Comments
 (0)