const themes: Themes = {
light: {
'bg-primary': 'blue',
'bg-secondary': 'white',
},
dark: {
'bg-primary': 'dark-blue',
'bg-secondary': 'black',
},
};
ThemeModule
Theme - модуль для темизации приложений (SPA/SSR)
Nuxt install
// nuxt.config.js
export default {
modules: ['shared-front/nuxt/theme'],
};
Module options
storeName
- type:
string - default:
'color-theme'
Ключ для хранения темы пользователя в Cookie и localStorage
themes
- type:
Themes - required:
false
Список тем с css переменными
interface Theme extends StylObject {}
interface Themes extends StylObject {
[key: string]: Theme;
}
Далее данный список доступен так же по алиасу #runtime/shared-front/themes.json и $themes переменной из stylus
Пример
themeContainer
- type:
string - default:
'html'
Контейнер в котором будет использоваться темизация
helperVariablePrefix
- type:
string - default:
'c-'
Префикс для сгенерированных css переменных
В модуле компонентов используются переменные с префиксом 'c-'
defaultColorTheme
- type:
string - default:
'light'
Цветовая тема по-умолчанию
themeSelector
- type:
string - default:
'&.theme-$s'
Аргумент для css-theme-generator
Vue install
Vue 2
// main.js
import Vue from 'vue';
import { Plugin, useThemeSymbol } from 'shared-front/lib/modules/theme';
Vue.use(Plugin, {
storeName: 'color-theme',
isClient: true,
});
const app = new Vue({
// For using `useTheme`
provide: {
[useThemeSymbol]: Vue.prototype.$theme,
},
});
Vue 3
// main.ts
import { createApp } from 'vue';
import { Plugin } from 'shared-front/lib/modules/theme';
import App from './App.vue';
const app = createApp(App);
app.use(Plugin, {
storeName: 'color-theme',
isClient: true,
});
Plugin options
storeName
- type:
string - default:
'color-theme'
Ключ для хранения темы пользователя в Cookie и localStorage
isClient
- type:
boolean - default:
true
Флаг, запущен ли плагин на клиенте. Если true, то инициализирует клиентскую логику
Stylus
Для подключения stylus миксинов необходимо импортировать shared-front/lib/nuxt-modules/theme/styles/index.styl
При использовании NuxtJS это будет сделано автоматически в модуле
Глобально
// stylus options
{
import: ['shared-front/lib/nuxt-modules/theme/dist/runtime/styles/index.styl'],
paths: [
path.resolve(__dirname, 'node_modules'),
],
},
В конкретном файле
@import 'node_modules/shared-front/lib/nuxt-modules/theme/dist/runtime/styles/index.styl'
defaultColorTheme
- type:
string - default:
'light'
Стандартная цветовая тема, от неё зависят селекторы в миксине theme
theme
Миксин для работы со стилями тем. Нужен для более удобного применения стилей, поскольку может быть случай когда у нас еще нет темы в куках или еще нет класса на документе и тогда используется prefers-color-scheme.
.foo
+theme('light')
color black
+theme('dark')
color white
themeName
- type:
string - default:
defaultColorTheme
selector
- type:
string - default:
'.theme-%s &'
%s - заменяется на themeName внутри миксина
Если класс темы находится на App Component и нужно задать какие-то стили/переменные для отдельных тем на нем же, selector может иметь вид &.theme-%s.
Example
// Input
html
+theme('light', '&.theme-%s')
color #000
+theme('dark', '&.theme-%s')
color #fff
// Output
html {
color: #000;
}
html.theme-light {
color: #000;
}
@media (prefers-color-scheme: dark) {
html {
color: #fff;
}
}
html.theme-dark {
color: #fff;
}
css-theme-generator
Генератор тем
Предпочтительный способ задания тем в css, т.к. цвета хранятся и в stylus и в css без дублирования кода
themes
- type:
object - required:
true
Объект тем вида { light: { text-primary: #fff } }
selector
- type:
string - default:
'&.theme-%s'
Селектор передаваемый в миксин theme
Example
// Input
html
$themes = {
light: {
text-primary: #000,
},
dark: {
text-primary: #fff,
},
}
css-theme-generator($themes)
// Output
html {
--c-text-primary: #000;
}
html.theme-light {
--c-text-primary: #000;
}
@media (prefers-color-scheme: dark) {
html {
--c-text-primary: #fff;
}
}
html.theme-dark {
--c-text-primary: #fff;
}
Usage
Перед самой стилизацией, нужно проставить класс текущей темы на контейнер. Класс должен иметь структуру ${prefixSelector}-${themeName}, prefixSelector из stylus. Далее в стилях приложения использовать stylus mixin theme.
<template>
<div class="app">
App
<div class="content">Some content</div>
</div>
</template>
<script>
import { useTheme } from 'shared-front/lib/modules/theme';
export default {
head() {
const htmlAttrs = {};
if (this.userTheme) htmlAttrs.class = `theme-${this.userTheme}`;
return { htmlAttrs };
},
computed: {
userTheme() {
return this.$theme.userTheme;
},
},
methods: {
setTheme(themeName) {
this.$theme.setTheme(themeName);
},
},
setup() {
const theme = useTheme();
const userTheme = computed(() => theme.userTheme);
const setTheme = (themeName) => theme.setTheme(themeName);
return {
userTheme,
setTheme,
};
},
};
</script>
<style lang="stylus">
$themes = {
light: {
text-primary: black,
bg-primary: white,
},
dark: {
text-primary: white,
bg-primary: black,
},
}
html
css-theme-generator($themes)
.content
transition color .25s, background .25s
color var(--c-text-primary)
backround var(--c-bg-primary)
:hover
+theme('light')
color dark-grey
+theme('dark')
color grey
</style>