Creating a dynamic atom theme with pywal? - css

I'm trying to write an atom theme. However, it will not be static. I want to use imported css from pywal to change how atom looks depending on the color scheme of the rest of the desktop at that given moment. I am able to import the colors from the pywal cache, and use them as css colors. I can even assign them to less variables. However, when I try to use a function such as darken, I get the error error evaluating function 'darken': color.toHSL is not a function
I had concluded it was due to the import settings, so I tried using the (less) keyword in my import for the css file. When I did so, it said it could not find the file, so (in order to test if I was at least right about the import settings), I copied the pywal css file into the styles directory and changed the filename in import accordingly. This led me back to square one, as I started receiving the same error. An example of my attempts are below.
Relevant code:
~/.cache/wal/colors.css (aka "tempcolors.css"):
/* CSS variables
Generated by 'wal' */
:root {
--wallpaper: url("/home/regular/wallpapers/current/image.jpg");
/* Special */
--background: #0a0b10;
--foreground: #d5c5a8;
--cursor: #d5c5a8;
/* Colors */
--color0: #0a0b10;
--color1: #483E45;
/* ... */
--color15: #d5c5a8;
}
colors.less:
// These colors are specific to the theme. Do not use in a package!
//#import (less) url('file:///home/[MYUSERNAME]/.cache/wal/colors.css'); // this stopped working when I added (less)
#import (less) "tmpcolors.css";
#very-light-gray: #c5c8c6;
#light-gray: #969896;
/* the rest of the standard colors */
#background: var(--background);
#foreground: var(--foreground);
#color-1: var(--color1);
#color-2: var(--color2);
/* ... */
#color-15: var(--color15);
Here's the section in base.less where I tried to use my custom colors:
atom-text-editor {
/* ... */
.gutter {
background-color: #color-7; //works
background-color: darken(#color-7, 25%); //doesn't work
background-color: darken(#red, 25%); //works
Can someone help me? Is what I'm trying to do possible?
P.S. Please let me know if you need more info

Related

SassError: Undefined variable

I have a variable file that has two definitions of themes I want to overwrite:
_vars.scss
body {
$bg-color: #fff
}
body.theme-dark {
$bg-color: #333
}
I´m calling the variables in my Angular button component:
button.scss
#import '_vars.scss';
.button {
background-color: $bg-color;
}
But I´m getting the following compiling error:
SassError: Undefined variable.
background-color: $bg-color;
Whats is the right way to overwrite variables depending on my body theme class?
Thanks
You define $bg-color depending on the theme, but never $font-size-18.
On a side note, I would consider to use CSS Custom Properties instead of SASS variables if I was in your shoes. Codyhouse have an interesting and easy to understand article about this, which also talks about color themes.
If you want to dig deeper into this topic you may want to read this article.
First of all variables inside scope valid only in that scope not universally. Now for your question see below :-
_vars.scss
Instead of making variables inside body scope create it in global scope.
$bg-color: #fff;
body {
background-color: $bg-color;
}
and then import it in your button.scss without underscore "_"
#use "vars" as *;
button {
background-color: $bg-color;
}

LESS variable overrides and import order

In our app.less file, we import a few variable files, and then the individual component style sheets.
app.less
#import variables.less /* Original app styles/colors */
#import corp-colors.less /* corporate color variables */
#import light-theme.less /* Theme definitions */
#import '../components/style' /* This file contains imports of every component in the app */
The variables.less file defines #link-color...
variables.less
#link-color: #1997CA;
And the light-theme.less redefines it by pulling in the corp color.
light-theme.less
body.light-theme {
#link-color: #corp-blue;
}
corp-colors.less
```less
#corp-blue: #2a60c8;
```
Finally, in my component, I digest the variable for a tab bottom border.
x-component/style.less
li {
&.is-selected {
.tab-label {
border-bottom: 3px solid #link-color;
}
}
}
As the light-theme is imported after variables, I'd expect to see the border color as #2a60c8, but am seeing the original #1997CA instead.
However, if I change the component style to use #corp-blue instead of #link-color, it shows correctly.
Am I overlooking something with import and override ordering?
LESS variables work not like CSS variables, they calculate their values on the compilation stage, not in runtime. It seems like you need to change:
body.light-theme {
#link-color: #corp-blue;
}
to:
#link-color: #corp-blue;

Feed theme variables to new Modules system

I work on styles for multi-tenant application for which the choice has been made to use SASS. Following the latest version guidelines, I started building base styles using #use and #forward. Now I want to theme this base with customers' colors and fonts variables to receive multiple stylesheets that can be served to different instances of our application.
If I was to use deprecated #import, I would go like this:
styles/customerA/index.scss
#import "customerA-variables";
#import "../base/index";
But with new rules I cannot find an easy way to simply feed theme specific variables to the base styles. I tried to use with keyword, but it turns out I need to define variables in a module, while I would rather encapsulate them in another module and import it.
styles/customerA/index.scss
#use "customerA-variables" as variables;
#use "../base/index" with (
$bgColor: variables.$bgColor,
$textColor: variables.$textColor
);
styles/base/_base-variables.scss
$bgColor: #eee !default;
$textColor: #333 !default;
styles/base/index.scss
/* HOW IT WORKS */
$bgColor: #eee !default;
$textColor: #333 !default;
/* HOW I WISH IT WORKED */
#use "./base-variables" as *;
/* LATER IN THE FILE */
body {
background-color: $bgColor;
color: $textColor;
}
In #use "../variables" as * scenario I get this error:
Error: This variable was not declared with !default in the #used module.
I'm looking for a working solution preferably without copy-pasting all theme variables inside with parenthesis.
First the error:
Error: This variable was not declared with !default in the #used module.
That error arises when you try to #use a module/file with configuration variables but the configuration variables are not set as !default variables in the module/file. So, SASS checks if you are passing a configuration which is not provided to be configurated for the module. That's additional security to you.
I am not quite sure if I did understand your example right, but it could be the way:
// styles/customerA/index.scss
#use "customerA-variables" as variables;
#use "../base/index" with (
$bgColor: variables.$bgColor,
$textColor: variables.$textColor
);
--> SASS ERROR because $bgColor and/or $textColor
--> in #used module/file are not set as defaults, i.e.:
--> $bgColor: green;
--> must be: $bgColor: green !default;
So, you may check the module if the variables are all set to defaults and not overwritten by non-default values.
**SECOND: usage of #use:
The new rule #use indeed is really confusing ... in your example that leads to doubled code: once when you set the custom vars in customerA-variables.scss and then when you repeat that variables when you #use the module/file in styles/customerA/index.scss (see your second code example).
A good way to avoid that doubled code is to prepare a configuration file with the settings for the individual customer and THAN #use the configuration file (not the wanted module/file direct).
Example:
// ###
// ### module/file: ../base/index.scss
$bgColor: #eee !default;
$textColor: #333 !default;
body {
background-color: $bgColor;
color: $textColor;
}
// ###
// ### customer configuration file: configModuleCustomerA.scss
#forward "../base/index" with (
$bgColor: red,
$textColor: blue
);
// ###
// ### use that configuration file
// ### to your main file: styles/customerA/index.scss
#use "...path.../configModuleCustomerA" as *;
// Note:
// 1. that writes the configurated css
// 2. and it provides the variables for additional use to THIS file
// see going on this file below ...
.additionalElement {
background: $bgColor;
color: $textColor;
}
// ###
// ### ---> that compiles to CSS:
body {
background-color: red;
color: blue;
}
.additionalElement {
background: red;
color: blue;
}
NOTE: there is an additional TRICK/EFFECT you should know.
YOU ONLY NEED TO SET THE VARIABLES ONCE ... just the time when you config the module/file. And as you do it in a/the module config file the variables you set there are part of you project configuration!
So, if you need the SAME variables of a module a second/third/... time (i.e. in additional partials files) you #use that configuration file in any file where you need it/them. Don't worry: the css code is only compiled ONCE to your CSS: the first time you #use the module.
BUT HEAD UP IN YOUR CASE:
But if you want to #use a module/file with different configurations as in your case you have to compile it into two DIFFERENT CSS files. One module with two or more different configurations loaded to the same CSS is blocked by SASS. In that case you need to split the css to different customer css files which all uses different module configuration files.

SCSS : Import variable and style rule from another file. I don't want duplication style rule

I don't really understand about #import and partial file
But I want to ask for a little understanding.
I have 2 files. file2.scss must use the variable from file1.scss.
File1.scss
/* file1.scss */
$color-1 : #7E3D97;
#font-face{
font-family : AngsanaNew;
src: url(/font/AngsanaNew.TTF);
}
div.test1{
background-color: #222;
}
File2.scss
/* file2.scss */
#import 'file1'
div.content{
background-color : $color-1;
}
When I compile SCSS, It generates 2 files. Which is not what I want. I want it to be
/* file1.css */
#font-face{
font-family : AngsanaNew;
src: url(/font/AngsanaNew.TTF);
}
div.test1{
background-color: #222;
}
AND
/* file2.css */
div.content{
background-color : #7E3D97;
}
Because if I want to create a file file3.css, file4.css. while there is already a file1.css style rule. I will see #font-face and div.test1 contain in file3.css, file4.css.
I don't want that. What should I do?
P.S. Sorry my english. If you edit my text to make it easy to read. I will be very grateful.
If SASS is generating the CSS it does it for every 'normal named' file.scss. To mark a file for SASS that it should not be used to generate a separate css file use an underscore _ as prefix, - i.e. _partial.scss. That files will only be used to be imported to the main scss file.
Now you can organize your project:
// POSSIBLE PROJECT STRUCURE
// variables to whole project
// --> variables only, no classes
_defaults.scss
// partial files
// --> use vairables from _default.scss
// --> or if you want/need to define variables here
// --> use variables with default-flag: '$variable: value !default'
// --> so they will/can be overwritten by same variable set BEFORE in _default.scss
_partial-structure.scss
_partial-element.scss
...
// bring them together in main file
styles.scss
#import 'defaults';
#import 'partial-structure';
#import 'partial-element';
...

