Page Menu
Home
DevCentral
Search
Configure Global Search
Log In
Files
F24848336
D3989.id10397.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Award Token
Flag For Later
Size
3 KB
Referenced Files
None
Subscribers
None
D3989.id10397.diff
View Options
diff --git a/frontend/src/components/AppNavbar.vue b/frontend/src/components/AppNavbar.vue
--- a/frontend/src/components/AppNavbar.vue
+++ b/frontend/src/components/AppNavbar.vue
@@ -3,9 +3,11 @@
import { RouterLink } from 'vue-router'
import { configApi } from '@/plugins/api'
import { useAuth } from '@/composables/useAuth'
+import { useDarkMode } from '@/composables/useDarkMode'
const config = ref(null)
const { isAuthenticated, logout } = useAuth()
+const { isDark, toggle } = useDarkMode()
onMounted(async () => {
try {
@@ -63,6 +65,21 @@
Admin
</RouterLink>
+ <!-- Dark mode toggle: switches between sun (light) and moon (dark) icons -->
+ <button
+ @click="toggle"
+ class="text-gray-400 hover:text-white transition-colors"
+ :aria-label="isDark ? 'Switch to light mode' : 'Switch to dark mode'"
+ >
+ <!-- Moon icon: shown in light mode -->
+ <svg v-if="!isDark" xmlns="http://www.w3.org/2000/svg" class="h-4 w-4" fill="none" viewBox="0 0 24 24" stroke="currentColor">
+ <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M21 12.79A9 9 0 1111.21 3a7 7 0 109.79 9.79z" />
+ </svg>
+ <!-- Sun icon: shown in dark mode -->
+ <svg v-else xmlns="http://www.w3.org/2000/svg" class="h-4 w-4" fill="none" viewBox="0 0 24 24" stroke="currentColor">
+ <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 3v1m0 16v1m9-9h-1M4 12H3m15.364-6.364l-.707.707M6.343 17.657l-.707.707M17.657 17.657l-.707-.707M6.343 6.343l-.707-.707M12 8a4 4 0 100 8 4 4 0 000-8z" />
+ </svg>
+ </button>
</div>
</div>
</div>
diff --git a/frontend/src/composables/useDarkmode.js b/frontend/src/composables/useDarkmode.js
new file mode 100644
--- /dev/null
+++ b/frontend/src/composables/useDarkmode.js
@@ -0,0 +1,30 @@
+import { ref } from 'vue'
+
+const STORAGE_KEY = 'servpulse_dark_mode'
+
+// Shared state across all composable instances
+const isDark = ref(false)
+
+const applyDark = (value) => {
+ // Toggle the 'dark' class on <html> for Tailwind dark mode
+ document.documentElement.classList.toggle('dark', value)
+ localStorage.setItem(STORAGE_KEY, value ? 'dark' : 'light')
+ isDark.value = value
+}
+
+const initDarkMode = () => {
+ const saved = localStorage.getItem(STORAGE_KEY)
+ if (saved) {
+ // Use saved preference
+ applyDark(saved === 'dark')
+ } else {
+ // Fall back to system preference
+ applyDark(window.matchMedia('(prefers-color-scheme: dark)').matches)
+ }
+}
+
+const toggle = () => applyDark(!isDark.value)
+
+export function useDarkMode() {
+ return { isDark, toggle, initDarkMode }
+}
diff --git a/frontend/src/main.js b/frontend/src/main.js
--- a/frontend/src/main.js
+++ b/frontend/src/main.js
@@ -3,6 +3,10 @@
import { createApp } from 'vue'
import App from './App.vue'
import router from './router'
+import { useDarkMode } from '@/composables/useDarkMode'
+
+// Apply dark mode before app mounts to avoid flash
+useDarkMode().initDarkMode()
const app = createApp(App)
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Sun, Mar 15, 03:00 (5 h, 27 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
3530009
Default Alt Text
D3989.id10397.diff (3 KB)
Attached To
Mode
D3989: Add dark mode toggle button
Attached
Detach File
Event Timeline
Log In to Comment