Skip to content
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

Add proper brand colors to drills menu #42663

Merged
merged 12 commits into from
May 17, 2024
Merged

Add proper brand colors to drills menu #42663

merged 12 commits into from
May 17, 2024

Conversation

deniskaber
Copy link
Contributor

@deniskaber deniskaber commented May 14, 2024

Closes #42560 and #42680

Description

This adds theming possibilities for InteractiveQuestion - filters, drills, table content.

How to verify

Describe the steps to verify that the changes are working as expected.

  1. build SDK and use it with https://github.com/metabase/embedding-sdk-customer-zero/tree/42560-q-theming
  2. change colors in https://github.com/metabase/embedding-sdk-customer-zero/blob/42560-q-theming/src/components/AppProvider.tsx#L33
  3. Content should be updated according to the theme.

Demo

Screen.Recording.2024-05-16.at.02.51.02.mov

Checklist

  • Tests have been added/updated to cover changes in this PR

@deniskaber deniskaber self-assigned this May 14, 2024
@metabase-bot metabase-bot bot added .Team/Embedding visual Run Percy visual testing labels May 14, 2024
Copy link

github-actions bot commented May 14, 2024

Codenotify: Notifying subscribers in CODENOTIFY files for diff 752bf84...972134c.

Notify File(s)
@alxnddr frontend/src/metabase/visualizations/components/ClickActions/ClickActionControl.module.css
frontend/src/metabase/visualizations/components/ClickActions/ClickActionControl.styled.tsx
frontend/src/metabase/visualizations/components/ClickActions/ClickActionsPopover.styled.tsx
frontend/src/metabase/visualizations/components/ClickActions/ClickActionsViewSection.styled.tsx
frontend/src/metabase/visualizations/components/TableInteractive/TableInteractive.module.css
frontend/src/metabase/visualizations/visualizations/PieChart/PieChart.module.css
@kdoh frontend/src/metabase/ui/components/buttons/Button/Button.styled.tsx
frontend/src/metabase/ui/components/inputs/Input/Input.styled.tsx
frontend/src/metabase/ui/components/inputs/Select/Select.styled.tsx
frontend/src/metabase/ui/components/overlays/HoverCard/HoverCard.styled.tsx
frontend/src/metabase/ui/components/overlays/Menu/Menu.styled.tsx
frontend/src/metabase/ui/components/overlays/Popover/Popover.styled.tsx
frontend/src/metabase/ui/utils/colors.ts
@ranquild enterprise/frontend/src/metabase-enterprise/whitelabel/lib/whitelabel.js

Copy link

replay-io bot commented May 14, 2024

Status Complete ↗︎
Commit 972134c
Results
⚠️ 6 Flaky
2519 Passed

@deniskaber deniskaber requested a review from a team May 15, 2024 23:59
Copy link
Contributor

@heypoom heypoom left a comment

Choose a reason for hiding this comment

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

Looks good to me so far! I think we should keep the external color scheme separate from the internal ones though, because of #42680 (explained in the below comments).

This is also because some of our colors might not make sense to external users, such as error and success used in smart scalar to indicate negative and positive changes (best to remap to negative and positive as discussed with Alessio), and we can provide public-facing TSDocs on those.

Also a note on the use of global mutations in useMemo, which might be nice if we can replace that with useEffect or other construct to better indicate we're doing impure mutations.

Comment on lines +45 to +46
--mb-color-bg-white: ${({ theme }) => theme.fn.themeColor("bg-white")};
--mb-color-bg-black: ${({ theme }) => theme.fn.themeColor("bg-black")};
Copy link
Contributor

Choose a reason for hiding this comment

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

note to future self: we should consider remapping bg-black and bg-white when we are tackling #42680 to remap colors to make sense for dark mode users

Comment on lines 40 to 48
if (theme?.colors) {
Object.entries(theme.colors).forEach(([key, value]) => {
colors[key as keyof MetabaseColors] = value;
});
} else {
Object.entries(originalColors).forEach(([key, value]) => {
colors[key as keyof MetabaseColors] = value;
});
}
Copy link
Contributor

@heypoom heypoom May 16, 2024

Choose a reason for hiding this comment

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

I wonder if we only pass in partial theme.colors, does the rest of the colors (i.e. originalColors) still gets applied? For instance, if I set text-dark: '#2d2d30' but didn't set anything else, does the default mb-brand-color gets applied? I'm asking this because of what the else branch is doing.

Also, I think we are globally mutating the colors object here, so semantically I don't think putting it in useMemo make sense, as useMemo usually communicates purity.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Also, I think we are globally mutating the colors object here, so semantically I don't think putting it in useMemo make sense, as useMemo usually communicates purity.

