DEV: Let themes extend color definitions (#10429)

DEV: Let themes extend color definitions (#10429)

Themes can now declare custom colors that get compiled in core’s color definitions stylesheet, thus allowing themes to better support dark/light color schemes.

For example, if you need your theme to use tertiary for an element in a light color scheme and quaternary in a dark scheme, you can add the following SCSS to your theme’s color_definitions.scss file:

:root {
  --mytheme-tertiary-or-quaternary: #{dark-light-choose($tertiary, $quaternary)};
}

And then use the --mytheme-tertiary-or-quaternary variable as the color property of that element. You can also use this file to add color variables that use SCSS color transformation functions (lighten, darken, saturate, etc.) without compromising your theme’s compatibility with different color schemes.

diff --git a/app/assets/javascripts/admin/components/ace-editor.js b/app/assets/javascripts/admin/components/ace-editor.js
index 407b0fe..f486854 100644
--- a/app/assets/javascripts/admin/components/ace-editor.js
+++ b/app/assets/javascripts/admin/components/ace-editor.js
@@ -33,6 +33,15 @@ export default Component.extend({
     }
   },
 
+  @observes("placeholder")
+  placeholderChanged() {
+    if (this._editor) {
+      this._editor.setOptions({
+        placeholder: this.placeholder
+      });
+    }
+  },
+
   @observes("disabled")
   disabledStateChanged() {
     this.changeDisabledState();
@@ -72,7 +81,6 @@ export default Component.extend({
 
   didInsertElement() {
     this._super(...arguments);
-
     loadScript("/javascripts/ace/ace.js").then(() => {
       window.ace.require(["ace/ace"], loadedAce => {
         loadedAce.config.set("loadWorkerFromBlob", false);
@@ -85,7 +93,7 @@ export default Component.extend({
 
         editor.setTheme("ace/theme/chrome");
         editor.setShowPrintMargin(false);
-        editor.setOptions({ fontSize: "14px" });
+        editor.setOptions({ fontSize: "14px", placeholder: this.placeholder });
         editor.getSession().setMode("ace/mode/" + this.mode);
         editor.on("change", () => {
           this._skipContentChangeEvent = true;
diff --git a/app/assets/javascripts/admin/components/admin-theme-editor.js b/app/assets/javascripts/admin/components/admin-theme-editor.js
index 0299c04..0ae1d14 100644
--- a/app/assets/javascripts/admin/components/admin-theme-editor.js
+++ b/app/assets/javascripts/admin/components/admin-theme-editor.js
@@ -1,3 +1,4 @@
+import I18n from "I18n";
 import { next } from "@ember/runloop";
 import Component from "@ember/component";
 import discourseComputed from "discourse-common/utils/decorators";
@@ -30,9 +31,17 @@ export default Component.extend({
   activeSectionMode(targetName, fieldName) {
     if (["settings", "translations"].includes(targetName)) return "yaml";
     if (["extra_scss"].includes(targetName)) return "scss";
+    if (["color_definitions"].includes(fieldName)) return "scss";
     return fieldName && fieldName.indexOf("scss") > -1 ? "scss" : "html";
   },
 
+  @discourseComputed("currentTargetName", "fieldName")
+  placeholder(targetName, fieldName) {
+    return fieldName && fieldName === "color_definitions"
+      ? I18n.t("admin.customize.theme.color_definitions.placeholder")
+      : "";
+  },
+
   @discourseComputed("fieldName", "currentTargetName", "theme")
   activeSection: {
     get(fieldName, target, model) {
diff --git a/app/assets/javascripts/admin/models/theme.js b/app/assets/javascripts/admin/models/theme.js
index eb2aecf..06d5fae 100644
--- a/app/assets/javascripts/admin/models/theme.js
+++ b/app/assets/javascripts/admin/models/theme.js
@@ -72,7 +72,7 @@ const Theme = RestModel.extend({
     }
 
     return {
-      common: [...common, "embedded_scss"],
+      common: [...common, "embedded_scss", "color_definitions"],
       desktop: common,
       mobile: common,
       settings: ["yaml"],
diff --git a/app/assets/javascripts/admin/templates/components/admin-theme-editor.hbs b/app/assets/javascripts/admin/templates/components/admin-theme-editor.hbs
index 3ebd8f2..ce92810 100644
--- a/app/assets/javascripts/admin/templates/components/admin-theme-editor.hbs
+++ b/app/assets/javascripts/admin/templates/components/admin-theme-editor.hbs
@@ -87,4 +87,4 @@
   <pre class="field-error">{{error}}</pre>
 {{/if}}
 
-{{ace-editor content=activeSection editorId=editorId mode=activeSectionMode autofocus="true"}}
+{{ace-editor content=activeSection editorId=editorId mode=activeSectionMode autofocus="true" placeholder=placeholder}}
diff --git a/app/assets/stylesheets/common/admin/customize.scss b/app/assets/stylesheets/common/admin/customize.scss
index a9a0e74..970a720 100644
--- a/app/assets/stylesheets/common/admin/customize.scss
+++ b/app/assets/stylesheets/common/admin/customize.scss
@@ -447,6 +447,12 @@
       bottom: 0;
     }
 
+    .ace_placeholder {
+      font-family: inherit;
+      font-size: $font-up-1;
+      color: $primary-high;
+    }
+
     .status-actions {
       float: right;
       margin-top: 7px;
diff --git a/app/helpers/application_helper.rb b/app/helpers/application_helper.rb
index e8c260f..3d9523b 100644
--- a/app/helpers/application_helper.rb
+++ b/app/helpers/application_helper.rb
@@ -458,7 +458,7 @@ module ApplicationHelper
     dark_scheme_id =  user_dark_scheme_id || SiteSetting.default_dark_mode_color_scheme_id
 
     if dark_scheme_id != -1
-      result << Stylesheet::Manager.color_scheme_stylesheet_link_tag(dark_scheme_id, '(prefers-color-scheme: dark)')
+      result << Stylesheet::Manager.color_scheme_stylesheet_link_tag(dark_scheme_id, '(prefers-color-scheme: dark)', theme_ids)
     end
     result.html_safe
   end
diff --git a/app/models/color_scheme.rb b/app/models/color_scheme.rb
index eb09f1c..2978858 100644
--- a/app/models/color_scheme.rb
+++ b/app/models/color_scheme.rb
@@ -271,7 +271,7 @@ class ColorScheme < ActiveRecord::Base
 
   def publish_discourse_stylesheet
     if self.id
-      Stylesheet::Manager.color_scheme_cache_clear(self)
+      Stylesheet::Manager.clear_color_scheme_cache!
 
       theme_ids = Theme.where(color_scheme_id: self.id).pluck(:id)
       if theme_ids.present?
diff --git a/app/models/theme_field.rb b/app/models/theme_field.rb
index a15d42e..4e525b0 100644
--- a/app/models/theme_field.rb
+++ b/app/models/theme_field.rb
@@ -265,7 +265,7 @@ class ThemeField < ActiveRecord::Base
   end
 
   def self.scss_fields
-    @scss_fields ||= %w(scss embedded_scss)
+    @scss_fields ||= %w(scss embedded_scss color_definitions)
   end
 
   def self.basic_targets
@@ -424,6 +424,9 @@ class ThemeField < ActiveRecord::Base
     ThemeFileMatcher.new(regex: /^common\/embedded\.scss$/,
                          targets: :common, names: "embedded_scss", types: :scss,
                          canonical: -> (h) { "common/embedded.scss" }),
+    ThemeFileMatcher.new(regex: /^common\/color_definitions\.scss$/,
+                         targets: :common, names: "color_definitions", types: :scss,
+                         canonical: -> (h) { "common/color_definitions.scss" }),
     ThemeFileMatcher.new(regex: /^(?:scss|stylesheets)\/(?<name>.+)\.scss$/,
                          targets: :extra_scss, names: nil, types: :scss,
                          canonical: -> (h) { "stylesheets/#{h[:name]}.scss" }),
diff --git a/config/locales/client.en.yml b/config/locales/client.en.yml
index 0168e34..333cfd0 100644
--- a/config/locales/client.en.yml
+++ b/config/locales/client.en.yml
@@ -3994,6 +3994,10 @@ en:
           embedded_scss:
             text: "Embedded CSS"
             title: "Enter custom CSS to deliver with embedded version of comments"
+          color_definitions:
+            text: "Color Definitions"
+            title: "Enter custom color definitions (advanced users only)"
+            placeholder: "\r\nUse this stylesheet to add custom colors to the list of CSS custom properties.\r\n\r\nExample: \r\n\r\n:root {\r\n  --mytheme-tertiary-or-quaternary: #{dark-light-choose($tertiary, $quaternary)};\r\n}\r\n\r\nPrefixing the property names is highly recommended to avoid conflicts with plugins and/or core."
           head_tag:
             text: "</head>"
             title: "HTML that will be inserted before the </head> tag"
diff --git a/lib/stylesheet/compiler.rb b/lib/stylesheet/compiler.rb
index b5575cd..8596c5d 100644
--- a/lib/stylesheet/compiler.rb
+++ b/lib/stylesheet/compiler.rb
@@ -21,7 +21,7 @@ module Stylesheet
         file = File.read path
 
         if asset.to_s == Stylesheet::Manager::COLOR_SCHEME_STYLESHEET
-          file += Stylesheet::Importer.import_color_definitions
+          file += Stylesheet::Importer.import_color_definitions(options[:theme_id])
         end
       end
 
diff --git a/lib/stylesheet/importer.rb b/lib/stylesheet/importer.rb
index f190196..e08d766 100644

[... diff too long, it was truncated ...]

GitHub sha: 882b0aac

This commit appears in #10429 which was merged by pmusaraj.