diff --git a/app/assets/javascripts/discourse/app/components/d-styles.gjs b/app/assets/javascripts/discourse/app/components/d-styles.gjs index efc3cca12d9..9f4b25f6649 100644 --- a/app/assets/javascripts/discourse/app/components/d-styles.gjs +++ b/app/assets/javascripts/discourse/app/components/d-styles.gjs @@ -63,7 +63,7 @@ export default class DStyles extends Component { css.push( `.badge-category[data-category-id="${category.id}"] { ` + `--category-badge-color: var(--category-${category.id}-color); ` + - `--category-badge-text-color: #${category.text_color}; ` + + `--category-badge-text-color: #${category.textColor}; ` + `}` ); diff --git a/app/assets/javascripts/discourse/app/components/edit-category-general.gjs b/app/assets/javascripts/discourse/app/components/edit-category-general.gjs index 1ddf1843e30..41c6badb8f9 100644 --- a/app/assets/javascripts/discourse/app/components/edit-category-general.gjs +++ b/app/assets/javascripts/discourse/app/components/edit-category-general.gjs @@ -27,7 +27,6 @@ export default class EditCategoryGeneral extends Component { customizeTextContentLink = getURL( "/admin/customize/site_texts?q=uncategorized" ); - foregroundColors = ["FFFFFF", "000000"]; get styleTypes() { return Object.keys(CATEGORY_STYLE_TYPES).map((key) => ({ @@ -306,31 +305,6 @@ export default class EditCategoryGeneral extends Component { {{/unless}} - - <@form.Field - @name="text_color" - @title={{i18n "category.foreground_color"}} - @format="full" - as |field| - > - -
-
- - -
-
-
- diff --git a/app/assets/javascripts/discourse/app/controllers/edit-category-tabs.js b/app/assets/javascripts/discourse/app/controllers/edit-category-tabs.js index 96d0b352666..3e6e7e40f0f 100644 --- a/app/assets/javascripts/discourse/app/controllers/edit-category-tabs.js +++ b/app/assets/javascripts/discourse/app/controllers/edit-category-tabs.js @@ -40,6 +40,7 @@ export default class EditCategoryTabsController extends Controller { expandedMenu = false; parentParams = null; validators = []; + textColors = ["000000", "FFFFFF"]; @and("showTooltip", "model.cannot_delete_reason") showDeleteReason; @@ -120,6 +121,8 @@ export default class EditCategoryTabsController extends Controller { } this.model.setProperties(transientData); + this.setTextColor(this.model.color); + this.set("saving", true); this.model @@ -184,4 +187,15 @@ export default class EditCategoryTabsController extends Controller { goBack() { DiscourseURL.routeTo(this.model.url); } + + @action + setTextColor(backgroundColor) { + const r = parseInt(backgroundColor.substr(0, 2), 16); + const g = parseInt(backgroundColor.substr(2, 2), 16); + const b = parseInt(backgroundColor.substr(4, 2), 16); + const brightness = (r * 299 + g * 587 + b * 114) / 1000; + const color = brightness >= 128 ? this.textColors[0] : this.textColors[1]; + + this.model.set("text_color", color); + } } diff --git a/app/assets/javascripts/discourse/app/helpers/category-variables.js b/app/assets/javascripts/discourse/app/helpers/category-variables.js index e57b69797a3..bfb50e3a48e 100644 --- a/app/assets/javascripts/discourse/app/helpers/category-variables.js +++ b/app/assets/javascripts/discourse/app/helpers/category-variables.js @@ -7,16 +7,16 @@ export default function categoryVariables(category) { vars += `--category-badge-color: #${category.color};`; } - if (category.text_color) { - vars += `--category-badge-text-color: #${category.text_color};`; + if (category.textColor) { + vars += `--category-badge-text-color: #${category.textColor};`; } if (category.parentCategory?.color) { vars += `--parent-category-badge-color: #${category.parentCategory.color};`; } - if (category.parentCategory?.text_color) { - vars += `--parent-category-badge-text-color: #${category.parentCategory.text_color};`; + if (category.parentCategory?.textColor) { + vars += `--parent-category-badge-text-color: #${category.parentCategory.textColor};`; } return htmlSafe(vars); diff --git a/app/assets/javascripts/discourse/app/lib/transformer/registry.js b/app/assets/javascripts/discourse/app/lib/transformer/registry.js index 050ad601837..02826c48985 100644 --- a/app/assets/javascripts/discourse/app/lib/transformer/registry.js +++ b/app/assets/javascripts/discourse/app/lib/transformer/registry.js @@ -15,6 +15,7 @@ export const VALUE_TRANSFORMERS = Object.freeze([ "category-available-views", "category-description-text", "category-display-name", + "category-text-color", "composer-service-cannot-submit-post", "header-notifications-avatar-size", "home-logo-href", diff --git a/app/assets/javascripts/discourse/app/models/category.js b/app/assets/javascripts/discourse/app/models/category.js index d48d06591e2..38c63ec4d12 100644 --- a/app/assets/javascripts/discourse/app/models/category.js +++ b/app/assets/javascripts/discourse/app/models/category.js @@ -497,6 +497,16 @@ export default class Category extends RestModel { }); } + get textColor() { + return applyValueTransformer( + "category-text-color", + this.get("text_color"), + { + category: this, + } + ); + } + @computed("parent_category_id", "site.categories.[]") get parentCategory() { if (this.parent_category_id) { diff --git a/app/assets/javascripts/discourse/tests/acceptance/category-edit-test.js b/app/assets/javascripts/discourse/tests/acceptance/category-edit-test.js index add1a557a48..11377538947 100644 --- a/app/assets/javascripts/discourse/tests/acceptance/category-edit-test.js +++ b/app/assets/javascripts/discourse/tests/acceptance/category-edit-test.js @@ -26,8 +26,6 @@ acceptance("Category Edit", function (needs) { await fillIn("input.category-name", "testing"); assert.dom(".category-style .badge-category__name").hasText("testing"); - await fillIn(".edit-text-color input", "ff0000"); - await click(".edit-category-topic-template a"); await fillIn(".d-editor-input", "this is the new topic template"); diff --git a/app/assets/javascripts/discourse/tests/acceptance/category-new-test.js b/app/assets/javascripts/discourse/tests/acceptance/category-new-test.js index d9080af40a0..38ffca9c22e 100644 --- a/app/assets/javascripts/discourse/tests/acceptance/category-new-test.js +++ b/app/assets/javascripts/discourse/tests/acceptance/category-new-test.js @@ -1,7 +1,9 @@ import { click, currentURL, fillIn, visit } from "@ember/test-helpers"; import { test } from "qunit"; import sinon from "sinon"; +import { cloneJSON } from "discourse/lib/object"; import DiscourseURL from "discourse/lib/url"; +import { fixturesByUrl } from "discourse/tests/helpers/create-pretender"; import { acceptance } from "discourse/tests/helpers/qunit-helpers"; import selectKit from "discourse/tests/helpers/select-kit-helper"; import { i18n } from "discourse-i18n"; @@ -99,6 +101,59 @@ acceptance("Category New", function (needs) { }); }); +acceptance("Category text color", function (needs) { + needs.user(); + needs.pretender((server, helper) => { + const category = cloneJSON(fixturesByUrl["/c/11/show.json"]).category; + + server.get("/c/testing/find_by_slug.json", () => { + return helper.response(200, { + category: { + ...category, + color: "EEEEEE", + text_color: "000000", + }, + }); + }); + }); + + test("Category text color is set based on contrast", async function (assert) { + await visit("/new-category"); + + let previewTextColor = document + .querySelector(".category-style .badge-category__wrapper") + .style.getPropertyValue("--category-badge-text-color") + .trim(); + + assert.strictEqual( + previewTextColor, + "#FFFFFF", + "has the default text color" + ); + + await fillIn("input.category-name", "testing"); + await fillIn(".category-color-editor .hex-input", "EEEEEE"); + await click("#save-category"); + + assert.strictEqual( + currentURL(), + "/c/testing/edit/general", + "it transitions to the category edit route" + ); + + previewTextColor = document + .querySelector(".category-style .badge-category__wrapper") + .style.getPropertyValue("--category-badge-text-color") + .trim(); + + assert.strictEqual( + previewTextColor, + "#000000", + "sets the contrast text color" + ); + }); +}); + acceptance("New category preview", function (needs) { needs.user({ admin: true }); diff --git a/app/assets/javascripts/discourse/tests/acceptance/transformers/text-color-test.js b/app/assets/javascripts/discourse/tests/acceptance/transformers/text-color-test.js new file mode 100644 index 00000000000..3950a5ef9a5 --- /dev/null +++ b/app/assets/javascripts/discourse/tests/acceptance/transformers/text-color-test.js @@ -0,0 +1,26 @@ +import { visit } from "@ember/test-helpers"; +import { test } from "qunit"; +import { withPluginApi } from "discourse/lib/plugin-api"; +import { acceptance } from "discourse/tests/helpers/qunit-helpers"; + +acceptance("category-text-color transformer", function () { + test("applying a value transformation", async function (assert) { + withPluginApi("1.34.0", (api) => { + api.registerValueTransformer("category-text-color", () => "FF0000"); + }); + + await visit("/"); + + const element = document.querySelector( + "[data-topic-id='11994'] .badge-category__wrapper" + ); + + assert.strictEqual( + window + .getComputedStyle(element) + .getPropertyValue("--category-badge-text-color"), + "#FF0000", + "it transforms the category text color" + ); + }); +}); diff --git a/config/locales/client.en.yml b/config/locales/client.en.yml index df31db500bc..ee6920de61b 100644 --- a/config/locales/client.en.yml +++ b/config/locales/client.en.yml @@ -4147,7 +4147,6 @@ en: background_image_dark: "Dark Category Background Image" style: "Styles" background_color: "Color" - foreground_color: "Foreground color" styles: type: "Style" icon: "Icon"