Closed Soletiq closed 3 years ago
Thought about doing something for this in v3, though there is already some overlap of being able to do this in userland naturally, as well as through presets.
Vuetify most of time used to create Admin application, light theme is well enough to most company, Vuetify should concentrate on its core.
@Soletiq I keep an array of themes in my store and switch between them with a simple mutation and Object.assign
I would also like to have multiple themes, I heavily customize colors and override the sass variables. And Themes would be used for different parts of the app. blue theme - selling green theme - buying yellow - search
i found this mixin in the src but im not sure how to override it from outside and make it more programmatic.
` @mixin theme ($component) .theme--light.#{$component} @content($material-light) .theme--dark.#{$component} @content($material-dark)
`
Would be very thankful if someone could point me to a way in doing that if possible
This is happening implicity for version 3. Please follow https://github.com/vuetifyjs/vuetify/issues/12688 for updates.
If you have any additional questions, please reach out to us in our Discord community.
I know this issue is closed but it still comes up in search engine results, so for anyone else looking to implement such a thing here's my code.
In plugins/vuetify.js
I store my extra themes, but really you could store these anywhere in your app that makes sense to you:
import Vue from 'vue'
import Vuetify from 'vuetify/lib/framework'
Vue.use(Vuetify)
export default new Vuetify({
theme: {
options: { customProperties: true },
themes: {
blue: {
accent: '#82B1FF',
error: '#FF5252',
info: '#2196F3',
primary: '#1976D2',
secondary: '#424242',
success: '#4CAF50',
warning: '#f88C00'
},
green: {
accent: '#CDDC39',
error: '#ff5722',
info: '#1976D2',
primary: '#4caf50',
secondary: '#009688',
success: '#1976D2',
warning: '#ff9800'
}
}
}
})
In plugins/store.js
I made a mutation that applies the theme when they're set in the store:
import Vue from 'vue'
import Vuex from 'vuex'
// Importing the vuetify instantiation, not the Vuetify framework itself
import vuetify from '@/plugins/vuetify'
Vue.use(Vuex)
export default new Vuex.Store({
state: {
preferencesDrawer: false,
preferences: {
contrast: 'light',
theme: 'blue'
}
},
mutations: {
// Same theme is used in a light and dark variant, e.g. light green and dark green
setTheme(state, theme) {
Vue.set(state.preferences, 'theme', theme)
vuetify.framework.theme.themes.dark = vuetify.userPreset.theme.themes[theme]
vuetify.framework.theme.themes.light = vuetify.userPreset.theme.themes[theme]
},
// Now you can switch between the light and dark version of the green theme
setContrast(state, contrast) {
Vue.set(state.preferences, 'contrast', contrast)
vuetify.framework.theme.dark = contrast === 'dark'
}
}
})
And then somewhere in the UI you can interface with the store.
PreferencesDrawer.vue
:
<template>
<v-navigation-drawer v-model="open" fixed right temporary>
<v-list-item>
<v-select label="color theme" :items="themeOptions" v-model="theme" />
</v-list-item>
<v-list-item>
<v-select label="contrast" :items="contrastOptions" v-model="contrast" />
</v-list-item>
</v-navigation-drawer>
</template>
<script>
export default {
data() {
return {
themeOptions: [
{
text: 'blue',
value: 'blue'
},
{
text: 'green',
value: 'green'
}
],
contrastOptions: [
{
text: 'dark',
value: 'dark'
},
{
text: 'light',
value: 'light'
}
]
}
},
computed: {
// Open/close this whole drawer menu
open: {
get() {
return this.$store.state.preferencesDrawer
},
set(value) {
this.$store.commit('setPreferencesDrawer', value)
}
},
theme: {
get() {
return this.$store.state.preferences.theme
},
set(theme) {
this.$store.commit('setTheme', theme)
}
},
contrast: {
get() {
return this.$store.state.preferences.contrast
},
set(contrast) {
this.$store.commit('setContrast', contrast)
}
}
}
}
</script>
Cheers.
Here is a workaround fir Vuetify 2 allowing to use a custom theme locally:
<template>
<div :class="{ [className]: true }">
<style v-if="css">{{ css }}</style>
<slot name="default"></slot>
</div>
</template>
<script>
import Vue from 'vue'
import { genStyles, parse } from 'vuetify/lib/services/theme/utils'
export default Vue.extend({
name: 'x-custom-theme',
props: {
colors: { type: Object, default: () => null },
},
computed: {
className() {
return `x-custom-theme--theme-${this._uid}`
},
css() {
if (!this.colors) return null
try {
const { primary, anchor } = this.$vuetify.theme.currentTheme
const theme = { primary, anchor, ...this.colors }
return genStyles(parse(theme)).replaceAll(
'.v-application ',
`.v-application .${this.className} `
)
} catch (err) {
console.warn(`Failed to generate local theme:`, err)
return null
}
},
},
})
</script>
You can use this as:
<x-custom-theme :colors="{ primary: '#ffeeaaa' }">
<v-btn color="primary">Click here</v-btn>
</x-custom-theme>
Note this is quite hackish ;-) (e.g. $vuetify.theme.currentTheme
will not have the right value within the component).
Problem to solve
Currently, it seems I can only create 1 light and dark theme. But I want the capability of being able to create multiple themes each with their own light and dark variants.
Proposed solution
Allow us to provide an array of themes and select which theme is active.