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 BackgroundContext for gray background component theme changes #2364

Merged
merged 24 commits into from
Oct 1, 2024

Conversation

benlister-okta
Copy link
Contributor

@benlister-okta benlister-okta commented Sep 20, 2024

DES-6423

Summary

  • Adds BackgroundContext react context which can be used to display optimized contrast versions of certain components/component states
  • Background color detection is handled by BackgroundProvider automatically but can be overridden by adding contrastMode highContrast | lowContrast
  • Background context behavior is baked into OdysseyProvider, but is in its own file so it could be used outside of OdysseyProvider
  • Currently configured for isDisabled secondary Button, Status, and Tag
  • Uses Type augmentation to add the BackgroundProvider logic globally, requiring no component level changes for non-styled components.

Example usage:

<BackgroundProvider contrastMode="lowContrast"> <Button isDisabled label="Secondary" onClick={() => {}} variant="secondary" /> </BackgroundProvider>

<BackgroundProvider> <Button isDisabled label="Secondary" onClick={() => {}} variant="secondary" /> </BackgroundProvider>

Testing & Screenshots

  • I have confirmed this change with my designer and the Odyssey Design Team.
    CleanShot 2024-09-18 at 10 05 46@2x

@@ -175,18 +175,6 @@ export const StatusWrapper: StoryObj<TooltipProps> = {
},
};

