Skip to content

FEATURE: Theme-owned color palettes #32795

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 3 commits into
base: main
Choose a base branch
from

Conversation

OsamaSayegh
Copy link
Member

This PR replaces the color palette dropdown on the theme page with a color palette editor that enables editing the theme's color palette directly from the theme page. With this change, a theme's color palette is strongly tied to its theme and can't be linked to other themes and it can't be selected by users without using the theme as well.

All of the changes are behind a feature flag. To enable it, turn on the use_overhauled_theme_color_palette setting.

Screenshot:

@OsamaSayegh OsamaSayegh force-pushed the feature/theme-owned-palettes branch 3 times, most recently from 0026468 to 768923f Compare May 19, 2025 09:29
@OsamaSayegh OsamaSayegh force-pushed the feature/theme-owned-palettes branch from 768923f to 53295b1 Compare May 19, 2025 09:48
}

@action
onDarkColorChange(name, value) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm wondering if we can just pass the color object to this callback instead of having to loop through again in the controller to retrieve the object.

@@ -476,4 +488,26 @@ export default class AdminCustomizeThemesShowController extends Controller {
editColorScheme() {
this.router.transitionTo("adminCustomize.colors.show", this.colorSchemeId);
}

@action
onLightColorChange(name, value) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Comment on lines +436 to +440
<DButton
class="admin-theme__save-palette-changes btn-primary"
@icon="check"
@action={{@controller.saveColorChanges}}
/>
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it will be useful to add a disable state for this button since it involves an AJAX call.

Comment on lines +257 to +267
@discourseComputed(
"model.colorPalette.colors.@each.{hex,originalHex,dark_hex,originalDarkHex}"
)
hasChangedColors() {
return this.model.colorPalette.colors.some((color) => {
return (
color.hex !== color.originalHex ||
color.dark_hex !== color.originalDarkHex
);
});
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Instead of having to inspect each object for changes, perhaps we can pass a tracked property to the ColorPaletteEditor component for it to update this tracked property when changes are made?

@@ -76,6 +60,10 @@ export default class ColorScheme extends EmberObject {
init() {
super.init(...arguments);

const colors = A(this.colors ?? []);
this.colors = colors.map((c) => {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

All these looping in the PR is also making me wonder if we selected the wrong data structure here. Perhaps we should be using a object here instead of an array so that we can easily look up a color object by its name?

it "creates a theme-owned color palette if one doesn't exist" do
expect(theme.owned_color_palette).to be_nil

max_id = ColorScheme.maximum(:id) || 0
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
max_id = ColorScheme.maximum(:id) || 0

This line is not used.

Comment on lines +1534 to +1567
it "updates an existing theme-owned color palette" do
palette = theme.find_or_create_owned_color_palette
color = palette.colors.find_by(name: "primary")

put "/admin/themes/#{theme.id}/change-colors.json",
params: {
colors: [{ name: "primary", hex: "aabbcc", dark_hex: "ccddee" }],
}

expect(response.status).to eq(200)
color.reload
expect(color.hex).to eq("aabbcc")
expect(color.dark_hex).to eq("ccddee")
end

it "only updates specified colors" do
palette = theme.find_or_create_owned_color_palette
primary_color = palette.colors.find_by(name: "primary")
secondary_color = palette.colors.find_by(name: "secondary")

original_secondary_hex = secondary_color.hex

put "/admin/themes/#{theme.id}/change-colors.json",
params: {
colors: [{ name: "primary", hex: "112233", dark_hex: "445566" }],
}

expect(response.status).to eq(200)
primary_color.reload
secondary_color.reload

expect(primary_color.hex).to eq("112233")
expect(secondary_color.hex).to eq(original_secondary_hex)
end
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These two tests can be combined into one IMO.

Comment on lines +167 to +180
it "shows color palette editor when feature is enabled" do
theme_page.visit(theme.id)

expect(theme_page).to have_color_palette_editor
expect(theme_page).to have_no_color_scheme_selector
end

it "doesn't show color palette editor when feature is disabled" do
SiteSetting.use_overhauled_theme_color_palette = false
theme_page.visit(theme.id)

expect(theme_page).to have_no_color_palette_editor
expect(theme_page).to have_color_scheme_selector
end
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Personally, I don't think these two cases are worth the overhead of system tests. The risk of a regression here is also low IMO.

expect(theme_page).to have_color_scheme_selector
end

it "allows editing colors without affecting other themes" do
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
it "allows editing colors without affecting other themes" do
it "allows editing colors" do

I don't think we need to verify affecting other themes in system tests. That is already covered by the controller test.

Comment on lines +195 to +196
updated_color = theme_page.color_palette_editor.get_color_value("primary")
expect(updated_color).to eq("#ff000e")
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is not relying on capybara matches so has a good chance to be flaky.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Development

Successfully merging this pull request may close these issues.

3 participants