How to allow users to override my package's LESS variables?


#1

I have a package which defines some LESS styles. In that .less file I defined some variables. For example:

@my-color: red;

I’d like for users to be able to override that value in there user stylesheet in the same way that they can override standard UI and Syntax LESS variables. So I was hoping they could do:

@my-color: blue;

And by doing that override the default value from my package. But it doesn’t seem to work. Is it possible to set things up so that this does work? So users can override any packages LESS variable with their stylesheet?


#2

Currently this is not possible since the package LESS gets compiled and loaded in a separate step from the styles.less. This also assumes that they are using LESS and not CSS to style your UI, which should be supported. What I do for my packages is just document the classes I use for various UI elements and then let people use whatever process they want for styling those elements. For example, see the README for my soft-wrap-indicator package.


#3

Thanks for your help. In this particular case it’s a little tricker, because I’m generating a lot of other rules based on that variable. I’ve found that I can do most of what I want by importing the users style.less into my packages theme.

So in my package I do:

@import "../../../styles.less";

And that allows the user to override my default value if they wish.

I realize this is a bit of a hack, live reload won’t work (for that particular bit of styling). And in current Atom if styles.less doesn’t exist my package won’t load (can fix that when Atom updates to LESS 2.4 with optional imports).

So it’s a hack, but I’m happy it works. The one thing that I would like is a less hardcoded path to styles.less. I’ve tried using atom://styles.less, but it doesn’t seem to work. Does anyone know if a good way to reference styles.less from a package stylesheet?


#4

There was an attempt to make Less variables overridable, but had to be put on ice again: https://github.com/atom/atom/pull/4153#issuecomment-73980380

I like your idea. We had a similar one: Add an “official” .atom/init-styles.less (or so) file that then can be used by packages and themes, like you described above. Using a different file than styles.less is just so people don’t expect it to live-reload and that Atom needs to be reloaded first.

There probably needs to be some convention about naming the variables. Like prefixing with the package/theme: my-package-variable. And maybe a couple “shared” ones. Like ui-font-size or so?

And yes… a shorter import path would be nice.


#5

This sounds good I think.

For naming what about user-variables. I think this is serving a similar function to ui-variables and syntax-variables, so follow that naming convention?

I don’t fully understand when CSS build/cache process runs and how it would interact with this file. Would it work to:

  1. @import user-variables in atom.less right after importing the syntax and ui variables? I think that would allow overriding of theme those variables, which I don’t think is possible now.

  2. And then packages that have variables that they want to allow override on can also import user-variables just as they already import ui-variables and syntax-variables now.

I have a pull request to update Atom to LESS 2.4 that might also be needed/helpful here. It would allow using @import (optional) for when the user hasn’t created this file.

Jesse


#6

This would be awesome!


#7

:+1: Yes, I like user-variables. Makes sense next to UI and Syntax variables. Also makes it more clear that it shouldn’t be used for normal styling like in styles.less.

I tried to use @import "../../../styles.less"; in a theme. It worked when “live reloading” in dev mode. But not when reloading or switching themes. Absolute path @import "/Users/[name]/.atom/user-variables.less"; worked in all cases. So maybe Atom needs to make that file available somehow for relative importing?

I think theme authors can decide if they want to allow people to override all ui-variables or only specific ones. It would depend where the import happens, before a or after a variable gets defined in a theme and probably same with packages too.

// allow to be overridden
@font-size: 11px;

@import (optional) "../../../user-variables.less";

// don't allow to be overridden
@text-color: black;

#8

In Sass you can also deal with that by simply putting the import at the top of the file, but setting configurable variables with !default. Not sure if Less has such a feature.


#9

That would be nice, but looks like in Less you have to do it by moving the import: http://lesscss.org/features/#variables-feature-default-variables. Yeah, not as flexible as Sass’s !default.


#10

Their defence is a bit lame, but they’re right, it does work. Wouldn’t a user-variables.less be a super easy way to replicate what the failed attempts for config in themes were trying to achieve? It’s not as discoverable as config in settings-view, but you can cover that in the README and basically get all this flexibility almost for free. Or is there some drawback? Should we raise in issue in atom/atom (or somewhere else)?


#11

It wouldn’t be as elegant as in the settings, like having controls to change the variables in real-time. But still better than nothing. Yeah, feel free to make an issue on atom/atom and see what the core team thinks about it.

I think the only thing to figure out is the relative import path.


#12

Maybe packages can provide a variables-defaults.less, that can be parsed into the settings view? When changed they get written to ~/.atom/user-variables.less

The ~/.atom path can be added to the paths option of the less compiler, so the compiler knows to look there if it can’t find the imported file in the compiled file’s directory. Then you can use @import "user-variables";. Just like you can @import "syntax-variables"; anywhere.


#13

Done: