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

charts: color are theme dependent #88126

Merged
merged 18 commits into from
Mar 31, 2025
Merged

charts: color are theme dependent #88126

merged 18 commits into from
Mar 31, 2025

Conversation

JonasBa
Copy link
Member

@JonasBa JonasBa commented Mar 27, 2025

First pass of making colors theme dependent - we need this to be able to toggle between the correct themes for UI2. We should generally disallow direct theme imports as using them results in light/dark mode to be broken.

@github-actions github-actions bot added the Scope: Frontend Automatically applied to PRs that change frontend components label Mar 27, 2025
Copy link

codecov bot commented Mar 27, 2025

❌ 114 Tests Failed:

Tests completed Failed Passed Skipped
10044 114 9930 11
View the top 3 failed test(s) by shortest run time
getFieldRenderer ops breakdown renders operation breakdowns in sorted order when a sort field is provided
Stack Traces | 0.005s run time
ReferenceError: barColors is not defined
    at pickBarColor (.../performance/waterfall/utils.tsx:178:3)
    at .../utils/discover/fieldRenderers.tsx:874:56
    at Array.map (<anonymous>)
    at spanOperationRelativeBreakdownRenderer (.../utils/discover/fieldRenderers.tsx:844:46)
    at Object.<anonymous> (.../utils/discover/fieldRenderers.spec.tsx:401:40)
    at Promise.then.completed (.../jest-circus/build/utils.js:298:28)
    at new Promise (<anonymous>)
    at callAsyncCircusFn (.../jest-circus/build/utils.js:231:10)
    at _callCircusTest (.../jest-circus/build/run.js:316:40)
    at _runTest (.../jest-circus/build/run.js:252:3)
    at _runTestsForDescribeBlock (.../jest-circus/build/run.js:126:9)
    at _runTestsForDescribeBlock (.../jest-circus/build/run.js:121:9)
    at _runTestsForDescribeBlock (.../jest-circus/build/run.js:121:9)
    at run (.../jest-circus/build/run.js:71:3)
    at runAndTransformResultsToJestFormat (.../build/legacy-code-todo-rewrite/jestAdapterInit.js:122:21)
    at jestAdapter (.../build/legacy-code-todo-rewrite/jestAdapter.js:79:19)
    at runTestInternal (.../jest-runner/build/runTest.js:367:16)
    at runTest (.../jest-runner/build/runTest.js:444:34)
    at Object.worker (.../jest-runner/build/testWorker.js:106:12)
pickBarColor() returns a random color when no predefined option is available
Stack Traces | 0.005s run time
ReferenceError: barColors is not defined
    at pickBarColor (.../performance/waterfall/utils.tsx:178:3)
    at Object.<anonymous> (.../performance/waterfall/utils.spec.tsx:18:47)
    at Promise.then.completed (.../jest-circus/build/utils.js:298:28)
    at new Promise (<anonymous>)
    at callAsyncCircusFn (.../jest-circus/build/utils.js:231:10)
    at _callCircusTest (.../jest-circus/build/run.js:316:40)
    at processTicksAndRejections (node:internal/process/task_queues:105:5)
    at _runTest (.../jest-circus/build/run.js:252:3)
    at _runTestsForDescribeBlock (.../jest-circus/build/run.js:126:9)
    at _runTestsForDescribeBlock (.../jest-circus/build/run.js:121:9)
    at run (.../jest-circus/build/run.js:71:3)
    at runAndTransformResultsToJestFormat (.../build/legacy-code-todo-rewrite/jestAdapterInit.js:122:21)
    at jestAdapter (.../build/legacy-code-todo-rewrite/jestAdapter.js:79:19)
    at runTestInternal (.../jest-runner/build/runTest.js:367:16)
    at runTest (.../jest-runner/build/runTest.js:444:34)
    at Object.worker (.../jest-runner/build/testWorker.js:106:12)
pickBarColor() returns the predefined color when available
Stack Traces | 0.01s run time
ReferenceError: barColors is not defined
    at pickBarColor (.../performance/waterfall/utils.tsx:178:3)
    at Object.<anonymous> (.../performance/waterfall/utils.spec.tsx:10:36)
    at Promise.then.completed (.../jest-circus/build/utils.js:298:28)
    at new Promise (<anonymous>)
    at callAsyncCircusFn (.../jest-circus/build/utils.js:231:10)
    at _callCircusTest (.../jest-circus/build/run.js:316:40)
    at processTicksAndRejections (node:internal/process/task_queues:105:5)
    at _runTest (.../jest-circus/build/run.js:252:3)
    at _runTestsForDescribeBlock (.../jest-circus/build/run.js:126:9)
    at _runTestsForDescribeBlock (.../jest-circus/build/run.js:121:9)
    at run (.../jest-circus/build/run.js:71:3)
    at runAndTransformResultsToJestFormat (.../build/legacy-code-todo-rewrite/jestAdapterInit.js:122:21)
    at jestAdapter (.../build/legacy-code-todo-rewrite/jestAdapter.js:79:19)
    at runTestInternal (.../jest-runner/build/runTest.js:367:16)
    at runTest (.../jest-runner/build/runTest.js:444:34)
    at Object.worker (.../jest-runner/build/testWorker.js:106:12)

