theme
Gitea Actions Demo / Deploy (push) Successful in 45s

This commit is contained in:
vadim committed 2026-10-01 10:01:23 +03:00
1 parent c03f9826af
commit 1274dece67
4 files changed
+56 -14

No files matched your search

+20
View File
@@ -0,0 +1,20 @@
import { watch } from 'vue'
import { useTheme } from 'vuetify'
import { useStorage } from '@vueuse/core'
import { THEME_MODES, THEME_STORAGE_KEY, type ThemeMode } from '@/lib/theme.ts'
/** Persisted light/dark/system theme mode, cycled in that order on each call to `cycleThemeMode`. */
export function useThemeMode() {
const theme = useTheme()
const mode = useStorage<ThemeMode>(THEME_STORAGE_KEY, 'system')
watch(mode, (value) => theme.change(value), { immediate: true })
function cycleThemeMode(e?: MouseEvent) {
if (e) theme.setTransitionOrigin(e.target as HTMLElement)
const nextIndex = (THEME_MODES.indexOf(mode.value) + 1) % THEME_MODES.length
mode.value = THEME_MODES[nextIndex]
}
return { mode, cycleThemeMode }
}
+13 -13
View File
@@ -2,17 +2,17 @@
import { useRouter } from 'vue-router' import { useRouter } from 'vue-router'
import { authClient } from '@/lib/auth-client.ts' import { authClient } from '@/lib/auth-client.ts'
import { computed, ref } from 'vue' import { computed, ref } from 'vue'
import { useTheme } from 'vuetify'
import ProjectMenu from '@/components/ProjectMenu.vue' import ProjectMenu from '@/components/ProjectMenu.vue'
import AppBreadcrumbs from '@/components/AppBreadcrumbs.vue' import AppBreadcrumbs from '@/components/AppBreadcrumbs.vue'
import BackButton from '@/components/BackButton.vue' import BackButton from '@/components/BackButton.vue'
import { useThemeMode } from '@/composables/useThemeMode.ts'
import { THEME_ICONS } from '@/lib/theme.ts'
const router = useRouter() const router = useRouter()
const session = authClient.useSession() const session = authClient.useSession()
const theme = useTheme() const { mode: themeMode, cycleThemeMode } = useThemeMode()
const title = 'APP' const title = 'Ulitka'
const version = '0.0.1'
const isAuth = computed(() => !!session.value.data) const isAuth = computed(() => !!session.value.data)
@@ -56,12 +56,6 @@ async function goToSignOut() {
}) })
} }
function toggleTheme(e: MouseEvent) {
const target = e.target as HTMLElement
theme.setTransitionOrigin(target)
theme.toggle()
}
const goToSettings = () => { const goToSettings = () => {
router.push({ name: 'settings' }) router.push({ name: 'settings' })
} }
@@ -90,8 +84,9 @@ const goToSettings = () => {
</template> </template>
<v-divider class="mx-1" vertical /> <v-divider class="mx-1" vertical />
<v-app-bar-title> <v-app-bar-title>
<router-link class="text-decoration-none text-link font-weight-bold" to="/"> <router-link class="text-decoration-none text-link font-weight-bold d-flex align-baseline ga-2" to="/">
{{ title }} <v-icon icon="mdi-snail" />
<div>{{ title }}</div>
</router-link> </router-link>
</v-app-bar-title> </v-app-bar-title>
@@ -113,7 +108,12 @@ const goToSettings = () => {
</div> </div>
<v-divider class="mx-2" vertical /> <v-divider class="mx-2" vertical />
<v-btn icon="mdi-brightness-6" density="comfortable" @click="toggleTheme" /> <v-btn
:icon="THEME_ICONS[themeMode]"
:title="`Theme: ${themeMode}`"
density="comfortable"
@click="cycleThemeMode"
/>
<v-divider class="mx-2" vertical /> <v-divider class="mx-2" vertical />
<div v-if="session.data"> <div v-if="session.data">
+21
View File
@@ -0,0 +1,21 @@
export type ThemeMode = 'light' | 'dark' | 'system'
export const THEME_MODES: ThemeMode[] = ['light', 'dark', 'system']
export const THEME_STORAGE_KEY = 'theme-mode'
export const THEME_ICONS: Record<ThemeMode, string> = {
light: 'mdi-white-balance-sunny',
dark: 'mdi-weather-night',
system: 'mdi-theme-light-dark',
}
export function isThemeMode(value: unknown): value is ThemeMode {
return THEME_MODES.includes(value as ThemeMode)
}
/** Read the persisted theme mode synchronously, before Vuetify is created, to avoid a flash of the wrong theme. */
export function readStoredThemeMode(): ThemeMode {
if (typeof localStorage === 'undefined') return 'system'
const stored = localStorage.getItem(THEME_STORAGE_KEY)
return isThemeMode(stored) ? stored : 'system'
}
+2 -1
View File
@@ -14,6 +14,7 @@ import * as components from 'vuetify/components'
import { VAvatarGroup } from 'vuetify/labs/VAvatarGroup' import { VAvatarGroup } from 'vuetify/labs/VAvatarGroup'
import * as directives from 'vuetify/directives' import * as directives from 'vuetify/directives'
import { registerLayouts } from '@/layouts/register.ts' import { registerLayouts } from '@/layouts/register.ts'
import { readStoredThemeMode } from '@/lib/theme.ts'
const app = createApp(App) const app = createApp(App)
@@ -24,7 +25,7 @@ const vuetify = createVuetify({
components: { ...components, VAvatarGroup }, components: { ...components, VAvatarGroup },
directives, directives,
theme: { theme: {
defaultTheme: 'dark', // 'system' | 'light' | 'dark' defaultTheme: readStoredThemeMode(),
themes: { themes: {
dark: { dark: {
colors: { colors: {