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

Merged
merged 20 commits into from
Jun 4, 2025
Merged

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 4 times, most recently from 768923f to 53295b1 Compare May 19, 2025 09:48
@OsamaSayegh OsamaSayegh force-pushed the feature/theme-owned-palettes branch from f903ffa to 3169855 Compare May 29, 2025 12:54
@github-actions github-actions bot added the i18n PRs which update English locale files or i18n related code label May 29, 2025
@OsamaSayegh OsamaSayegh force-pushed the feature/theme-owned-palettes branch 4 times, most recently from 839286d to 069de0f Compare May 30, 2025 15:57
@OsamaSayegh OsamaSayegh force-pushed the feature/theme-owned-palettes branch 2 times, most recently from d3ff343 to 01f7913 Compare June 3, 2025 01:01
Comment on lines +87 to +93
this.toasts.error({
data: {
message: i18n(
"admin.config_areas.color_palettes.invalid_color_length"
),
},
});
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 feel like using a toast here is not the right UI pattern. Normally, input validation errors are shown right below the input so that it is clear which input the error is shown for.

Copy link
Contributor

Choose a reason for hiding this comment

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

Just to make it clear, I don't think this should be a blocking comment but something worth thinking about.

cc @ellaestigoy

if (event.keyCode === 13) {
event.preventDefault();

if (currentValue.length !== 6 && currentValue.length !== 3) {
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 manually validate this, I think we can just rely on the minLength and maxLength attributes on the input to restrict the length?

Copy link
Contributor

Choose a reason for hiding this comment

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

Also, it has limitation that toast will show only when admin hit enter (13 keyCode). But I can click outside and will never know that something is wrong.

Demo

Screen.Recording.2025-06-03.at.4.17.31.pm.mov

When I am out of focus and value is invalid, should we display error as well?

Copy link
Member Author

Choose a reason for hiding this comment

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

I don't believe minlength and maxlength would work here. We want to allow values that are either exactly 3 OR 6 chars long; 4 and 5 are illegal.

Copy link
Member Author

Choose a reason for hiding this comment

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

@lis2 I've pushed a change to show an error toast if the value is invalid when moving focus outside the text input (and show red border around inputs containing invalid colors).

Comment on lines 122 to 139
@action
onTextPaste(event) {
const content = (event.clipboardData || window.clipboardData).getData(
"text"
);

if (!this.isValidHex(content)) {
event.preventDefault();
this.toasts.error({
data: {
message: i18n(
"admin.config_areas.color_palettes.invalid_color_length"
),
},
});
return;
}
}
Copy link
Contributor

Choose a reason for hiding this comment

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

Having to handle all these events manually feels odd to me. In my mind, the pattern should be that each input tracks its own "value" and reacts accordingly when the value of its input changes.

Copy link
Member Author

Choose a reason for hiding this comment

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

I think this is related to the toasts comment above. I'm using toasts because we don't have an outlet/space in the palette editor to show errors for individual colors. If we change our design to make space for errors, I think we'll be able to use the "tracking" pattern you describe here.

Copy link
Contributor

Choose a reason for hiding this comment

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

I see. Let's defer this but we should definitely follow up with product/design about this.

data: JSON.stringify({ colors }),
contentType: "application/json",
});
this.owned_color_palette = paletteData;
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 curious why we need to set this attribute as it doesn't seem to be used anywhere.

Copy link
Member Author

Choose a reason for hiding this comment

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

We serialize this attribute in the Theme model. When a theme's color palette is edited via the /admin/themes/:id/change-colors endpoint, it may create a new color palette record and serialize the new record in the response. In that case, the Theme object in the client app should have the newly created record to avoid stale state when/if the Theme object in question is passed to other areas of the app.

end

def include_base_palette?
object.color_scheme_id.blank? && object.owned_color_palette.blank?
Copy link
Contributor

@tgxworld tgxworld Jun 3, 2025

Choose a reason for hiding this comment

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

I don't seem to see owned_color_palette being eager loaded anywhere so this will result in an N+1 queries problem when this serializer is used to render a list of themes.

Copy link
Member Author

Choose a reason for hiding this comment

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

owned_color_palette is an alias for owned_color_scheme. Theme#include_basic_relations does include the owned_color_scheme relation.

Copy link
Member Author

@OsamaSayegh OsamaSayegh Jun 4, 2025

Choose a reason for hiding this comment

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

(having said that, I think this serializer should never be used to render a list of themes --- it sends way too much data for any list. In the new themes and components listing pages, we have smaller serializers that include only the data needed for these respective pages)

Copy link
Contributor

Choose a reason for hiding this comment

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

I see thank you for clarifying 👍

Copy link
Contributor

Choose a reason for hiding this comment

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

(having said that, I think this serializer should never be used to render a list of themes --- it sends way too much data for any list. In the new themes and components listing pages, we have smaller serializers that include only the data needed for these respective pages)

I see so does that means this controller action will eventually be removed?

themes: serialize_data(@themes, ThemeSerializer),

Copy link
Member Author

Choose a reason for hiding this comment

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

It should be removed given that we no longer call it in the app (/admin/customize/themes has been removed by @lis2), but API compatibility makes it hard to remove endpoints.

if (event.keyCode === 13) {
event.preventDefault();

if (currentValue.length !== 6 && currentValue.length !== 3) {
Copy link
Contributor

Choose a reason for hiding this comment

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

Also, it has limitation that toast will show only when admin hit enter (13 keyCode). But I can click outside and will never know that something is wrong.

Demo

Screen.Recording.2025-06-03.at.4.17.31.pm.mov

When I am out of focus and value is invalid, should we display error as well?

this.colorPaletteChangeTracker.dirtyColorsCount > 0 &&
transition.intent.name !== "adminCustomizeThemes.show.index"
) {
transition.abort();
Copy link
Contributor

Choose a reason for hiding this comment

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

I noticed a bug when I played with it. When I change color and try to leave the page, I see a warning. However, if I frist click settings, warning is not showing. Recorded that

Screen.Recording.2025-06-03.at.4.33.58.pm.mov

Copy link
Member Author

@OsamaSayegh OsamaSayegh Jun 4, 2025

Choose a reason for hiding this comment

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

I'm actually not sure if we should the warning if the user goes to the settings tab of the theme. If you go back to the colors tab, the unsaved changes will not be lost, so you can continue editing and save them even if you flick to the settings tab and back. I can certainly show the warning when navigating to the settings tab if you think it makes more sense to show it.

@lis2
Copy link
Contributor

lis2 commented Jun 3, 2025

Wow, that is huge amount of work! I played with it and it feels much better than the previous version 🎊

I found and recorded 2 bugs, but because it is hidden behind feature flag, I am ok to merge it like that and improve in next iterations. However, I think that Tgx's comments are valid and important.

Finally, I feel that we should not remove feature flag until we solve "revert to original color". But this is problem for another day and let's first close this monster :)

@OsamaSayegh OsamaSayegh force-pushed the feature/theme-owned-palettes branch from aeb2b9d to c689c95 Compare June 4, 2025 03:02
@OsamaSayegh OsamaSayegh merged commit 7fce724 into main Jun 4, 2025
16 checks passed
@OsamaSayegh OsamaSayegh deleted the feature/theme-owned-palettes branch June 4, 2025 04:47
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
i18n PRs which update English locale files or i18n related code
Development

Successfully merging this pull request may close these issues.

5 participants