To view more test analytics, go to the Test Analytics Dashboard
📋 Got 3 mins? Take this short survey to help us improve Test Analytics.

@JonasBa JonasBa changed the title charts: color dependent charts: color are theme dependent Mar 27, 2025
@JonasBa JonasBa marked this pull request as ready for review March 27, 2025 22:01
@JonasBa JonasBa requested review from a team as code owners March 27, 2025 22:01
Copy link
Contributor

Choose a reason for hiding this comment

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

is the plan to remove those entirely? I guess you just couldn’t do it right now because there are still more usages?

Copy link
Member Author

Choose a reason for hiding this comment

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

yeah, we have a ton more. I'm going to make another pass, but I need to first figure out how this broke chartcuterie

@@ -274,8 +276,10 @@ class Chart extends Component<ChartProps, State> {
);
}
const chartColors = timeseriesData.length
? (colors?.slice(0, series.length) ??
getChartColorPalette(timeseriesData.length - 2 - (hasOther ? 1 : 0)).slice())
? ((colors as string[])?.slice(0, series.length) ??
Copy link
Contributor

Choose a reason for hiding this comment

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

I don’t understand this type assertion. It seems that we’ve widened the type of colors to also be potentially a function, but now, we are asserting here that it is a string. Couldn’t this fail at runtime if we pass a function as colors ?

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'm going to try and remove these before merging.

Comment on lines 395 to 399
colors?:
| string[]
| readonly string[]
| ReturnType<Theme['chart']['getColorPalette']>
| ((theme: Theme) => string[] | ReturnType<Theme['chart']['getColorPalette']>);
Copy link
Contributor

Choose a reason for hiding this comment

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

we should probably extract this to a type Colors

visualMap: options.options?.visualMap,
backgroundColor: theme.background,
};
}
type FunctionRegressionChartData = {
evidenceData: NormalizedTrendsTransaction;
rawResponse: any;
Copy link
Contributor

Choose a reason for hiding this comment

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

seems like if we make this unknown, everything still compiles. Feels like a better default than any:

Suggested change
rawResponse: any;
rawResponse: unknown;

@@ -48,7 +47,7 @@ export function PerformanceScoreChart({
: projectScore.totalScore
: undefined;

let ringSegmentColors = getChartColorPalette(3).slice() as string[];
let ringSegmentColors = theme.chart.getColorPalette(3) as unknown as string[];
Copy link
Contributor

Choose a reason for hiding this comment

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

Those type assertions indicate that the type we return from getColorPalette is too narrow. In fact, we seem to basically return CHART_PALETTE[index], which means we return a reference to the array inside CHART_PALETTE, which is why it is readonly.

So doing a type assertion to a string[] means it becomes mutable, at which point re-assignments are possible and would have a huge impact, because it would mutate the overall CHART_PALETTE. That feels like it can lead to hard to track bugs that will only occur in certain sencarios.

Now here we don’t actually push to ringSegmentColors (we reassign it), but I still think it’s dangerous territory.

So I think we should either:

  • not do a type assertion, and refactor this into an immutable way, e.g. like this:
const getRingSegmentColors = () => {
  const ringSegmentColors = theme.chart.getColorPalette(3);
  const ringBackgroundColors = ringSegmentColors.map(color => `${color}50`);

  if (webVital) {
    const index = ORDER.indexOf(webVital);

    return {
      ringSegmentColors: ringSegmentColors.map((color, i) => {
        return i === index ? color : theme.gray200;
      }),
      ringBackgroundColors: ringBackgroundColors.map((color, i) => {
        return i === index ? color : `${theme.gray200}33`;
      }),
    };
  }

  return {ringSegmentColors, ringBackgroundColors};
};
  • embrace that everybody works in mutable ways, and just have getColorPalette return a string[] by creating a copy of what it returns internally so that no one will accidentally mutate the global palette ?

Copy link
Member Author

Choose a reason for hiding this comment

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

Let me do a second pass on this, as this isn't the only place that does this :/

@JonasBa JonasBa merged commit dcd5fe4 into master Mar 31, 2025
40 checks passed
@JonasBa JonasBa deleted the jb/theme/chart-palette branch March 31, 2025 13:04
andrewshie-sentry pushed a commit that referenced this pull request Mar 31, 2025
First pass of making colors theme dependent - we need this to be able to
toggle between the correct themes for UI2. We should generally disallow
direct theme imports as using them results in light/dark mode to be
broken.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Scope: Frontend Automatically applied to PRs that change frontend components
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants