Theme switch with scss

Forum rules
Please note that response time for technical support is within 3-5 business days.
Post Reply
TDZTechnika
Posts: 13
Joined: 02 Jun 2020, 13:43

06 Jun 2020, 14:04

I can see the theme is using css files to be able to switch the theme:

Code: Select all

changeTheme(theme) {
            this.theme = theme.split('-')[0];
			this.changeStyleSheetUrl('layout-css', theme, 'layout');
			this.changeStyleSheetUrl('theme-css', theme, 'theme');
		},
I would like to move .scss files to the /src/ folder to be abale to use scss variables (colors and font sizes) in my custom scss styles. But what I can see is the theme switch stops working. Is there any chance to have an example with having .scss files working and in the same time to keep theme switch ability working.

I guess all themes must be compiled into css in production or development mode.

Thanks
Last edited by TDZTechnika on 08 Jun 2020, 13:30, edited 1 time in total.

TDZTechnika
Posts: 13
Joined: 02 Jun 2020, 13:43

08 Jun 2020, 13:26

I am trying to do something as the example bellow. But I cannot get the results. I got the error:

Code: Select all

Module build failed (from ./node_modules/mini-css-extract-plugin/dist/loader.js):
ReferenceError: document is not defined
    at insertStyleElement (webpack-internal:///./node_modules/style-loader/dist/runtime/injectStylesIntoStyleTag.js:93:15)
    at addStyle (webpack-internal:///./node_modules/style-loader/dist/runtime/injectStylesIntoStyleTag.js:208:13)
    at modulesToDom (webpack-internal:///./node_modules/style-loader/dist/runtime/injectStylesIntoStyleTag.js:81:18)
    at module.exports (webpack-internal:///./node_modules/style-loader/dist/runtime/injectStylesIntoStyleTag.js:239:25)
    at eval (webpack-internal:///./node_modules/style-loader/dist/cjs.js!./node_modules/css-loader/dist/cjs.js!./node_modules/sass-loader/dist/cjs.js!./src/assets/theme/theme-yellow-light.scss:15:14)
    at Object../node_modules/style-loader/dist/cjs.js!./node_modules/css-loader/dist/cjs.js!./node_modules/sass-loader/dist/cjs.js!./src/assets/theme/theme-yellow-light.scss
Please let me guys know if you have a better idea or you can point me out in the right direction with my solution. Thanks.

Image
Last edited by TDZTechnika on 08 Jun 2020, 14:43, edited 4 times in total.

TDZTechnika
Posts: 13
Joined: 02 Jun 2020, 13:43

08 Jun 2020, 13:35

Also I tried to import scss based on the user setting but it is only working in development environment. In production build it stops working:

Image

TDZTechnika
Posts: 13
Joined: 02 Jun 2020, 13:43

08 Jun 2020, 15:00

Another solution is to change the theme scc styles in a way to make just one css bundle with the following aproach:

Code: Select all

<body class="theme-blue-light">
So we can change the theme by switching the class on the body.

Hope guys from primevue could join the conversation.

cagatay.civici
Prime
Posts: 18616
Joined: 05 Jan 2009, 00:21
Location: Cybertron
Contact:

06 Jul 2020, 12:22

The themes are loaded with script tags at demo for easy theme switching functionality, for sure they can be included to app so vue-cli can compile sass and add it to bundle. However we'd like to avoid doing that as there are so many themes with color alternatives and the bundle will be a big one so solution could be a configuration with lazy loaded themes similar to lazy loaded routing. This is an enhancement for future though, we're discussing this internally now with our team. Any feedback is welcome.

FairKing
Posts: 11
Joined: 23 Oct 2019, 15:14

06 Jul 2020, 17:55

Thanks for the reply.
I managed to solve the challenge.

Bellow is my code

vue.config.js:

Code: Select all

const webpack = require('webpack');
const path = require('path');
const isDevelopment = process.env.NODE_ENV === 'development';

var config = {};
if (isDevelopment) {
    // Development
} else {
    // Production
    config = {
        entry: {
            "assets/theme/theme-blue-light": [path.resolve(__dirname, 'src/assets/theme/theme-blue-light.scss')],
            "assets/theme/theme-blue-dark": [path.resolve(__dirname, 'src/assets/theme/theme-blue-dark.scss')],
            "assets/theme/theme-green-light": [path.resolve(__dirname, 'src/assets/theme/theme-green-light.scss')],
            "assets/theme/theme-green-dark": [path.resolve(__dirname, 'src/assets/theme/theme-green-dark.scss')],
            "assets/theme/theme-cyan-light": [path.resolve(__dirname, 'src/assets/theme/theme-cyan-light.scss')],
            "assets/theme/theme-cyan-dark": [path.resolve(__dirname, 'src/assets/theme/theme-cyan-dark.scss')],
            "assets/theme/theme-purple-light": [path.resolve(__dirname, 'src/assets/theme/theme-purple-light.scss')],
            "assets/theme/theme-purple-dark": [path.resolve(__dirname, 'src/assets/theme/theme-purple-dark.scss')],
            "assets/theme/theme-indigo-light": [path.resolve(__dirname, 'src/assets/theme/theme-indigo-light.scss')],
            "assets/theme/theme-indigo-dark": [path.resolve(__dirname, 'src/assets/theme/theme-indigo-dark.scss')],
            "assets/theme/theme-yellow-light": [path.resolve(__dirname, 'src/assets/theme/theme-yellow-light.scss')],
            "assets/theme/theme-yellow-dark": [path.resolve(__dirname, 'src/assets/theme/theme-yellow-dark.scss')],
            "assets/theme/theme-orange-light": [path.resolve(__dirname, 'src/assets/theme/theme-orange-light.scss')],
            "assets/theme/theme-orange-dark": [path.resolve(__dirname, 'src/assets/theme/theme-orange-dark.scss')],
            "assets/theme/theme-pink-light": [path.resolve(__dirname, 'src/assets/theme/theme-pink-light.scss')],
            "assets/theme/theme-pink-dark": [path.resolve(__dirname, 'src/assets/theme/theme-pink-dark.scss')],
            "assets/layout/css/layout-blue-light": [path.resolve(__dirname, 'src/assets/layout/css/layout-blue-light.scss')],
            "assets/layout/css/layout-blue-dark": [path.resolve(__dirname, 'src/assets/layout/css/layout-blue-dark.scss')],
            "assets/layout/css/layout-green-light": [path.resolve(__dirname, 'src/assets/layout/css/layout-green-light.scss')],
            "assets/layout/css/layout-green-dark": [path.resolve(__dirname, 'src/assets/layout/css/layout-green-dark.scss')],
            "assets/layout/css/layout-cyan-light": [path.resolve(__dirname, 'src/assets/layout/css/layout-cyan-light.scss')],
            "assets/layout/css/layout-cyan-dark": [path.resolve(__dirname, 'src/assets/layout/css/layout-cyan-dark.scss')],
            "assets/layout/css/layout-purple-light": [path.resolve(__dirname, 'src/assets/layout/css/layout-purple-light.scss')],
            "assets/layout/css/layout-purple-dark": [path.resolve(__dirname, 'src/assets/layout/css/layout-purple-dark.scss')],
            "assets/layout/css/layout-indigo-light": [path.resolve(__dirname, 'src/assets/layout/css/layout-indigo-light.scss')],
            "assets/layout/css/layout-indigo-dark": [path.resolve(__dirname, 'src/assets/layout/css/layout-indigo-dark.scss')],
            "assets/layout/css/layout-yellow-light": [path.resolve(__dirname, 'src/assets/layout/css/layout-yellow-light.scss')],
            "assets/layout/css/layout-yellow-dark": [path.resolve(__dirname, 'src/assets/layout/css/layout-yellow-dark.scss')],
            "assets/layout/css/layout-orange-light": [path.resolve(__dirname, 'src/assets/layout/css/layout-orange-light.scss')],
            "assets/layout/css/layout-orange-dark": [path.resolve(__dirname, 'src/assets/layout/css/layout-orange-dark.scss')],
            "assets/layout/css/layout-pink-light": [path.resolve(__dirname, 'src/assets/layout/css/layout-pink-light.scss')],
            "assets/layout/css/layout-pink-dark": [path.resolve(__dirname, 'src/assets/layout/css/layout-pink-dark.scss')],
        },
    };
}

module.exports = {
	publicPath: process.env.BASE_URL,
	assetsDir: process.env.BASE_URL,
    productionSourceMap: isDevelopment,
    configureWebpack: config,
};
BrowserSettings class (TypeScript):

Code: Select all

export class BrowserSettings {
	themeMode: string;
    layoutMode: string;
    colorMode: string;
	pageSize: number;
	constructor() {}
}
main.ts:

Code: Select all

/* Load Theme Css dynamically */
import { BrowserSettings } from "@/models/CoreModels";
var strSettings = localStorage.getItem("settings");
var themeMode = "light";
var colorMode = "blue";
if (strSettings) {
    var browserSettings = JSON.parse(strSettings || "{}") as BrowserSettings;
    themeMode = browserSettings.themeMode || "light";
    colorMode = browserSettings.colorMode || "blue";
}
if (process.env.NODE_ENV === "development") {
    require(`@/assets/theme/theme-${colorMode}-${themeMode}.scss`);
    require(`@/assets/layout/css/layout-${colorMode}-${themeMode}.scss`);
} else {
    var allStyles = {};
    let layoutStyles = document.querySelectorAll("head > link[href*='/assets/layout/css/layout-'][rel='stylesheet']");
    layoutStyles.forEach(function (item) {
        var themeHref = item.getAttribute("href");
        var key = themeHref.substring(themeHref.indexOf("/layout-") + 1, themeHref.indexOf(".css") - 9).replace(/-/g, "_");
        allStyles[key] = themeHref;
        if (key.indexOf(colorMode + "_" + themeMode) === -1) {
            document.head.removeChild(item);
        }
    });
    let themeStyles = document.querySelectorAll("head > link[href*='/assets/theme/theme-'][rel='stylesheet']");
    themeStyles.forEach(function (item) {
        var themeHref = item.getAttribute("href");
        var key = themeHref.substring(themeHref.indexOf("/theme-") + 1, themeHref.indexOf(".css") - 9).replace(/-/g, "_");
        allStyles[key] = themeHref;
        if (key.indexOf(colorMode + "_" + themeMode) === -1) {
            document.head.removeChild(item);
        }
    });
    Vue.mixin({
        data() {
            return {
                themeStyles: allStyles,
            }
        }
    });
}
App.vue:

Code: Select all

	methods: {
		...mapActions("browserSettings", ["setTheme", "setLayout", "setColor", "setPageSize"]), // vuex actions
		onThemeChange(themeMode) {
			this.setTheme(themeMode); // vuex action to save user preference
			this.changeTheme();
		},
		onLayoutChange(layoutMode) {
			this.setLayout(layoutMode); // vuex action to save user preference
		},
		onColorChange(colorMode) {
			this.setColor(colorMode); // vuex action to save user preference
			this.changeTheme();
		},
		onRowCountChange(rowCount) {
			this.setPageSize(rowCount); // vuex action to save user preference
		},
		changeTheme() {
			if (process.env.NODE_ENV === "development") {
				window.location.reload(false);
			} else {
				var theme = this.colorMode + "-" + this.themeMode;
				this.changeStyleSheetUrl(theme, "layout-", '/assets/layout/css/');
				this.changeStyleSheetUrl(theme, "theme-", '/assets/theme/');
				window.location.reload(false);
                	}
		},
		changeStyleSheetUrl(theme, prefix, path) {
			var themeHref = this.themeStyles[(prefix + theme).replace("-", "_")];
			if (themeHref) {
				let styles = document.querySelectorAll(`head > link[href*='${path}${prefix}'][rel='stylesheet']`);
				styles.forEach(function (item) { document.head.removeChild(item); });
				var newStyle = document.createElement('link');
				newStyle.setAttribute('href', themeHref);
				newStyle.setAttribute('rel', 'stylesheet');
				document.head.appendChild(newStyle);
                	}
		},
	},

Post Reply

Return to “Apollo - PrimeVue”

  • Information
  • Who is online

    Users browsing this forum: No registered users and 3 guests