Semantically - yes, but we need updated colors object to calculate mantine theme overrides. I don't think we should enforce semantics and introduce extra rerenders because of it.

Copy link
Contributor

Choose a reason for hiding this comment

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

@deniskaber Yeah, I couldn't think of a way to cleanly do this without an extra re-render cycle either, so I think this will have to do 👍🏻

Copy link
Contributor

@heypoom heypoom May 16, 2024

Choose a reason for hiding this comment

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

A way to make this logic jump out a bit more would be to move it to a named function, say setGlobalMetabaseColors. It kinda makes the logic jumps out more that it's not doing the usual thing that you would expect it to, so the reader knows to be prepared for that

Comment on lines 26 to 28
export interface MetabaseColors {
/** Primary brand color */
brand?: string;

/** Text color on dark elements. Should be a lighter color for readability. */
"text-dark"?: string;

/** Text color on light elements. Should be a darker color for readability. */
"text-light"?: string;

/** Lighter variation of dark text on light elements. */
"text-medium"?: string;
}

export type MetabaseColor = keyof MetabaseColors;
export type MetabaseColors = ColorPalette;
Copy link
Contributor

Choose a reason for hiding this comment

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

@deniskaber we have a plan to remap the external-facing color names to the internal ones in #42680, as the names we use currently (e.g. text-dark and text-light) does not make sense for SDK customers who uses dark mode, so the idea there is to remap them (e.g. text-primary to text-dark, text-secondary to text-light and so on) - see the discussion here

If we don't remap the color names, then we would have to do a rename for the entire codebase - which is going to be a lot of diffs (and potentially cause confusion internally)

@@ -2,7 +2,7 @@ import { colors } from "metabase/lib/colors/palette";
import MetabaseSettings from "metabase/lib/settings";

