DEV: Backend support for light/dark mode in color palettes (#30893)

We're embarking on a project for overhauling the color palette and theme
systems in Discourse. As part of this project, we're making each color
palette include light and dark modes instead of the status quo of
requiring 2 separate color palettes to implement light and dark modes.

This commit is a first step towards that goal; it adds a code path for
generating and serving `color_definitions` stylesheets using the
built-in dark variant of a color palette. All of this code path is
behind a default-off site setting `use_overhauled_theme_color_palette`,
so there's no change in behavior unless the setting is enabled.

Internal topic: t/141467.
This commit is contained in:
Osama Sayegh
2025-01-23 15:54:49 +03:00
committed by GitHub
parent 13f86c99ea
commit 10f34ddf86
10 changed files with 193 additions and 41 deletions

View File

@ -676,6 +676,73 @@ RSpec.describe Stylesheet::Manager do
expect(link).to include("/stylesheets/color_definitions_funky-bunch_#{cs.id}_")
end
it "generates the dark mode of a color scheme when the dark option is specified" do
scheme = ColorScheme.create_from_base(name: "Neutral", base_scheme_id: "Neutral")
ColorSchemeRevisor.revise(
scheme,
colors: [{ name: "primary", hex: "CABFAF", dark_hex: "FAFCAB" }],
)
theme = Fabricate(:theme)
manager = manager(theme.id)
dark_stylesheet =
Stylesheet::Manager::Builder.new(
target: :color_definitions,
theme: theme,
color_scheme: scheme,
manager: manager,
dark: true,
).compile
light_stylesheet =
Stylesheet::Manager::Builder.new(
target: :color_definitions,
theme: theme,
color_scheme: scheme,
manager: manager,
).compile
expect(light_stylesheet).to include("--primary: #CABFAF;")
expect(light_stylesheet).to include("color_definitions_neutral_#{scheme.id}_#{theme.id}")
expect(light_stylesheet).not_to include(
"color_definitions_neutral_#{scheme.id}_#{theme.id}_dark",
)
expect(dark_stylesheet).to include("--primary: #FAFCAB;")
expect(dark_stylesheet).to include("color_definitions_neutral_#{scheme.id}_#{theme.id}_dark")
end
it "uses the light colors as fallback if the dark scheme doesn't define them" do
scheme = ColorScheme.create_from_base(name: "Neutral", base_scheme_id: "Neutral")
ColorSchemeRevisor.revise(scheme, colors: [{ name: "primary", hex: "BACFAB", dark_hex: nil }])
theme = Fabricate(:theme)
manager = manager(theme.id)
dark_stylesheet =
Stylesheet::Manager::Builder.new(
target: :color_definitions,
theme: theme,
color_scheme: scheme,
manager: manager,
dark: true,
).compile
light_stylesheet =
Stylesheet::Manager::Builder.new(
target: :color_definitions,
theme: theme,
color_scheme: scheme,
manager: manager,
).compile
expect(light_stylesheet).to include("--primary: #BACFAB;")
expect(light_stylesheet).to include("color_definitions_neutral_#{scheme.id}_#{theme.id}")
expect(light_stylesheet).not_to include(
"color_definitions_neutral_#{scheme.id}_#{theme.id}_dark",
)
expect(dark_stylesheet).to include("--primary: #BACFAB;")
expect(dark_stylesheet).to include("color_definitions_neutral_#{scheme.id}_#{theme.id}_dark")
end
it "updates outputted colors when updating a color scheme" do
scheme = ColorScheme.create_from_base(name: "Neutral", base_scheme_id: "Neutral")
theme = Fabricate(:theme)
@ -905,7 +972,7 @@ RSpec.describe Stylesheet::Manager do
# Ensure we force compile each theme only once
expect(output.scan(/#{child_theme_with_css.name}/).length).to eq(2)
expect(StylesheetCache.count).to eq(22) # (3 themes * 2 targets) + 16 color schemes (2 themes * 8 color schemes (7 defaults + 1 theme scheme))
expect(StylesheetCache.count).to eq(38) # (3 themes * 2 targets) + 32 color schemes (2 themes * 8 color schemes (7 defaults + 1 theme scheme) * 2 (light and dark mode per scheme))
end
it "generates precompiled CSS - core and themes" do
@ -913,7 +980,7 @@ RSpec.describe Stylesheet::Manager do
Stylesheet::Manager.precompile_theme_css
results = StylesheetCache.pluck(:target)
expect(results.size).to eq(30) # 11 core targets + 9 theme + 10 color schemes
expect(results.size).to eq(46) # 8 core targets + 6 theme + 32 color schemes (light and dark mode per scheme)
theme_targets.each do |tar|
expect(
@ -929,7 +996,7 @@ RSpec.describe Stylesheet::Manager do
Stylesheet::Manager.precompile_theme_css
results = StylesheetCache.pluck(:target)
expect(results.size).to eq(30) # 11 core targets + 9 theme + 10 color schemes
expect(results.size).to eq(46) # 8 core targets + 6 theme + 32 color schemes (light and dark mode per scheme)
expect(results).to include("color_definitions_#{scheme1.name}_#{scheme1.id}_#{user_theme.id}")
expect(results).to include(