SwitchAppearance.vue 1.3 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162
  1. <script lang="ts" setup>
  2. import type { Ref } from 'vue'
  3. import VPSwitch from '@/components/VPSwitch/VPSwitch.vue'
  4. import { useSettingsStore } from '@/pinia'
  5. import VPIconMoon from './icons/VPIconMoon.vue'
  6. import VPIconSun from './icons/VPIconSun.vue'
  7. const settings = useSettingsStore()
  8. const devicePrefersTheme = inject('devicePrefersTheme') as Ref<string>
  9. const isDark = computed(() => settings.theme === 'dark')
  10. const switchTitle = computed(() => {
  11. return isDark.value ? $gettext('Switch to light theme') : $gettext('Switch to dark theme')
  12. })
  13. async function toggleAppearance() {
  14. if (isDark.value)
  15. settings.set_theme('light')
  16. else
  17. settings.set_theme('dark')
  18. if (devicePrefersTheme.value === settings.theme)
  19. settings.set_preference_theme('auto')
  20. else
  21. settings.set_preference_theme(settings.theme)
  22. }
  23. </script>
  24. <template>
  25. <VPSwitch
  26. :title="switchTitle"
  27. class="VPSwitchAppearance"
  28. :aria-checked="isDark"
  29. @click="toggleAppearance"
  30. >
  31. <VPIconSun class="sun" />
  32. <VPIconMoon class="moon" />
  33. </VPSwitch>
  34. </template>
  35. <style scoped>
  36. .sun {
  37. opacity: 1;
  38. }
  39. .moon {
  40. opacity: 0;
  41. }
  42. .dark .sun {
  43. opacity: 0;
  44. }
  45. .dark .moon {
  46. opacity: 1;
  47. }
  48. .dark .VPSwitchAppearance :deep(.check) {
  49. /*rtl:ignore*/
  50. transform: translateX(18px);
  51. }
  52. </style>