export function updateColors() {
const scheme = MetabaseSettings.get("application-colors");
const scheme = MetabaseSettings.get("application-colors") || {};
Copy link
Contributor

Choose a reason for hiding this comment

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

Just a curiosity question, but I think this field is unset when the application colors haven't been overridden in the appearance settings? So, I think this value is only populated when the users set them in the admin panel? If so, using a default like this should work fine.

cc @WiNloSt we were discussing about this issue in Slack/GitHub earlier

Copy link
Member

@WiNloSt WiNloSt May 16, 2024

Choose a reason for hiding this comment

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

Yeah, just retested. And also from the default value, it will always return a map. That means you don't need || {} part.

(defsetting application-colors
(deferred-tru "Choose the colors used in the user interface throughout Metabase and others specifically for the charts. You need to refresh your browser to see your changes take effect.")
:visibility :public
:export? true
:type :json
:feature :whitelabel
:default {}
:audit :getter
:doc "To change the user interface colors:

Copy link
Contributor

@heypoom heypoom May 16, 2024

Choose a reason for hiding this comment

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

@WiNloSt it was returning undefined or null in the SDK though, so I think that is why Denis added the || {} part. Doesn't that happen to you when running the demo app?

Copy link
Member

Choose a reason for hiding this comment

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

adding || {} looks like a hack to me if we expect MetabaseSettings.get('application-colors ') to always return a map.

By doing this wouldn't we just ignore the fact that application-colors doesn't return the correct value? That means when users set colors in appearance settings, if we don't provide theme would those colors even work?

Copy link
Contributor

@heypoom heypoom May 16, 2024

Choose a reason for hiding this comment

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

That's what I want to know as well - why wasn't it returning a map despite public-settings.clj...

My (probably wrong) guess is that if application-colors is not set, then the default colors defined in colors would get applied. However, when one or more colors is set then it's going to return a map. That would explain this diff I saw above as well. Would be great if @deniskaber could confirm our assumptions here 🙏🏻

    } else {
      Object.entries(originalColors).forEach(([key, value]) => {
        colors[key as keyof MetabaseColors] = value;
      });
    }

Copy link
Member

@WiNloSt WiNloSt May 16, 2024

Choose a reason for hiding this comment

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

Well I don't think the color from instance is working, my brand needs to be a distinct shade of blue (almost purple)
image

Also, this seems to make the admin settings look off. Can you confirm that too @heypoom ?
image

Copy link
Contributor

@heypoom heypoom May 16, 2024

Choose a reason for hiding this comment

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

@WiNloSt yes, can confirm on my end that this breaks the dashboard styling. Thanks for running this locally!

For the customized user interface colors issue, let's tackle this separately in #42705.

CleanShot 2567-05-16 at 17 59 55@2x

CleanShot 2567-05-16 at 18 00 12@2x

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Hey @heypoom , @WiNloSt . In the main metabase app settings get populated into MetabaseSettings object from server on page load - https://github.com/metabase/metabase/blob/master/resources/frontend_client/index_template.html#L27
So, when this piece of code gets executed, we already have MetabaseSettings object initialized with real values.

But in the SDK context we don't have this logic. MetabaseSettings is empty until we load user settings in provider, which is already late. We didn't have this issue in early builds because we haven't used EE plugins.
So, ideally we should initialize MetabaseSettings with some default settings, or load real settings before importing plugins (which is very tricky).

Here I added a fix that blocked me from running the demo. I can revert it if needed

Copy link
Contributor

@heypoom heypoom May 16, 2024

Choose a reason for hiding this comment

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

@deniskaber I see, thanks for the explanation! As I will be working on #42705 next, do you know if there's a way we can retrieve the application-colors object (that was previously from {{bootstrapJSON}}) dynamically rather than relying on index_template.html? So I can update the updateColors logic accordingly.

I think it's OK if this PR doesn't cover the customized ui colors logic, I can tackle that in my PR later. I think we can stick with || {} for now just to not throw the error, no need to revert it.

We can focus on resolving the dashboard styling issue (blue background color leaking into buttons) in the above screenshot for now 🙏🏻

Copy link
Contributor Author

Choose a reason for hiding this comment

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

@heypoom , we get application-colors in /api/user/current api request which happens here - https://github.com/metabase/metabase/blob/master/enterprise/frontend/src/embedding-sdk/hooks/private/use-init-data.ts#L75
During SDK initialization basically (but after user auth).

Copy link
Contributor

@heypoom heypoom left a comment

Choose a reason for hiding this comment

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

Some of the changes here appears to break the dashboard styling - see the screenshots here. Could you help to investigate this? Also added some review comments above 🙏🏻

@deniskaber deniskaber requested review from WiNloSt, heypoom and a team May 16, 2024 15:18
# Conflicts:
#	enterprise/frontend/src/embedding-sdk/components/private/SdkContentWrapper.tsx
#	enterprise/frontend/src/embedding-sdk/lib/theme/get-embedding-theme.ts
#	frontend/src/metabase/visualizations/components/ClickActions/ClickActionControl.styled.tsx
#	frontend/src/metabase/visualizations/components/TableInteractive/TableInteractive.module.css
@deniskaber deniskaber added the embedding-sdk-build Triggers embedding SDK package build label May 16, 2024
@deniskaber deniskaber added the no-backport Do not backport this PR to any branch label May 16, 2024
@heypoom
Copy link
Contributor

heypoom commented May 17, 2024

Thanks! Re-testing this locally now

Copy link
Contributor

@heypoom heypoom left a comment

Choose a reason for hiding this comment

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

I re-tested locally and the color leak issue in the dashboard no longer happens, looks great so far! Thanks for re-mapping the colors too 😄

@@ -34,6 +38,12 @@ const MetabaseProviderInternal = ({
theme,
}: MetabaseProviderProps): JSX.Element => {
const themeOverride = useMemo(() => {
const combinedThemeColors = getThemedColorsPallete(theme?.colors);
Copy link
Contributor

Choose a reason for hiding this comment

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

nit: typo

Suggested change
const combinedThemeColors = getThemedColorsPallete(theme?.colors);
const combinedThemeColors = getThemedColorsPalette(theme?.colors);

@@ -27,7 +27,7 @@ export const DEFAULT_EMBEDDED_COMPONENT_THEME: MetabaseComponentTheme = merge(
{
table: {
cell: {
backgroundColor: "white",
backgroundColor: "bg-white",
Copy link
Contributor

Choose a reason for hiding this comment

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

Good catch - thanks!


const originalColors = { ...colors };

export function getThemedColorsPallete(
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
export function getThemedColorsPallete(
export function getThemedColorsPalette(

@heypoom heypoom requested a review from a team May 17, 2024 12:09
@deniskaber deniskaber enabled auto-merge (squash) May 17, 2024 12:57
@deniskaber deniskaber merged commit a6035a1 into master May 17, 2024
108 checks passed
@deniskaber deniskaber deleted the 42560-q-theming branch May 17, 2024 13:40
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
embedding-sdk-build Triggers embedding SDK package build no-backport Do not backport this PR to any branch .Team/Embedding visual Run Percy visual testing
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Interactive question popovers and filters should follow the embedding theme
3 participants