SwitchAppearance.vue 1.3 KB

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