-
Notifications
You must be signed in to change notification settings - Fork 4.9k
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
Conversation
Codenotify: Notifying subscribers in CODENOTIFY files for diff 752bf84...972134c.
|
|
There was a problem hiding this 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.
--mb-color-bg-white: ${({ theme }) => theme.fn.themeColor("bg-white")}; | ||
--mb-color-bg-black: ${({ theme }) => theme.fn.themeColor("bg-black")}; |
There was a problem hiding this comment.
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
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; | ||
}); | ||
} |
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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 👍🏻
There was a problem hiding this comment.
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
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; |
There was a problem hiding this comment.
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") || {}; |
There was a problem hiding this comment.
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
There was a problem hiding this comment.
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.
metabase/src/metabase/public_settings.clj
Lines 341 to 349 in 44cb385
(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: |
There was a problem hiding this comment.
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?
There was a problem hiding this comment.
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?
There was a problem hiding this comment.
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;
});
}
There was a problem hiding this comment.
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)
Also, this seems to make the admin settings look off. Can you confirm that too @heypoom ?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment.
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
There was a problem hiding this comment.
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 🙏🏻
There was a problem hiding this comment.
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).
There was a problem hiding this 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 🙏🏻
# 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
Thanks! Re-testing this locally now |
There was a problem hiding this 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); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit: typo
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", |
There was a problem hiding this comment.
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( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
export function getThemedColorsPallete( | |
export function getThemedColorsPalette( |
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.
Demo
Screen.Recording.2024-05-16.at.02.51.02.mov
Checklist