export const Disabled: StoryObj<TooltipProps> = {
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Removing this since the story doesn't function (tooltip on the disabled button) and it would require additional documentation for the background provider work.

Copy link
Contributor

Choose a reason for hiding this comment

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

Thanks. I removed this in my branch as well haha

@@ -253,6 +253,8 @@ export const components = ({
justifyContent: "center",
alignItems: "center",
borderRadius: 0,
borderWidth: 0,
borderBottomWidth: "1px",
Copy link
Contributor Author

@benlister-okta benlister-okta Sep 20, 2024

Choose a reason for hiding this comment

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

Added this banner style change since its related to the contrast work and visual alignment with Figma (as of last week).

Copy link
Contributor

Choose a reason for hiding this comment

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

@benlister-okta The banner only has a border on the bottom?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

That's correct. Alex and I discussed and went this direction since in the new template the guidance is (or will be) to use banner at the top of the browser. And for existing instances, we are ok with the look since it adds subtle contrast but still fits the system.

Copy link
Contributor

Choose a reason for hiding this comment

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

Is rendering this banner at the top of the browser/above the top nav even possible?

Copy link
Contributor

Choose a reason for hiding this comment

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

What I mean is, I thought the nav components will be injected into their apps. They may not have the ability to render anything at a higher level than the top nav

Copy link
Contributor Author

Choose a reason for hiding this comment

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

That makes sense, I am not sure how it will be implemented globally, it may need to be done at a feature level to support that. However, we tested it with the bottom-only border in the app and were fine with the look so it can be something we work towards in the future.

Copy link
Contributor

Choose a reason for hiding this comment

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

We may need to run this up the chain to determine if it is a breaking visual change or not. I know it's pretty minor but not sure how strict we need to be with stuff like this

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I think it definitely warrants a message along with the release at very least. The border version was added 2 releases ago so its still a "new" change but we should make sure were letting people know.

Comment on lines 75 to 72
}: OdysseyProviderProps<SupportedLanguages>) => {
const { isLowContrast } = useBackground();

const odysseyTokens = useMemo(
() => ({ ...Tokens, ...designTokensOverride }),
[designTokensOverride],
);

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 OdysseyProvider consume BackgroundProvider, it should be baked in.

Also, we need a hook to calculate the background color of the parent element of OdysseyProvider. It needs to output a div for that to work.

We'd get the ref of the div and check against the DOM to compute the background-color of it.

Once we have that, the rest can be changed by having Surface and other "high contrast" components consume the BackgroundProvider and change the value.

@benlister-okta benlister-okta changed the title [DRAFT - OdysseyProvider] Add BackgroundContext for gray background component theme changes Add BackgroundContext for gray background component theme changes Sep 25, 2024
@benlister-okta benlister-okta marked this pull request as ready for review September 25, 2024 18:00
@benlister-okta benlister-okta requested a review from a team as a code owner September 25, 2024 18:00
contrastMode?: ContrastMode;
};

export const BackgroundProvider = ({
Copy link
Contributor

Choose a reason for hiding this comment

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

@benlister-okta Can we name this something more descriptive. Maybe BackgroundContrastModeProvider? Or just ContrastModeProvider?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Call call, updated it to ContrastModeProvider

() =>
createTheme({
...existingTheme,
custom: {
Copy link
Contributor

Choose a reason for hiding this comment

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

Do we want to name this key something more descriptive than just custom?

Copy link
Contributor

Choose a reason for hiding this comment

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

We probably don't even need this top level object TBH. Any thoughts on just moving the contrast mode value to this level?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I improved this and moved the contrast mode into the augmentation but I don't believe we can get rid of this entirely since it's used to pass the variables into the theme in OdysseyProvider so it can be used globally.

...existingTheme,
custom: {
...existingTheme.custom,
isLowContrast: contrastMode === "lowContrast",
Copy link
Contributor

Choose a reason for hiding this comment

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

I thought we were just going to return contrastMode here and it would be a string of type "highContrast" | "lowContrast"?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I was using this at one point but am now just exporting odysseyContrastMode

@@ -0,0 +1,142 @@
/*!
Copy link
Contributor

Choose a reason for hiding this comment

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

In keeping with best practices, this file should be named <something>Provider.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

updated it to ContrastModeProvider.

issue likely from adding ContrastContext and needing a delay for some tests.
const OdysseyProvider = <SupportedLanguages extends string>(
props: OdysseyProviderProps<SupportedLanguages>,
) => (
<ContrastModeProvider>
Copy link
Contributor

Choose a reason for hiding this comment

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

@benlister-okta You can't currently set an explicit contrast mode. Looking at the code it seems like something you were trying to support

Copy link
Contributor Author

Choose a reason for hiding this comment

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

You can by passing contrastMode="lowContrast" (or highContrast) to the provider. The logic for it is in the ContrastProvider file: https://github.com/okta/odyssey/pull/2364/files#diff-69196edb1faa4f2d8100e2344e3ebd81a965621255c029d9380c8a5f976d2901

in this block useLayoutEffect(() => { if (explicitContrastMode) { setContrastMode(explicitContrastMode); } else { const isLowContrast = parentBackgroundColor === Tokens.HueNeutral50; setContrastMode(isLowContrast ? "lowContrast" : "highContrast"); } }, [parentBackgroundColor, explicitContrastMode]);

Copy link
Contributor

@bryancunningham-okta bryancunningham-okta Sep 30, 2024

Choose a reason for hiding this comment

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

Right, but you are not passing that prop through here. I'd expect OdysseyProvider to take contrastMode prop and that be passed through to ContrastModeProvider here

Copy link
Contributor Author

Choose a reason for hiding this comment

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

ahh, I see what you mean now, I added it in there now too. I was testing in storybook by importing directly so I didn't notice.

@@ -59,6 +59,7 @@ export { useOdysseyDesignTokens } from "./OdysseyDesignTokensContext";
export * from "./Accordion";
export * from "./Autocomplete";
export { badgeContentMaxValues } from "./Badge";
export * from "./ContrastModeProvider";
Copy link
Contributor

Choose a reason for hiding this comment

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

Nit: Alphabetize :)

Copy link
Contributor

@bryancunningham-okta bryancunningham-okta 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. Couple comments but nothing major

@bryancunningham-okta
Copy link
Contributor

Does this effectively make the OdysseyThemeProvider useless?

{children}
</OdysseyTranslationProvider>
</ScopedCssBaseline>
</OdysseyThemeProvider>
Copy link
Contributor

Choose a reason for hiding this comment

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

@benlister-okta I'm not sure we can remove the OdysseyThemeProvider here to be honest

Copy link
Contributor

Choose a reason for hiding this comment

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

I guess you are passing the tokens along to OdysseyDesignTokensContext here, so, maybe we can

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yes we should still retain the functionality since the theme-related props (designTokensOverride, shadowRootElement, themeOverride) are now passed directly to OdysseyThemeProvider to simplify things.

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 not sure what you mean by this.^ We are not using OdysseyThemeProvider at all 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.

I meant it was implementing the same functionality. I see what you mean though, it no longer uses OdysseyThemeProvider at all so it would be weird and confusing to have the functionality duplicated.

I just updated to revert back to using OdysseyThemeProvider and extend it with the contrast stuff

};

const OdysseyProvider = <SupportedLanguages extends string>(
props: OdysseyProviderProps<SupportedLanguages>,
Copy link
Contributor

Choose a reason for hiding this comment

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

Little nit-picky but Id probably do this.

Suggested change
props: OdysseyProviderProps<SupportedLanguages>,
{ contrastMode, ...providerProps }: OdysseyProviderProps<SupportedLanguages>,

Copy link
Contributor Author

Choose a reason for hiding this comment

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

thanks, updated with this.

designTokensOverride={designTokensOverride}
shadowDomElement={shadowDomElement}
shadowRootElement={shadowRootElement}
themeOverride={{
Copy link
Contributor

Choose a reason for hiding this comment

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

We'll probably want to memoize this object we're passing to the themeOverride

Copy link
Contributor Author

Choose a reason for hiding this comment

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

good call, I added it in here now.

@@ -60,6 +60,25 @@ const OdysseyProviderInner = <SupportedLanguages extends string>({
}: OdysseyProviderProps<SupportedLanguages>) => {
const { contrastMode } = useContrastContext();

const memoizedThemeProps = useMemo(
Copy link
Contributor

@bryancunningham-okta bryancunningham-okta Sep 30, 2024

Choose a reason for hiding this comment

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

Sorry, i just meant the override styles themselves. Something like this:

const memoizedThemeProps = useMemo(
    () => ({
        ...themeOverride,
        odysseyContrastMode: contrastMode,
    }),
    [
      themeOverride,
      contrastMode,
    ],
  );

Copy link
Contributor

Choose a reason for hiding this comment

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

But, your solution is probably fine too

Copy link
Contributor Author

Choose a reason for hiding this comment

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

got it! I like your suggestion, its easier to read, IMO

@oktapp-aperture-okta oktapp-aperture-okta bot merged commit 09ba964 into main Oct 1, 2024
3 checks passed
@oktapp-aperture-okta oktapp-aperture-okta bot deleted the bl_gray_bg_components-theme branch October 1, 2024 16:10
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants