Full solution to Dynamic color scheme + extras
-
The following two SCSS mixins I need to use in Quasar Framework in Stylus:
-
Responsive Typography with min/max font-sizes:
https://www.sassmeister.com/gist/7f22e44ace49b5124eec -
Dynamic Theme CSS generator for multiple theme variables:
https://www.sassmeister.com/gist/e99b7a8c01ef87d0dff8
Once I found out how to rewrite these in Stylus I’ll post here so it can be useful for others as well!
-
-
@mesqueeb First mixin:
strip-unit($value) unit($value, '') fluid-type($properties, $min-vw, $max-vw, $min-value, $max-value) for $property in $properties {$property}: $min-value @media screen and (min-width: $min-vw) for $property in $properties {$property}: s('calc(%s + %s * (100vw - %s) / %s)', $min-value, strip-unit($max-value - $min-value), $min-vw, strip-unit($max-vw - $min-vw)) @media screen and (min-width: $max-vw) for $property in $properties {$property}: $max-value /* Single property */ html fluid-type(font-size, 320px, 1366px, 14px, 18px) /* Multiple properties with same values */ h1 fluid-type(padding-bottom padding-top, 20em, 70em, 2em, 4em)
-
@leopiccionia WOW!!! Thanks so much!!
-
@mesqueeb The following is functionally equivalent to second mixin, if I understood it correctly. If you’re curious,
@(...){...}
defines an anonymous mixin (much like an anonymous function). The second parameter can be either a named mixin or, in the following case, an anonymous mixin:$themes = { "theme-1": { "color": red }, "theme-2": { "color": orange }, "theme-3": { "color": yellow }, "theme-4": { "color": green }, "theme-5": { "color": blue } } themify($themes, $mixin) for $theme in $themes .{$theme} & $mixin($themes[$theme]) .test themify($themes, @($theme) { color: $theme.color })
-
Uhm, I don’t know why the Stylus code is not being syntax-highlighted.
-
This post is deleted! -
Wow. @leopiccionia you are a Stylus pro!!! You have just solved so many people’s problems trying to have dynamic theming!
-
Although I prefer Stylus, I’m actually more used to SCSS (which I use on my job). I used the Stylus compiler (a NPM package!) and trial-and-error approach. Some features, like anonymous and high-order functions/mixins, were actually great surprises, as I haven’t used them before in Stylus.
-
@leopiccionia I was able to successfully integrate it into my stylus files.
The very cool thing you can do with this. You know Quasar has a lot of components where you can e.g.
color="primary
.
Now if I include a styl file like so:.text-primary themify($themes, @($theme) { color: $theme.$primary !important }) .bg-primary themify($themes, @($theme) { background: $theme.$primary !important })
And you have a primary color setup for another theme e.g.
theme-retro
. Then just by adding the classtheme-retro
to the body tag all component’s primary color will change into your new theme!
Isn’t that cool? : )You’d need to setup the retro theme like so:
$themes = { "theme-retro": { "$primary": purple }, }
Now the final question: Do you think it’s possible to wrap it into another mixin to make using the mixin less verbose?
Cheers! -
Full example:
The variables in a styl file:
$themes = { "theme-default": { '$primary': $primary '$secondary': $secondary '$tertiary': $tertiary '$neutral': $neutral '$positive': $positive '$negative': $negative '$info': $info '$warning': $warning '$light': $light '$dark': $dark }, "theme-retro": { '$primary': purple '$secondary': lime '$tertiary': grey '$neutral': $neutral '$positive': $positive '$negative': $negative '$info': $info '$warning': $warning '$light': $dark '$dark': $light }, } // Create the Stylus mixin: themify($themes, $mixin) for $theme in $themes .{$theme} & $mixin($themes[$theme])
You can see that the themes hold the original values from Quasar. To change these you best change them before you make your
$themes
object.
Then in thetheme-retro
you see I can leave original options or change to my second theme. I can even switch aroundlight
anddark
!Then you have to add all the Quasar color classes with the correct mixin like so:
.text-primary themify($themes, @($theme) { color: $theme.$primary !important }) .bg-primary themify($themes, @($theme) { background: $theme.$primary !important }) .text-secondary themify($themes, @($theme) { color: $theme.$secondary !important }) .bg-secondary themify($themes, @($theme) { background: $theme.$secondary !important }) .text-tertiary themify($themes, @($theme) { color: $theme.$tertiary !important }) .bg-tertiary themify($themes, @($theme) { background: $theme.$tertiary !important }) .text-faded themify($themes, @($theme) { color: $theme.$faded !important }) .bg-faded themify($themes, @($theme) { background: $theme.$faded !important }) .text-positive themify($themes, @($theme) { color: $theme.$positive !important }) .bg-positive themify($themes, @($theme) { background: $theme.$positive !important }) .text-negative themify($themes, @($theme) { color: $theme.$negative !important }) .bg-negative themify($themes, @($theme) { background: $theme.$negative !important }) .text-info themify($themes, @($theme) { color: $theme.$info !important }) .bg-info themify($themes, @($theme) { background: $theme.$info !important }) .text-warning themify($themes, @($theme) { color: $theme.$warning !important }) .bg-warning themify($themes, @($theme) { background: $theme.$warning !important }) .text-light themify($themes, @($theme) { color: $theme.$light !important }) .bg-light themify($themes, @($theme) { background: $theme.$light !important }) .text-dark themify($themes, @($theme) { color: $theme.$dark !important }) .bg-dark themify($themes, @($theme) { background: $theme.$dark !important })
That’s all! Now your Quasar components will change when you change a class on the
<body>
tag fromtheme-default
totheme-retro
. -
@mesqueeb You could obviously wrap
themify
inside another mixin, but I don’t think it’s a scalable solution, as you’d need to know the keys ($primary
,$secondary
) a priori, and maintain a value to each key in each theme.I’d rather pass a mixin to
themify
that infer the color keys from the theme itself.themify-palette($theme) for $k, $v in $theme $k-stripped = match('^\$(.*)', $k)[1] & .bg-{$k-stripped} background-color: $v !important & .text-{$k-stripped} color: $v !important themify($themes, themify-palette)
As a side note, I’d say something like this is more readable:
$themes = { 'theme-default': { 'colors': { 'primary': $primary 'secondary': $secondary 'tertiary': $tertiary 'neutral': $neutral 'positive': $positive 'negative': $negative 'info': $info 'warning': $warning 'light': $light 'dark': $dark }, }, 'theme-retro': { 'colors': { 'primary': purple 'secondary': lime 'tertiary': grey 'neutral': $neutral 'positive': $positive 'negative': $negative 'info': $info 'warning': $warning 'light': $dark 'dark': $light }, }, } themify($themes, $mixin) for $theme in $themes .{$theme} & $mixin($themes[$theme]) themify-palette($theme) for $k, $v in $theme.colors & .bg-{$k} background-color: $v !important & .text-{$k} color: $v !important themify($themes, themify-palette)
-
Dynamic branding colors - configurable at any time during runtime in 0.15.7 already – to be released in less than 24 hours.
-
@rstoenescu Did I inspire you to add this?! : D
Can’t wait!! -
@leopiccionia
The first mixin with the fluid font-size etc. Is it possible that it doesn’t work well with setting some height to vh?.o-hero-carousel fluid-type(height, $breakpoint-xs, $breakpoint-lg, 50vh, 80vh)
I tried this but the calculation seems to be a little bit off. Can I use anything besides
px
? (what aboutrem
andem
?) -
The first mixin with the fluid font-size etc. Is it possible that it doesn’t work well with setting some height to vh?
Your problem may be related to an issue where some browsers doesn’t allow
vh
andvw
values insidecalc()
expressions.(what about rem and em?)
It should work as expected, as my mixin and the one you provided in Sass should output the same on a demo using
em
. If the outputs are different, let me know. -
-
@rstoenescu how to dynamically change the theme of an app
according to user ?any tutorial please suggest -
I created the following Vuex module to switch between a Light and Dark theme.
import { colors } from "quasar"; const themes = { namespaced: true, state: { name: "Light" }, mutations: { SET_THEME(state, newTheme) { state.name = newTheme.name; colors.setBrand("primary", newTheme.primary); colors.setBrand("secondary", newTheme.secondary); colors.setBrand("accent", newTheme.accent); } }, actions: { ChangeTheme(context) { if (context.state.name == "Dark") { context.commit("SET_THEME", lightTheme); } else { context.commit("SET_THEME", darkTheme); } } } }; const darkTheme = { name: "Dark", primary: "#222222", secondary: "#111111", accent: "#333333" }; const lightTheme = { name: "Light", primary: "#cce6ff", secondary: "#0052a3", accent: "#f57b00" }; export default themes;
Missing currently are some of the text colors which seem to be set through classes not a palette.
Just call this to flip between the themes:
this.$store.dispatch("themes/ChangeTheme");
-
@CodeGrue said in Full solution to Dynamic color scheme + extras:
import { colors } from “quasar”;
Your VueX solution works for the Quasar stylus variables only, not for custom added variables does it?
Is there way to dynamically change those as well?