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

[EuiCode/Block] Avoid recomputing code syntax colors #7486

4 changes: 4 additions & 0 deletions changelogs/upcoming/7486.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
**Bug fixes**

- Fix issue where code syntax styles would get recomputed, when the style determinant hasn't changed

105 changes: 72 additions & 33 deletions src/components/code/code_syntax.styles.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,44 +14,83 @@ import {

const visColors = euiPaletteColorBlind();

export const euiCodeSyntaxColors = (euiThemeContext: UseEuiTheme) => {
const { euiTheme } = euiThemeContext;
type IEuiCodeSyntaxColorTokens =
| 'backgroundColor'
| 'color'
| 'inlineCodeColor'
| 'selectedBackgroundColor'
| 'commentColor'
| 'selectorTagColor'
| 'stringColor'
| 'tagColor'
| 'nameColor'
| 'numberColor'
| 'keywordColor'
| 'functionTitleColor'
| 'typeColor'
| 'attributeColor'
| 'symbolColor'
| 'paramsColor'
| 'metaColor'
| 'titleColor'
| 'sectionColor'
| 'additionColor'
| 'deletionColor'
| 'selectorClassColor'
| 'selectorIdColor';

const generateEuiCodeSyntaxColors = () => {
const cache: Record<string, Record<IEuiCodeSyntaxColorTokens, string>> = {};

return (euiThemeContext: UseEuiTheme) => {
const { euiTheme } = euiThemeContext;

const backgroundColor = euiTheme.colors.lightestShade;

const backgroundColor = euiTheme.colors.lightestShade;
if (cache[backgroundColor]) {
return cache[backgroundColor];
}
Copy link
Contributor

Choose a reason for hiding this comment

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

Unfortunately consumers (not Kibana specifically, but in general) can customize more than just the backgroundColor. They could, for example, also override any or all of the text colors used below, which then would not correctly update per-theme or per-override. So we need to cache/memoize the variables per theme rather than just per background color.

@eokoneyo I spiked out a local attempt at converting this util to a hook with useMemo(): main...cee-chen:eui:code/emotion-perf

Is there any chance you could give it a shot in Kibana and see if it also reduces renders/improves performance similar to what's in your current PR?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Unfortunately consumers (not Kibana specifically, but in general) can customize more than just the backgroundColor. They could, for example, also override any or all of the text colors used below, which then would not correctly update per-theme or per-override. So we need to cache/memoize the variables per theme rather than just per background color.

Thanks for providing this additional context, totally makes sense to me. I'll test out your referenced spike.

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 @cee-chen, I finally got around to trying out the referenced spike, it does offer significant improvement to what the current state is and we get to keep the implementation native to react. see screenshot below;

Screenshot 2024-01-30 at 16 03 50

Copy link
Contributor

Choose a reason for hiding this comment

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

Woohoo, that's super exciting!! Thank you so much for checking @eokoneyo! How would you like to proceed with this work? If you want, we can cherry-pick my branch into this branch/PR and I can approve and merge. Or alternatively, I can open a new PR.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

@cee-chen given we are opting for the react implementation, I'm not sure I see any value in cherry-picking the work you've done into this PR especially that we can use it as is, I'd be happy to review once we have it up!!

Copy link
Contributor

@cee-chen cee-chen Jan 31, 2024

Choose a reason for hiding this comment

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

Haha, I mostly want you to get credit for the commit! It was your impetus/idea after all :) I might take over this PR just to get it merged in if that's cool.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Totally fine by me, I do appreciate the consideration too. Thanks Cee!


const result = {
backgroundColor: backgroundColor,
color: makeHighContrastColor(euiTheme.colors.text)(backgroundColor),
inlineCodeColor: makeHighContrastColor(visColors[3])(backgroundColor),
selectedBackgroundColor: 'inherit',
commentColor: makeHighContrastColor(euiTheme.colors.subduedText)(
backgroundColor
),
selectorTagColor: 'inherit',
stringColor: makeHighContrastColor(visColors[2])(backgroundColor),
tagColor: makeHighContrastColor(visColors[1])(backgroundColor),
nameColor: makeHighContrastColor(visColors[1])(backgroundColor),
numberColor: makeHighContrastColor(visColors[0])(backgroundColor),
keywordColor: makeHighContrastColor(visColors[3])(backgroundColor),
functionTitleColor: 'inherit',
typeColor: makeHighContrastColor(visColors[1])(backgroundColor),
attributeColor: 'inherit',
symbolColor: makeHighContrastColor(visColors[9])(backgroundColor),
paramsColor: 'inherit',
metaColor: makeHighContrastColor(euiTheme.colors.subduedText)(
backgroundColor
),
titleColor: makeHighContrastColor(visColors[7])(backgroundColor),
sectionColor: makeHighContrastColor(visColors[9])(backgroundColor),
additionColor: makeHighContrastColor(visColors[0])(backgroundColor),
deletionColor: makeHighContrastColor(euiTheme.colors.danger)(
backgroundColor
),
selectorClassColor: 'inherit',
selectorIdColor: 'inherit',
};

return {
backgroundColor: backgroundColor,
color: makeHighContrastColor(euiTheme.colors.text)(backgroundColor),
inlineCodeColor: makeHighContrastColor(visColors[3])(backgroundColor),
selectedBackgroundColor: 'inherit',
commentColor: makeHighContrastColor(euiTheme.colors.subduedText)(
backgroundColor
),
selectorTagColor: 'inherit',
stringColor: makeHighContrastColor(visColors[2])(backgroundColor),
tagColor: makeHighContrastColor(visColors[1])(backgroundColor),
nameColor: makeHighContrastColor(visColors[1])(backgroundColor),
numberColor: makeHighContrastColor(visColors[0])(backgroundColor),
keywordColor: makeHighContrastColor(visColors[3])(backgroundColor),
functionTitleColor: 'inherit',
typeColor: makeHighContrastColor(visColors[1])(backgroundColor),
attributeColor: 'inherit',
symbolColor: makeHighContrastColor(visColors[9])(backgroundColor),
paramsColor: 'inherit',
metaColor: makeHighContrastColor(euiTheme.colors.subduedText)(
backgroundColor
),
titleColor: makeHighContrastColor(visColors[7])(backgroundColor),
sectionColor: makeHighContrastColor(visColors[9])(backgroundColor),
additionColor: makeHighContrastColor(visColors[0])(backgroundColor),
deletionColor: makeHighContrastColor(euiTheme.colors.danger)(
backgroundColor
),
selectorClassColor: 'inherit',
selectorIdColor: 'inherit',
cache[backgroundColor] = result;

return result;
};
};

export const euiCodeSyntaxColors = generateEuiCodeSyntaxColors();

export const euiCodeSyntaxTokens = (euiThemeContext: UseEuiTheme) => {
const { euiTheme } = euiThemeContext;
const euiCodeBlock = euiCodeSyntaxColors(euiThemeContext);
Expand Down
Loading