CSS variable & SCSS mixin

I need to be able to use CSS variables because I need to have an hover effect (background-color) to be customizable by my VueJs app.
But my CSS stylesheet should have a default value, which is stored in a nested SCSS map. (map-getter is a function which returns values from nested maps)
I know that my SCSS code works, because I get the intended result when I do this:
.theme--dark .AppNavTile:hover {
background-color: map-getter($theme-dark, AppNav, hover);
//returns background-color: rgba(255, 255, 255, 0.87); in my browser's console
}
In order to use CSS variables, I can modify the code as follows:
.theme--dark .AppNavTile:hover {
--hover-bg-color: red;
background-color: var(--hover-bg-color);
}
It works fine and I have a red background when hovering the element.
Then I try to combine both:
.theme--dark .AppNavTile:hover {
--hover-bg-color: map-getter($theme-dark, AppNav, hover);
background-color: var(--hover-bg-color);
}
According to by browser's console, this returns the following:
.theme--dark .AppNavTile:hover {
--hover-bg-color: map-getter($theme-dark, AppNav, hover);
background-color: var(--hover-bg-color);
}
So it seems that the SCSS code remains uncompiled in the CSS variable. Is there any way around it?
Thanks!
The "problem" with CSS variables is they can have any value – why map-getter($theme-dark, AppNav, hover) is rendered as is. To instruct SCSS that this is actual SCSS code and not a random string you need to use interpolation (like if you use SCSS variables inside calc):
--hover-bg-color: #{map-getter($theme-dark, AppNav, hover)};

Resources