From 22ea8c0fdb275ca8686c5d5643b5be62c770515b Mon Sep 17 00:00:00 2001 From: Henriette Darge Date: Tue, 2 Jul 2024 09:14:16 +0200 Subject: [PATCH 1/3] Calculate variants of the defined colours so that they work in both modes --- app/helpers/colors_helper.rb | 115 ++++++++++++++---- app/models/colors/hex_color.rb | 1 + .../wp-status-button.component.sass | 6 +- .../highlighting/highlighting.functions.ts | 5 - .../timelines/elements/_bar.sass | 1 + 5 files changed, 99 insertions(+), 29 deletions(-) diff --git a/app/helpers/colors_helper.rb b/app/helpers/colors_helper.rb index c2dfcd88511b..f98e2b2b0bf3 100644 --- a/app/helpers/colors_helper.rb +++ b/app/helpers/colors_helper.rb @@ -61,10 +61,8 @@ def colored_text(color) ## def color_css Color.find_each do |color| - concat ".__hl_inline_color_#{color.id}_dot::before { background-color: #{color.hexcode} !important;}" - concat ".__hl_inline_color_#{color.id}_dot::before { border: 1px solid #555555 !important;}" if color.bright? - concat ".__hl_inline_color_#{color.id}_text { color: #{color.hexcode} !important;}" - concat ".__hl_inline_color_#{color.id}_text { -webkit-text-stroke: 0.5px grey; text-stroke: 0.5px grey;}" if color.super_bright? + set_background_colors_for class_name: ".__hl_inline_color_#{color.id}_dot::before", hexcode: color.hexcode + set_foreground_colors_for class_name: ".__hl_inline_color_#{color.id}_text", hexcode: color.hexcode end end @@ -80,27 +78,13 @@ def resource_color_css(name, scope) next end - styles = color.color_styles - background_style = styles.map { |k, v| "#{k}:#{v} !important" }.join(";") - if name === "type" - concat ".__hl_inline_#{name}_#{entry.id} { color: #{color.hexcode} !important;}" - concat ".__hl_inline_#{name}_#{entry.id} { -webkit-text-stroke: 0.5px grey;}" if color.super_bright? - - border_color = color.super_bright? ? "#555555" : color.hexcode - concat ".__hl_background_#{name}_#{entry.id} { border-color: #{border_color} !important; }" + set_foreground_colors_for class_name: ".__hl_inline_#{name}_#{entry.id}", hexcode: color.hexcode else - border_color = color.bright? ? "#555555" : color.hexcode - concat ".__hl_inline_#{name}_#{entry.id}::before { #{background_style}; border-color: #{border_color}; }\n" + set_background_colors_for class_name: ".__hl_inline_#{name}_#{entry.id}::before", hexcode: color.hexcode end - concat ".__hl_background_#{name}_#{entry.id} { #{background_style}; }\n" - - # Mark color as bright through CSS variable - # so it can be used to add a separate -bright class - unless color.bright? - concat ":root { --hl-#{name}-#{entry.id}-dark: #{styles[:color]} }\n" - end + set_background_colors_for class_name: ".__hl_background_#{name}_#{entry.id}", hexcode: color.hexcode end end @@ -117,4 +101,93 @@ def icon_for_color(color, options = {}) def color_by_variable(variable) DesignColor.find_by(variable:)&.hexcode end + + def set_background_colors_for(class_name:, hexcode:) + mode = User.current.pref.theme.split("_", 2)[0] + + concat "#{class_name} { #{default_color_styles(hexcode)} }" + if mode == "dark" + concat "#{class_name} { #{default_variables_dark} }" + concat "#{class_name} { #{highlighted_background_dark} }" + else + concat "#{class_name} { #{default_variables_light} }" + concat "#{class_name} { #{highlighted_background_light} }" + end + end + + def set_foreground_colors_for(class_name:, hexcode:) + mode = User.current.pref.theme.split("_", 2)[0] + + concat "#{class_name} { #{default_color_styles(hexcode)} }" + if mode == "dark" + concat "#{class_name} { #{default_variables_dark} }" + concat "#{class_name} { #{highlighted_foreground_dark} }" + else + concat "#{class_name} { #{default_variables_light} }" + concat "#{class_name} { #{highlighted_foreground_light} }" + end + end + + # rubocop:disable Layout/LineLength + def default_color_styles(hex) + color = ColorConversion::Color.new(hex) + rgb = color.rgb + hsl = color.hsl + + "--color-r: #{rgb[:r]}; + --color-g: #{rgb[:g]}; + --color-b: #{rgb[:b]}; + --color-h: #{hsl[:h]}; + --color-s: #{hsl[:s]}; + --color-l: #{hsl[:l]}; + --perceived-lightness: calc( ((var(--color-r) * 0.2126) + (var(--color-g) * 0.7152) + (var(--color-b) * 0.0722)) / 255 ); + --lightness-switch: max(0, min(calc((1/(var(--lightness-threshold) - var(--perceived-lightness)))), 1));" + end + + def default_variables_dark + "--lightness-threshold: 0.6; + --background-alpha: 0.18; + --lighten-by: calc(((var(--lightness-threshold) - var(--perceived-lightness)) * 100) * var(--lightness-switch));" + end + + def default_variables_light + "--lightness-threshold: 0.453; + --border-threshold: 0.75; + --border-alpha: max(0, min(calc((var(--perceived-lightness) - var(--border-threshold)) * 100), 1));" + end + + def highlighted_background_dark + "color: hsl(var(--color-h), calc(var(--color-s) * 1%), calc((var(--color-l) + var(--lighten-by)) * 1%)) !important; + background: rgba(var(--color-r), var(--color-g), var(--color-b), var(--background-alpha)) !important; + border: 1px solid hsl(var(--color-h), calc(var(--color-s) * 1%), calc((var(--color-l) + var(--lighten-by)) * 1%)) !important;" + end + + def highlighted_background_light + style = "color: hsl(0deg, 0%, calc(var(--lightness-switch) * 100%)) !important; + background: rgb(var(--color-r), var(--color-g), var(--color-b)) !important;" + mode = User.current.pref.theme + + if mode == "light_high_contrast" + style += "border: 1px solid hsla(var(--color-h), calc(var(--color-s) * 1%), calc((var(--color-l) - 75) * 1%), 1) !important;" + else + style += "border: 1px solid hsla(var(--color-h), calc(var(--color-s) * 1%), calc((var(--color-l) - 25) * 1%), var(--border-alpha)) !important;" + end + + style + end + + def highlighted_foreground_dark + "color: hsla(var(--color-h), calc(var(--color-s) * 1%), calc((var(--color-l) + var(--lighten-by)) * 1%), 1) !important;" + end + + def highlighted_foreground_light + mode = User.current.pref.theme + + if mode == "light_high_contrast" + "color: hsla(var(--color-h), calc(var(--color-s) * 1%), calc((var(--color-l) - (var(--color-l) * 0.5)) * 1%), 1); !important;" + else + "color: hsla(var(--color-h), calc(var(--color-s) * 1%), calc((var(--color-l) - (var(--color-l) * 0.22)) * 1%), 1); !important;" + end + end + # rubocop:enable Layout/LineLength end diff --git a/app/models/colors/hex_color.rb b/app/models/colors/hex_color.rb index 9ee6db0b71d2..c5aca6f16aaa 100644 --- a/app/models/colors/hex_color.rb +++ b/app/models/colors/hex_color.rb @@ -15,6 +15,7 @@ def contrasting_color(light_color: "#FFFFFF", dark_color: "#333333") # Get the fill style for this color. # If the color is light, use a dark font. # Otherwise, use a white font. + # TODO: remove def color_styles(light_color: "#FFFFFF", dark_color: "#333333") if bright? { color: dark_color, "background-color": hexcode } diff --git a/frontend/src/app/features/work-packages/components/wp-buttons/wp-status-button/wp-status-button.component.sass b/frontend/src/app/features/work-packages/components/wp-buttons/wp-status-button/wp-status-button.component.sass index 89abdac88706..d6484c557127 100644 --- a/frontend/src/app/features/work-packages/components/wp-buttons/wp-status-button/wp-status-button.component.sass +++ b/frontend/src/app/features/work-packages/components/wp-buttons/wp-status-button/wp-status-button.component.sass @@ -5,9 +5,9 @@ @include text-shortener(false) padding: 5px margin-bottom: 0 - background-color: var(--status-selector-bg-color) - border: 1px solid var(--status-selector-border-color) - color: white + background-color: var(--label-orange-bgColor-active) + border: 1px solid var(--label-orange-fgColor-rest) + color: var(--body-font-color) max-width: 100% display: flex diff --git a/frontend/src/app/features/work-packages/components/wp-fast-table/builders/highlighting/highlighting.functions.ts b/frontend/src/app/features/work-packages/components/wp-fast-table/builders/highlighting/highlighting.functions.ts index 91167eb217b5..63bddc3952b5 100644 --- a/frontend/src/app/features/work-packages/components/wp-fast-table/builders/highlighting/highlighting.functions.ts +++ b/frontend/src/app/features/work-packages/components/wp-fast-table/builders/highlighting/highlighting.functions.ts @@ -30,9 +30,4 @@ export namespace Highlighting { return '__hl_date_not_overdue'; } - - export function isBright(styles:CSSStyleDeclaration, property:string, id:string|number) { - const variable = `--hl-${property}-${id}-dark`; - return styles.getPropertyValue(variable) !== ''; - } } diff --git a/frontend/src/global_styles/content/work_packages/timelines/elements/_bar.sass b/frontend/src/global_styles/content/work_packages/timelines/elements/_bar.sass index 728ad52f8596..5ea4d5643edd 100644 --- a/frontend/src/global_styles/content/work_packages/timelines/elements/_bar.sass +++ b/frontend/src/global_styles/content/work_packages/timelines/elements/_bar.sass @@ -8,6 +8,7 @@ overflow: hidden padding: 0 0 0 5px white-space: nowrap + border: none .leftHandle position: absolute From 5a77b482ad6366beb8e9950347df756c8d3999fe Mon Sep 17 00:00:00 2001 From: Henriette Darge Date: Wed, 3 Jul 2024 11:54:47 +0200 Subject: [PATCH 2/3] Remove unused code --- app/helpers/colors_helper.rb | 12 ------------ app/models/colors/hex_color.rb | 16 ---------------- 2 files changed, 28 deletions(-) diff --git a/app/helpers/colors_helper.rb b/app/helpers/colors_helper.rb index f98e2b2b0bf3..3fa7694d6b7e 100644 --- a/app/helpers/colors_helper.rb +++ b/app/helpers/colors_helper.rb @@ -33,12 +33,6 @@ def options_for_colors(colored_thing) options = {} options[:name] = c.name options[:value] = c.id - options[:data] = { - color: c.hexcode, - bright: c.bright?, - dark: c.dark?, - background: c.contrasting_color(light_color: "transparent") - } options[:selected] = true if c.id == colored_thing.color_id colors.push(options) @@ -50,12 +44,6 @@ def selected_color(colored_thing) colored_thing.color_id end - def colored_text(color) - background = color.contrasting_color(dark_color: "#333", light_color: "transparent") - style = "background-color: #{background}; color: #{color.hexcode}" - content_tag(:span, color.hexcode, class: "color--text-preview", style:) - end - # # Styles to display colors itself (e.g. for the colors autocompleter) ## diff --git a/app/models/colors/hex_color.rb b/app/models/colors/hex_color.rb index c5aca6f16aaa..2d063c2e9b36 100644 --- a/app/models/colors/hex_color.rb +++ b/app/models/colors/hex_color.rb @@ -1,21 +1,9 @@ module Colors module HexColor - ## - # Returns the best contrasting color, either white or black - # depending on the overall brightness. - def contrasting_color(light_color: "#FFFFFF", dark_color: "#333333") - if bright? - dark_color - else - light_color - end - end - ## # Get the fill style for this color. # If the color is light, use a dark font. # Otherwise, use a white font. - # TODO: remove def color_styles(light_color: "#FFFFFF", dark_color: "#333333") if bright? { color: dark_color, "background-color": hexcode } @@ -31,10 +19,6 @@ def bright? brightness_yiq >= 150 end - def dark? - brightness_yiq < 150 - end - ## # Returns whether the color is very bright according to # YIQ lightness. From c4141fb9f1d6ad3c192cafa94a21692aad080eae Mon Sep 17 00:00:00 2001 From: Henriette Darge Date: Wed, 3 Jul 2024 13:22:41 +0200 Subject: [PATCH 3/3] Add timestamps to user_preferences table. Thus we know when the cached styles are invalid and needs to be reloaded. --- app/helpers/highlighting_helper.rb | 2 +- ...31639_add_timestamps_to_user_preferences.rb | 5 +++++ spec/models/user_preference_spec.rb | 18 ------------------ 3 files changed, 6 insertions(+), 19 deletions(-) create mode 100644 db/migrate/20240703131639_add_timestamps_to_user_preferences.rb diff --git a/app/helpers/highlighting_helper.rb b/app/helpers/highlighting_helper.rb index 1e15a2227f27..eadd74133eb2 100644 --- a/app/helpers/highlighting_helper.rb +++ b/app/helpers/highlighting_helper.rb @@ -4,6 +4,6 @@ def highlight_css_version_tag(max_updated_at = highlight_css_updated_at) end def highlight_css_updated_at - ApplicationRecord.most_recently_changed Status, IssuePriority, Type + ApplicationRecord.most_recently_changed Status, IssuePriority, Type, UserPreference end end diff --git a/db/migrate/20240703131639_add_timestamps_to_user_preferences.rb b/db/migrate/20240703131639_add_timestamps_to_user_preferences.rb new file mode 100644 index 000000000000..c147e67efc85 --- /dev/null +++ b/db/migrate/20240703131639_add_timestamps_to_user_preferences.rb @@ -0,0 +1,5 @@ +class AddTimestampsToUserPreferences < ActiveRecord::Migration[7.1] + def change + add_timestamps :user_preferences, default: DateTime.now + end +end diff --git a/spec/models/user_preference_spec.rb b/spec/models/user_preference_spec.rb index 272035014089..2d178a9bf87f 100644 --- a/spec/models/user_preference_spec.rb +++ b/spec/models/user_preference_spec.rb @@ -61,24 +61,6 @@ end end - describe "#respond_to?" do - context "for created_at (key not in the schema)" do - it "is does not respond" do - expect(preference) - .not_to respond_to(:created_at) - end - end - end - - describe "an unsupported method" do - context "for created_at (key not in the schema)" do - it "raises an error" do - expect { preference.created_at } - .to raise_error NoMethodError - end - end - end - describe "sort order" do it_behaves_like "accepts real and false booleans", :comments_in_reverse_order=,