Skip to content

New theming system

Agate requested to merge themev2 into develop

Inspired by @i_lie's work at !1094 but with a different approach to make it easier to costumize CSS and build new themes.

Basically, every important color and property is now a CSS variable, meaning one can override the variable directly, instead of overriding all the CSS rules using the hardcoded value.

For instance, instead of doing:

.theme-dark .ui.sidebar {
  background: red;

you can now do:

.theme-dark {
  --sidebar-background: red;

The benefits of this approach are multiple:

  1. You don't need to override many, many rules (e.g,, .button.inverted.basic). Changing the corresponding variable a single time is enough. This results in easier maintenance and development of new themes
  2. It's possible to build themes in pure CSS (meaning we could support per-pod and per-user themes, without the need to rebuild the front-end)
  3. It's less error-prone
  4. It results in smaller CSS
  5. It makes it easier to preserve backward compatibility with existing themes in future versions, since themes don't need to override CSS rules

What's in this PR?

In order to make this possible, I had to rewrite a lot of stuff, in particular:

  • Write a basic CSS parser to replace hardcoded color values in Fomantic UI source files, by their CSS var counterpart (see front/scripts/
  • Move back all the customizations that were done in the dark theme, back to the main CSS, setting new variables, and updating all our code to use these new variables

Although not directly related to this MR, I took this opportunity to:

  • Move all scoped CSS from .vue files to .scss files in front/src/style. It really makes everything easier to understand and maintain
  • Have front/scripts/ also strip unused rules and icons from Fomantic CSS. Resulting in a 45% reduction in the size of our final CSS file, from 715KiB to 405KiB (before compression). This may results in a few display issues here and there, but it worked great during my tests
  • Improve dark theme consistency and fixed some corner cases (e.g the sidebar input wasn't dark themed, neither some dropdowns, etc.)

Dark theme exemple

The dark theme went from a 300 lines file with many nested rules, to this:

// _main.scss
@use "sass:meta";
@use "./_vars.scss" as vars;

.theme-dark {
  $fwVars: meta.module-variables("vars");
  @import "../../_css_vars.scss";
// _vars.scss
/* purgecss start ignore */

$site-background: rgb(43, 58, 66);
$light-background-color: rgb(51, 71, 82);
$input-background: rgb(65, 86, 97);
$dimmer-background: rgba(43, 58, 66, 0.9);
$text-color: rgb(223, 235, 240);
$discrete-text-color: rgba(223, 235, 240, 0.904);
$really-discrete-text-color: rgba(223, 235, 240, 0.804);
$border-color: rgba(104, 136, 155, 0.5);
$light-shadow-color: rgba(223, 235, 240, 0.15);
$shadow-color: rgba(63, 102, 97, 0.95);
$box-shadow: 0px 1px 3px 0px rgba(63, 88, 102, 0.95),
  0px 0px 0px 1px rgba(63, 88, 102, 0.98);
$link-color: rgb(255, 144, 0);
$link-hover-color: $link-color;

$button-basic-box-shadow: 0px 0px 0px 1px $light-shadow-color inset;
$button-basic-color: $text-color;
$button-basic-hover-box-shadow: 0px 0px 0px 1px $text-color inset;
$dropdown-item-hover-background: $light-background-color;
$input-selection-background: $text-color;

$divider-color: $border-color;

$secondary-meny-box-shadow: inset 0px -2px 0px 0px $light-background-color;
$secondary-menu-active-item-box-shadow: inset 0px -2px 0px 0px $shadow-color;
$secondary-menu-active-item-color: $text-color;

$segment-background: $light-background-color;
$table-background: $input-background;

@import "../../_vars";

As you can see, building new themes, such as the Darkgreen theme contributed by @i_lie will be considerably easier using this new system. It also makes it possible to do more fine grained theming, purely in the browser, overriding only certain variables, as shown in the video below.


Edited by Agate

Merge request reports