Files
veridian/app/components/ThemeSwitcher.vue
T
zoeissleeping 61c73f394d feat: improve mobile responsiveness across UI
Sidenav becomes a full-screen overlay on mobile with slide-in animation.
Dialog goes full-screen on small screens. Settings dialog gets a mobile
nav with hamburger menu. Touch targets and text sizes scaled up for
mobile. Slider gets visual checked/unchecked colors. Sidebar auto-closes
on mobile route navigation. Resize handle hidden on mobile.
2026-04-27 12:06:15 -05:00

53 lines
2.2 KiB
Vue

<script setup lang="ts">
import type { DropdownItem } from '~/types/dropdown';
const props = defineProps<{
size: 'small' | 'medium' | 'large';
}>();
type Theme = 'light' | 'dark' | 'system';
const { updateSettings, settings } = await useUserSettings();
const selectTheme = (colorScheme: Theme) => {
updateSettings({ appearance: { colorScheme } });
};
const themeOptions: DropdownItem[] = [
{ id: 'light', label: 'Light', icon: 'i-mynaui-sun', onClick: () => selectTheme('light') },
{ id: 'dark', label: 'Dark', icon: 'i-mynaui-moon', onClick: () => selectTheme('dark') },
{ id: 'system', label: 'System', icon: 'i-mynaui-desktop', onClick: () => selectTheme('system') },
];
const currentOption = computed(
() => themeOptions.find((option) => option.id === settings.value?.appearance?.colorScheme) || themeOptions[2],
);
</script>
<template>
<Dropdown placement="top-end" dropdown-class="min-w-35">
<template #default="{ toggle, setRef }">
<button :ref="setRef" @click="toggle"
class="flex items-center justify-center rounded-lg @hover:bg-[var(--color-hover)] focus-visible:bg-[var(--color-hover)] transition-colors active:text-[var(--text-primary)]"
:class="{
'h-9 w-9 md:h-7 md:w-7 text-5 md:text-6': size === 'small',
'h-9 w-9 text-6': size === 'medium',
'h-11 w-11 text-7': size === 'large',
}">
<span :class="['pointer-events-none', currentOption!.icon]"></span>
</button>
</template>
<template #dropdown="{ close }">
<button v-for="option in themeOptions" :key="option.id" @click="option.onClick!(); close()"
class="text-left px-3 py-1.5 items-center gap-1 @hover:bg-[var(--color-hover)] rounded-lg transition-colors duration-150"
:class="{
'bg-[var(--color-hover)]': option.id === currentOption?.id,
}">
<span class="text-4.5" :class="option.icon"></span>
<span class="text-sm whitespace-nowrap text-ellipsis max-w-full overflow-hidden">{{ option.label
}}</span>
</button>
</template>
</Dropdown>
</template>