diff --git a/app/assets/images/forem-background.svg b/app/assets/images/forem-background.svg index 795d995ad..52f935240 100644 --- a/app/assets/images/forem-background.svg +++ b/app/assets/images/forem-background.svg @@ -1,3 +1,3 @@ - - + + diff --git a/app/assets/stylesheets/shared.scss b/app/assets/stylesheets/shared.scss index 5dd4859c4..ff10e65f5 100644 --- a/app/assets/stylesheets/shared.scss +++ b/app/assets/stylesheets/shared.scss @@ -181,3 +181,7 @@ } } } + +.forem-background { + fill: var(--accent-brand); +} diff --git a/app/javascript/admin/controllers/creator_settings_controller.js b/app/javascript/admin/controllers/creator_settings_controller.js index cda796eb4..c6e5d28ff 100644 --- a/app/javascript/admin/controllers/creator_settings_controller.js +++ b/app/javascript/admin/controllers/creator_settings_controller.js @@ -1,4 +1,5 @@ import { Controller } from '@hotwired/stimulus'; +import { brightness } from '../../utilities/color/accentCalculator'; const MAX_LOGO_PREVIEW_HEIGHT = 80; const MAX_LOGO_PREVIEW_WIDTH = 220; @@ -67,4 +68,29 @@ export class CreatorSettingsController extends Controller { reader.readAsDataURL(firstFile); } + + /** + * Updates ths branding/colors on the Creator Settings Page. + * + * @param {Event} event + */ + updateBranding(event) { + const { value: color } = event.target; + + if (!new RegExp(event.target.getAttribute('pattern')).test(color)) { + return; + } + + document.documentElement.style.setProperty('--accent-brand', color); + + // We need to recalculate '--accent-brand-darker' in javascript as it's + // currently being calculated in ruby. It is used for the hover effect + // over the button. + // 0.85 represents the brightness value set in Ruby to calculate + // '--accent-brand-darker' + document.documentElement.style.setProperty( + '--accent-brand-darker', + brightness(color, 0.85), + ); + } } diff --git a/app/javascript/utilities/__tests__/color/accentCalculator.test.js b/app/javascript/utilities/__tests__/color/accentCalculator.test.js new file mode 100644 index 000000000..b26d71120 --- /dev/null +++ b/app/javascript/utilities/__tests__/color/accentCalculator.test.js @@ -0,0 +1,9 @@ +import { brightness } from '@utilities/color/accentCalculator'; + +describe('Color: Accent Calculator Utilities', () => { + it('should return a hex with the adjusted brightness', () => { + expect(brightness('#ccddee', 0.5)).toBe('#666f77'); + expect(brightness('#ccddee')).toBe('#ccddee'); + expect(brightness('#41625c', 0.85)).toBe('#37534e'); + }); +}); diff --git a/app/javascript/utilities/color/accentCalculator.js b/app/javascript/utilities/color/accentCalculator.js new file mode 100644 index 000000000..0e1a5f053 --- /dev/null +++ b/app/javascript/utilities/color/accentCalculator.js @@ -0,0 +1,56 @@ +/** + * Updates the brightness of the color + * @param {String} color + * @param {Integer} amount + * Based on the ruby implementation + * https://github.com/forem/forem/blob/main/app/services/color/compare_hex.rb + */ +export function brightness(color, amount = 1) { + const rgbObj = hexToRgb(color); + Object.keys(rgbObj).forEach((key) => { + rgbObj[key] = Math.round(rgbObj[key] * amount); + }); + + return rgbToHex(rgbObj['r'], rgbObj['g'], rgbObj['b']); +} + +/** + * Converts the HEX color to an RGB color + * @param {String} Hex color + * @returns {Object} An object with keys for R,G,B based on the HEX color + * @returns {null} If we cannot determine a hex pattern from the string + */ +function hexToRgb(hex) { + const result = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(hex); + return result + ? { + r: parseInt(result[1], 16), + g: parseInt(result[2], 16), + b: parseInt(result[3], 16), + } + : null; +} + +/** + * Converts the RGB parameters to a HEX String + * @param {String} Red value from RGB + * @param {String} Green value from RGB + * @param {String} Blue value from RGB + + * @returns {String} The converted HEX String. + */ +function rgbToHex(r, g, b) { + return `#${rgbParameterToHex(r)}${rgbParameterToHex(g)}${rgbParameterToHex( + b, + )}`; +} + +/** + * Converts each RGB parameter to its corresponding HEX value + * @param {param} This will be either red, green or blue from RGB. + * @returns {String} The converted number to its two digit HEX String. + */ +function rgbParameterToHex(param) { + const hex = param.toString(16); + return hex.length == 1 ? `0${hex}` : hex; +} diff --git a/app/views/admin/creator_settings/_form.html.erb b/app/views/admin/creator_settings/_form.html.erb index 2fa80953e..806e00810 100644 --- a/app/views/admin/creator_settings/_form.html.erb +++ b/app/views/admin/creator_settings/_form.html.erb @@ -35,13 +35,16 @@ <%= text_field_tag :primary_brand_color_hex, ::Settings::UserExperience.primary_brand_color_hex, pattern: "^#+([a-fA-F0-9]{6})$", + title: "Provide a valid HEX Color or pick your color from the color picker.", placeholder: ::Settings::UserExperience.primary_brand_color_hex, - class: "crayons-textfield js-color-field" %> + class: "crayons-textfield js-color-field", + "data-action": "change->creator-settings#updateBranding" %> <%= color_field_tag :primary_brand_color_hex, ::Settings::UserExperience.primary_brand_color_hex, pattern: "^#+([a-fA-F0-9]{6})$", placeholder: ::Settings::UserExperience.primary_brand_color_hex, class: "crayons-color-selector js-color-field ml-2", + "data-action": "change->creator-settings#updateBranding", required: true %> @@ -52,11 +55,11 @@ Who can join this community?
- <%= radio_button_tag :invite_only_mode, "0", class: "crayons-field crayons-field--radio", required: true %> + <%= radio_button_tag :invite_only_mode, "0", false, class: "crayons-radio" %>
- <%= radio_button_tag :invite_only_mode, "1", class: "crayons-field crayons-field--radio", required: true %> + <%= radio_button_tag :invite_only_mode, "1", true, class: "crayons-radio" %>
@@ -68,11 +71,11 @@ Who can view content in this community?
- <%= radio_button_tag :public, "0", class: "crayons-field crayons-field--radio", required: true %> + <%= radio_button_tag :public, "0", false, class: "crayons-radio" %>
- <%= radio_button_tag :public, "1", class: "crayons-field crayons-field--radio", required: true %> + <%= radio_button_tag :public, "1", true, class: "crayons-radio" %>
diff --git a/app/views/devise/confirmations/new.html.erb b/app/views/devise/confirmations/new.html.erb index c364ffd9b..2e4fa6801 100644 --- a/app/views/devise/confirmations/new.html.erb +++ b/app/views/devise/confirmations/new.html.erb @@ -22,7 +22,7 @@ if you didn't get the email... - <%= inline_svg_tag("forem-background.svg", aria: true, title: "forem background", class: "absolute bottom-0 right-0 hidden m:block") %> + <%= inline_svg_tag("forem-background.svg", aria: true, title: "forem background", class: "forem-background absolute bottom-0 right-0 hidden m:block") %> <% end %> - <%= inline_svg_tag("forem-background.svg", aria: true, title: "forem background", class: "absolute bottom-0 right-0 hidden m:block") %> + <%= inline_svg_tag("forem-background.svg", aria: true, title: "forem background", class: "forem-background absolute bottom-0 right-0 hidden m:block") %> diff --git a/app/views/users/show.html.erb b/app/views/users/show.html.erb index 3aca424cf..af7ec6044 100644 --- a/app/views/users/show.html.erb +++ b/app/views/users/show.html.erb @@ -33,7 +33,7 @@
-