Vuetify toggle between light and dark theme (with vuex)
Asked Answered
B

3

14

so in my Vue-project I basically have two pages/components that will be shown with the use of vue-router depending on the URL. I can switch between those pages/components via a button.

I am also using VueX for the management of some data.

Now I included a switch in one of the components to toggle between a dark and a light theme from Vuetify.

In the template for this component I do:

    <v-switch
      label="Toggle dark them"
      @change="toggleDarkTheme()"
    ></v-switch>

And in the function that gets called I do:

    toggleDarkTheme() {
          this.$vuetify.theme.dark = !this.$vuetify.theme.dark;
          console.log(this.$vuetify.theme.dark);
    },

In app.vue I have included the <v-app dark> and in my main.js i have the following:

    Vue.use(Vuetify);
    const vuetify = new Vuetify({
      theme: {
        // dark: true,
        themes: {
          light: {
            primary: colors.purple,
            secondary: colors.grey.darken1,
            accent: colors.shades.black,
            error: colors.red.accent3,
            background: colors.indigo.lighten5, 
          },
          dark: {
            primary: colors.blue.lighten3,
            background: colors.indigo.base,
          },
        },
      },
    });
    
    Vue.config.productionTip = false;
    
    new Vue({
      router,
      store,
      vuetify,
      render: (h) => h(App),
    }).$mount('#app');

So my problem now is, when I click the switch, the theme is indeed toggled from light to dark mode in this component. Light mode is the default and when I click the switch once, I get dark theme. However when I click the button to switch to the other URL, there the light theme will be used. How do I implement this feature correctly?

Thanks in advance!

Beret answered 25/5, 2020 at 15:43 Comment(0)
F
34

You should have a JavaScript class called vuetify.js, that should look like this in your case.

import Vue from "vue";
import Vuetify from "vuetify/lib";

Vue.use(Vuetify);

export default new Vuetify({
  theme: {
    themes: {
      light: {
        primary: colors.purple,
        secondary: colors.grey.darken1,
        accent: colors.shades.black,
        error: colors.red.accent3,
        background: colors.indigo.lighten5
      },
      dark: {
        primary: colors.blue.lighten3,
        background: colors.indigo.base
      }
    }
  }
});

Your switch should be working, but just in case, try this button I've made in your component.

    <div>
      <v-tooltip v-if="!$vuetify.theme.dark" bottom>
        <template v-slot:activator="{ on }">
          <v-btn v-on="on" color="info" small fab @click="darkMode">
            <v-icon class="mr-1">mdi-moon-waxing-crescent</v-icon>
          </v-btn>
        </template>
        <span>Dark Mode On</span>
      </v-tooltip>

      <v-tooltip v-else bottom>
        <template v-slot:activator="{ on }">
          <v-btn v-on="on" color="info" small fab @click="darkMode">
            <v-icon color="yellow">mdi-white-balance-sunny</v-icon>
          </v-btn>
        </template>
        <span>Dark Mode Off</span>
      </v-tooltip>
    </div>

The Button calls this method in your <script>

darkMode() {
      this.$vuetify.theme.dark = !this.$vuetify.theme.dark;
    }
Frodine answered 26/5, 2020 at 17:8 Comment(0)
M
4

The below code creates a dark mode toggle switch btn.

Note: Its use Localstore

DarkModeToggel.vue


<template>
   <v-icon class="mr-2">
      mdi-brightness-4
   </v-icon>
   <v-list-item-title class="pr-10">
      Dark Mode
   </v-list-item-title>
   <v-switch v-model="darkmode" color="primary" />
</template>

--

<script>
export default {
  data () {
    return {
      darkmode: false
    }
  },
  watch: {
    darkmode (oldval, newval) {
      this.handledarkmode()
    }
  },
  created () {
    if (process.browser) {
      if (localStorage.getItem('DarkMode')) {
        const cookieValue = localStorage.getItem('DarkMode') === 'true'
        this.darkmode = cookieValue
      } else {
        this.handledarkmode()
      }
    }
  },
  methods: {
    handledarkmode () {
      if (process.browser) {
        if (this.darkmode === true) {
          this.$vuetify.theme.dark = true
          localStorage.setItem('DarkMode', true)
        } else if (this.darkmode === false) {
          this.$vuetify.theme.dark = false
          localStorage.setItem('DarkMode', false)
        }
      }
    }
  }
}
</script>

@ckuessner answer is working but not persistent.

Mordy answered 23/6, 2021 at 21:34 Comment(0)
V
0

Here's simple example of button theme switcher with theme state persistence in cookies. Based on solution of @rohit-nishad.

A several ways of cookie manipulation:

The given example is implemented using cookie-universal-nuxt.

ColorThemeSwitch.vue

<template>
  <v-tooltip bottom>
    <template #activator="{ on }">
      <v-btn v-on="on" icon @click="switchTheme">
        <v-icon>
          {{ $vuetify.theme.dark ? 'mdi-white-balance-sunny' : 'mdi-moon-waxing-crescent' }}
        </v-icon>
      </v-btn>
    </template>
    <span>Change theme</span>
  </v-tooltip>
</template>

<script>
export default {
  created() {
    const darkModeCookie = this.$cookies.get('app.darkMode');
    if (darkModeCookie) {
      this.$vuetify.theme.dark = darkModeCookie;
    }
  },
  methods: {
    switchTheme() {
      this.$vuetify.theme.dark = !this.$vuetify.theme.dark;
      this.$cookies.set('app.darkMode', this.$vuetify.theme.dark);
    },
  },
};
</script>

It is better to put the code from 'created' hook somewhere in layouts or plugin so your app will change the theme no matter if component is presented on the current page. Example of plugin usage:

~/plugins/persistedThemeLoader.js

export default function ({ $vuetify, $cookies }) {
  const darkModeCookie = $cookies.get('app.darkMode');
  if (darkModeCookie) {
    $vuetify.theme.dark = darkModeCookie;
  }
}

nuxt.config.js

plugins: [
    '~/plugins/vuetify',
    { src: '~/plugins/persistedThemeLoader', mode: 'client' },
],
Vaginitis answered 16/6, 2022 at 21:12 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.