Skip to content

refactor(theme): unify and name chart colors across themes#2276

Open
elizabetdev wants to merge 7 commits into
mainfrom
agent/unify-chart-palette
Open

refactor(theme): unify and name chart colors across themes#2276
elizabetdev wants to merge 7 commits into
mainfrom
agent/unify-chart-palette

Conversation

@elizabetdev
Copy link
Copy Markdown
Contributor

@elizabetdev elizabetdev commented May 14, 2026

Summary

Unifies the categorical and semantic chart palettes across the HyperDX and ClickStack themes, then renames the categorical slots from numeric indices (--color-chart-1..-10) to named hues (--color-chart-blue, --color-chart-orange, …). Theme branding still differentiates UI chrome (Mantine accent, Click UI globals); shared chart categorical colors stay one palette.

Follow-up in this PR (latest commit):

  • --color-chart-info — Brand-specific log / chart “info” severity: HyperDX uses Mantine greens (green-6 dark, green-7 light) via tokens; ClickStack uses var(--color-chart-blue). Documented in _chart-tokens.scss; values set in each theme _tokens.scss after the shared chart-tokens include.
  • Theme switchingAppThemeProvider applies the active .theme-* class on <html> during render (not only in useEffect) so any same-pass getComputedStyle reads see the correct brand.
  • Search / time chartDBTimeChart passes optional logLevelColorFn into formatResponseForTimeChart. On HyperDX, info-like severities resolve from useMantineTheme().colors.green so hex matches Mantine immediately after ClickStack → HyperDX (avoids stale nested --mantine-color-green-* on the document before Mantine updates). ClickStack keeps using logLevelColor (CSS). getLogLevelColorOrder accepts the same resolver so legend sort matches.

Why (original PR)

Pre-PR, two coupled problems lived in the chart-color layer:

  • Per-theme palettes: HyperDX’s --color-chart-1 was brand green, ClickStack’s was Observable blue. This required a runtime detectActiveTheme() branch in the JS fallback path, an SSR/hydration mismatch caveat, and made HyperDX’s brand-green double as --color-chart-success (success pills and primary chart series shared a hue).
  • Index-only addressing: Identity callers (“this pill is always cyan”) were forced to look up an arbitrary slot number, and reordering categorical assignment required SCSS edits.

After the refactor:

  • One shared categorical + most semantic palette in _chart-tokens.scss, included by both themes.
  • Named CSS vars for identity (var(--color-chart-cyan)) decoupled from the JS-side CATEGORICAL_ORDER array that drives multi-series index assignment.
  • No runtime theme detection in the chart palette path.

Brand impact

  • Multi-series / categorical defaults: HyperDX charts no longer lead with brand green for slot 0; they lead with Observable blue (#437eef), matching ClickStack. Brand identity stays on Mantine accent, Click UI globals, sidebar, etc.
  • Log-level “info” series (search histogram, etc.): Intentionally not unified — HyperDX uses Mantine greens above; ClickStack uses chart blue, so toggling brand changes that series color by design.

Commits in this PR

  1. refactor(theme): unify chart palette across themes via shared partial — extracts _chart-tokens.scss; both themes @include chart-tokens.chart-tokens in dark and light blocks.
  2. refactor(utils): single chart palette aligned with shared SCSS partial — one CHART_PALETTE, removes detectActiveTheme(), simplifies semantic reads.
  3. docs+story: align with unified chart palette — docs and Chart Colors story.
  4. refactor(theme): name categorical chart colors instead of indexing — named hue vars + CATEGORICAL_ORDER in utils.ts.
  5. chore: add changeset for unified+named chart palette — changeset for @hyperdx/app.
  6. fix(theme): log chart info colors and reliable theme switching--color-chart-info per brand, sync theme class on <html>, logLevelColorFn + Mantine resolution in DBTimeChart, formatResponseForTimeChart / getLogLevelColorOrder plumbing, tests and story updates.

Test plan

  • yarn ci:unit src/__tests__/ChartUtils.test.ts
  • yarn ci:unit src/components/__tests__/DBTimeChart.test.tsx
  • SCSS compiles for _chart-tokens.scss, hyperdx/_tokens.scss, clickstack/_tokens.scss
  • Toggle dark ↔ light — categorical and semantic colors stay legible; heatmap gradient flips palettes
  • Toggle HyperDX ↔ ClickStack — categorical multi-series colors stay the same; log-level info color follows brand (green vs blue); no stale green after switch
  • Storybook Design Tokens / Chart Colors — semantic swatch includes --color-chart-info
  • Search page histogram after brand switch — info bars match expected HyperDX / ClickStack colors

elizabetdev and others added 4 commits May 13, 2026 18:22
Both themes now consume the same chart palette (categorical 1-10 +
semantic success/warning/error + their highlight variants) from a new
`packages/app/src/theme/themes/_chart-tokens.scss` partial. Previously
the values lived in four byte-similar-but-not-identical blocks across
`hyperdx/_tokens.scss` and `clickstack/_tokens.scss` (dark + light each).

Behavior change for HyperDX: the categorical palette now leads with
ClickStack-style blue (`#437eef`) instead of HyperDX brand green
(`#00c28a`), and semantic success becomes Observable green (`#3ca951`)
rather than brand green. Single-series HyperDX charts will render in
blue going forward; status pills using `getChartColorSuccess()` shift
to the more saturated Observable green. This continues the Click UI
convergence — chart-color identity stops being a brand differentiator
between the two themes.

Implementation:

- New `_chart-tokens.scss` defines three mixins:
  `categorical-chart-tokens`, `semantic-chart-tokens`, and the
  convenience `chart-tokens` that includes both. The same comment
  about CSS specificity that previously lived inline in
  `clickstack/_tokens.scss` moves there to explain why scheme blocks
  must redeclare these vars.
- `hyperdx/_tokens.scss` adds `@use '../chart-tokens';` and replaces
  both inline chart blocks (dark + light) with
  `@include chart-tokens.chart-tokens;`. Net loss of ~40 lines.
- `clickstack/_tokens.scss` does the same. Net loss of another ~40
  lines. The "duplication is required" comment is gone now that the
  duplication is centralized.
- `_base-tokens.scss` is unchanged. It already `@include`s
  `hyperdx-tokens.dark-mode-tokens` for SSR; that mixin transitively
  includes the chart tokens, so the SSR fallback layer keeps working.

JS palette consolidation in `utils.ts` (CHART_PALETTE +
CLICKSTACK_CHART_PALETTE -> single CHART_PALETTE, COLORS reorder,
detectActiveTheme cleanup) and storybook + doc updates land in
follow-up commits in this PR.

Verified each partial compiles via `npx sass`.

Co-authored-by: Cursor <cursoragent@cursor.com>
Collapses CHART_PALETTE and CLICKSTACK_CHART_PALETTE in
`packages/app/src/utils.ts` into a single CHART_PALETTE that mirrors
the new `_chart-tokens.scss` partial. Reorders the exported COLORS
array so COLORS[0] is blue (matches the new --color-chart-1) and
removes the brand-green-first ordering.

Knock-on simplifications now that there is only one palette:

- `getSemanticChartColor` no longer takes per-theme fallbacks.
  Signature: `(cssVarName, fallback) -> string`. It still reads the
  live CSS var first; the fallback only matters for SSR or when
  `getComputedStyle` throws.
- `detectActiveTheme()` is removed entirely. Its only consumer was
  `getSemanticChartColor`'s per-theme fallback branch.
- The SSR/hydration-mismatch caveats in the JSDoc are gone too.
  Both themes resolve every chart var to the same hex now, so
  fallback == live value.

Verified via `yarn ci:unit src/__tests__/ChartUtils.test.ts` — all 28
tests pass. Tests reference colors positionally as `COLORS[0]`,
`COLORS[1]` etc., so reordering is transparent to them.

Storybook label reorder and data-viz doc updates land next.

Co-authored-by: Cursor <cursoragent@cursor.com>
Updates the storybook label list and the data viz colors guide to match
the new shared palette. Both files previously described a per-theme split
(HyperDX brand-green-first vs ClickStack blue-first); after this PR's
prior commits the palettes are identical, so the docs were factually
wrong.

Storybook (`ChartColors.stories.tsx`):

- Reorders COLOR_LABELS so slot 1 is "Blue (Primary)", matching the new
  COLORS array and `--color-chart-1`. Old order had "Green (Brand)" at
  position 0, which would now render as a blue swatch labeled "Green".

Data viz doc (`agent_docs/data_viz_colors.md`):

- Replaces the per-theme "where the colors live" tables with a single
  shared palette table.
- Adds a "Why one palette across both themes" subsection explaining the
  two reasons we collapsed the per-theme split (brand-green doubling as
  --color-chart-success in HyperDX; runtime detectActiveTheme() branch
  required for the SSR fallback).
- Replaces the green-first / blue-first "Per-theme considerations"
  section with a short note that theme branding now lives in Mantine
  accent + Click UI globals + chrome, not in chart colors. The
  "yellow accent stays out of the categorical palette" rationale moves
  here intact.
- Simplifies the "Adding new entries" section: hex changes now land in
  two places (`_chart-tokens.scss` + `CHART_PALETTE` in `utils.ts`)
  instead of four.
- Updates the pre-merge checklist: "HyperDX <-> ClickStack toggle should
  *not* change chart colors anymore"; the only legitimate visual diff
  is theme chrome.
- Updates the file reference summary so the new `_chart-tokens.scss`
  partial appears as the primary entry, with the two `_tokens.scss`
  files listed as consumers.
- Refreshes JS line-number references to match the slimmer `utils.ts`.

Co-authored-by: Cursor <cursoragent@cursor.com>
Categorical chart slots are now addressed by hue name
(`--color-chart-blue`, `--color-chart-orange`, etc.) instead of by
index (`--color-chart-1`..`-10`). The numbered vars are removed.

Identity callers can now reference the var that means what they
actually want ("this pill is always cyan" -> `var(--color-chart-cyan)`)
without coupling to the categorical assignment order. Multi-series
charts still pick by index, but that ordering now lives in a single
JS array (`CATEGORICAL_ORDER` in `utils.ts`) rather than being baked
into the CSS var names. Reordering the default series colors no
longer requires SCSS edits.

- _chart-tokens.scss: rename categorical vars to named hues; semantic
  vars unchanged
- utils.ts: introduce CATEGORICAL_ORDER, derive COLORS from it, rewire
  getColorFromCSSVariable() to look up the named var via a
  camelCase->kebab-case slug
- ChartColors.stories.tsx: replace COLOR_LABELS + index math with a
  CATEGORICAL_SLOTS table that is name-by-position
- data_viz_colors.md: rewrite categorical sections to describe named
  slots + the JS-side ordering layer; update file-reference and
  add/reorder recipes
- hyperdx/_tokens.scss: drop the now-stale "1-indexed maps to 0-indexed
  COLORS" comment

Co-authored-by: Cursor <cursoragent@cursor.com>
@vercel
Copy link
Copy Markdown

vercel Bot commented May 14, 2026

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
hyperdx-oss Ready Ready Preview, Comment May 15, 2026 6:32pm

Request Review

@changeset-bot
Copy link
Copy Markdown

changeset-bot Bot commented May 14, 2026

🦋 Changeset detected

Latest commit: c96ad57

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 3 packages
Name Type
@hyperdx/app Patch
@hyperdx/api Patch
@hyperdx/otel-collector Patch

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

@github-actions github-actions Bot added the review/tier-3 Standard — full human review required label May 14, 2026
@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented May 14, 2026

🔴 Tier 4 — Critical

Touches auth, data models, config, tasks, OTel pipeline, ClickHouse, or CI/CD.

Why this tier:

  • Large diff: 508 production lines changed (threshold: 400)

Additional context: agent branch (agent/unify-chart-palette)

Review process: Deep review from a domain expert. Synchronous walkthrough may be required.
SLA: Schedule synchronous review within 2 business days.

Stats
  • Production files changed: 8
  • Production lines changed: 508 (+ 18 in test files, excluded from tier calculation)
  • Branch: agent/unify-chart-palette
  • Author: elizabetdev

To override this classification, remove the review/tier-4 label and apply a different review/tier-* label. Manual overrides are preserved on subsequent pushes.

@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented May 14, 2026

PR Review

Solid refactor — collapses the per-theme chart palettes into one shared _chart-tokens.scss partial, drops the detectActiveTheme() branch in utils.ts, and moves series ordering into CATEGORICAL_ORDER. The intentional brand-color change (HyperDX series no longer leads with brand green) is correctly called out in the changeset.

Must-fix

  • ⚠️ packages/app/src/theme/semanticColorsGrouped.ts:60-69 still lists color-chart-1color-chart-10, which no longer exist after this PR → Replace with the new named tokens (color-chart-blue, color-chart-orange, color-chart-red, color-chart-cyan, color-chart-green, color-chart-pink, color-chart-purple, color-chart-light-blue, color-chart-brown, color-chart-gray). Today SemanticColors.stories.tsx will render 10 transparent / var(--)-undefined swatches.

Nits (optional)

  • 💡 getChartColorSuccessHighlight / getChartColorErrorHighlight / getChartColorWarningHighlight still hand‑roll a 2‑arg call to getSemanticChartColor after the clickstackColor parameter was dropped — works fine, just worth confirming there are no lingering 3‑arg call sites elsewhere (grep clean in this branch).
  • 💡 agent_docs/data_viz_colors.md and the new _chart-tokens.scss say the palette is identical across both themes — consider updating SemanticColors.stories.tsx's "charts" section header (or just delete now that ChartColors.stories.tsx is the canonical view) to avoid two parallel docs going stale.

Otherwise looks clean: COLORS derivation from CATEGORICAL_ORDER is in lockstep with the SCSS, the SSR fallback now matches the live CSS-var values (no more theme-divergent hydration caveat), and tests that index into COLORS[i] continue to pass since the assertion is symbolic.

@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented May 14, 2026

E2E Test Results

All tests passed • 179 passed • 3 skipped • 1198s

Status Count
✅ Passed 179
❌ Failed 0
⚠️ Flaky 2
⏭️ Skipped 3

Tests ran across 4 shards in parallel.

View full report →

Co-authored-by: Cursor <cursoragent@cursor.com>
@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented May 14, 2026

Deep Review

✅ No critical issues found.

🟡 P2 -- recommended

  • packages/app/src/utils.ts:489 -- getChartColorInfo() SSR/fallback hex (#3ca951) no longer matches either theme's live CSS-resolved value (HyperDX var(--mantine-color-green-6) / ClickStack var(--color-chart-blue)), so the JS fallback path now disagrees with the painted color on both brands.
    • Fix: Align the fallback by computing it from the same source the SCSS uses (e.g. a per-brand build-time constant) or drop the SSR call path so server-rendered chart series cannot embed a color that disagrees with hydrate-time CSS.
    • correctness, maintainability
  • packages/app/src/theme/ThemeProvider.tsx:134-149 -- AppThemeProvider now mutates document.documentElement.classList inside the function body during render rather than in an effect, which violates React's render-purity rule and leaves DOM state out of sync with any render React abandons (concurrent interrupt, Suspense throw, error-boundary rethrow).
    • Fix: Move the class swap into useLayoutEffect (which still runs before children read the DOM in their own effects) or restructure so chart components do not need synchronous render-time getComputedStyle reads.
    • correctness, maintainability, adversarial, julik-frontend-races
  • packages/app/src/components/__tests__/DBTimeChart.test.tsx:39-50 -- The new resolveLogLevelColorForTimeChart workaround is wired up but has no behavioral test asserting that an info-level row resolves to the Mantine green hex on HyperDX dark/light or that it falls back to logLevelColor on ClickStack and when mantineTheme.colors.green is missing.
    • Fix: Add it() blocks that mock useAppTheme/useMantineColorScheme across the four branches (hyperdx+dark, hyperdx+light, clickstack, missing green palette) and assert formatResponseForTimeChart returns the expected color for an info row.
    • testing, julik-frontend-races
  • packages/app/src/utils.ts:354-374 -- The 10 categorical + 6 semantic hex values are duplicated between CHART_PALETTE and _chart-tokens.scss with only a comment linking them; nothing fails the build if one side drifts.
    • Fix: Add a unit test that parses _chart-tokens.scss and asserts each --color-chart-{name} value equals CHART_PALETTE[name], or generate the SCSS from the TS constant at build time.
    • maintainability, testing
  • packages/app/src/utils.ts:400-403 -- paletteKeyToCssSlug(name: keyof typeof CHART_PALETTE) accepts the three *Highlight keys, for which it produces var names (--color-chart-green-highlight, etc.) that do not exist in the SCSS partial; today the only caller iterates CATEGORICAL_ORDER, but the wide type lets a future misuse silently fall back to the SSR hex with no type error.
    • Fix: Narrow the parameter to (typeof CATEGORICAL_ORDER)[number] so non-categorical keys become a compile error.
    • kieran-typescript
  • packages/app/src/components/DBPieChart.tsx -- The brand/scheme-switch race the PR works around for DBTimeChart still exists for pie charts: getColorPropsgetLevelColorgetChartColorInfo() reads --color-chart-info (and hence --mantine-color-green-6/-7) at format time, and the surrounding useMemo is keyed only on data, so info-level slices keep stale colors until the next refetch.
    • Fix: Hoist resolveLogLevelColorForTimeChart into a shared useLogLevelColor() hook in utils.ts and consume it from both DBTimeChart and DBPieChart, then include colorScheme/themeName in the pie's color memo deps.
    • julik-frontend-races
  • agent_docs/data_viz_colors.md:114-184 -- The new --color-chart-info CSS variable and the public getChartColorInfo() reader (the one chart color that intentionally varies across brands) are not documented in the Semantic Colors table or the Reader Functions table, and the existing --color-chart-success description still claims info-level fills route through success.
    • Fix: Add --color-chart-info to both tables, drop the info-level claim from the success row, and call out that info is the lone brand-coupled chart token.
    • project-standards
  • packages/app/src/__tests__/ChartUtils.test.ts:308-335 -- The expectation color: getChartColorInfo() is tautological under jsdom: with no theme class on <html>, getComputedStyle returns empty, so both expected and actual resolve to the same CHART_PALETTE.green fallback, hiding a regression that routed info through getColorFromCSSVariable(0) or any other helper.
    • Fix: Assert against the literal expected hex (or stub getChartColorInfo to a sentinel value) so the test fails if the formatter stops calling the info-specific helper.
    • testing
🔵 P3 nitpicks (9)
  • packages/app/src/components/DBTimeChart.tsx:298-325 -- resolveLogLevelColorForTimeChart hardcodes the knowledge that --color-chart-info resolves to Mantine green[6]/green[7] inside a chart component, coupling it to a SCSS mapping defined far away in hyperdx/_tokens.scss.
    • Fix: Co-locate the bypass with getChartColorInfo() (e.g. as a useLogLevelColor() hook) so the green-6/green-7 mapping lives next to the var that depends on it.
    • maintainability
  • packages/app/src/theme/ChartColors.stories.tsx:16-27 -- CATEGORICAL_SLOTS redeclares the ordering, kebab-case slugs, and labels that CATEGORICAL_ORDER + paletteKeyToCssSlug already encode; reordering the JS array silently leaves the storybook labels stale.
    • Fix: Export CATEGORICAL_ORDER and the slug helper from utils.ts and derive the storybook table from them.
    • maintainability, adversarial
  • packages/app/src/utils.ts:542-546 -- getLogLevelColorOrder(colorForLevel = logLevelColor) has exactly one caller, and that caller always passes the resolved function, so the default is dead and merely advertises an opt-out that should not exist.
    • Fix: Make colorForLevel required.
    • maintainability
  • packages/app/src/ChartUtils.tsx:524,617 -- The logLevelColorFn parameter is threaded through three signatures purely to support one workaround in DBTimeChart, expanding the public surface for one private need.
    • Fix: Replace the parameter chain with a hook (e.g. useLogLevelColor()) consumed at the chart-component boundary, so the format helpers stay parameter-free.
    • maintainability
  • packages/app/src/components/DBTimeChart.tsx:313 -- effectiveScheme = colorScheme ?? 'dark' treats 'auto' (a value Mantine can return when forceColorScheme is not set) as dark, so any future code path that mounts MantineProvider without forceColorScheme would silently pick the wrong green shade.
    • Fix: Either explicitly assert colorScheme !== 'auto' here or read document.documentElement.dataset.mantineColorScheme as the source of truth.
    • correctness
  • packages/app/src/theme/ChartColors.stories.tsx:38-59 -- SEMANTIC_CHART_COLORS calls getChartColorInfo() at module-evaluation time, before any theme class is applied to <html> in Storybook, so the Info swatch is permanently frozen at the SSR fallback regardless of brand selection.
    • Fix: Move the hex resolution inside the story render function so it re-evaluates per render.
    • adversarial
  • agent_docs/data_viz_colors.md:406-407 -- The pre-merge checklist states "chart colors stay the same" when toggling brands, which directly contradicts the brand-coupled --color-chart-info introduced by this PR.
    • Fix: Refine the bullet to distinguish categorical/semantic colors that stay constant from --color-chart-info which is intentionally brand-coupled.
    • project-standards
  • packages/app/src/utils.ts:489 -- The new --color-chart-info token deviates from the "Adding a new semantic color" recipe in data_viz_colors.md (no entry in CHART_PALETTE, defined in per-theme _tokens.scss rather than _chart-tokens.scss) without the recipe being updated to describe a brand-varying-semantic exception.
    • Fix: Update the recipe to document the per-brand-semantic path or add an info entry to CHART_PALETTE so the SSR fallback is named and discoverable.
    • project-standards
  • packages/app/src/theme/themes/_chart-tokens.scss:22-30 -- The CSS-specificity caveat (categorical vars must live inside [data-mantine-color-scheme] selectors) is documented only on categorical-chart-tokens, even though the same rule applies to semantic-chart-tokens and to the wrapper mixin.
    • Fix: Hoist the specificity note to the file-level docblock so it governs both mixins.
    • maintainability

Reviewers (8): correctness, testing, maintainability, project-standards, adversarial, kieran-typescript, julik-frontend-races, agent-native.

Testing gaps:

  • No test verifies the runtime equality COLORS[i] === getComputedStyle(--color-chart-{kebab(CATEGORICAL_ORDER[i])}) — the alignment invariant is type-checked but not behaviorally locked in.
  • No test exercises a brand or scheme switch while a chart is mounted, so the very race resolveLogLevelColorForTimeChart exists to fix is not regression-protected.
  • No test asserts that AppThemeProvider applies the theme class synchronously (the render-vs-effect distinction the refactor introduces).
  • No test covers paletteKeyToCssSlug for camelCase keys (lightBluelight-blue) — a load-bearing string transform.

@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented May 14, 2026

PR Review

  • ⚠️ Render-time DOM mutation in ThemeProvider.tsx:138-149document.documentElement.classList.add/remove now runs during render instead of in useEffect. The comment explains the constraint (children read CSS vars in the same commit), and the loop is idempotent so it converges, but synchronous DOM writes during render are a React anti-pattern that can misbehave with discarded renders in StrictMode/concurrent mode. Consider whether useLayoutEffect plus moving the getComputedStyle reads in children to also be effect-driven would be a cleaner fix; if not, leave a stronger inline note that this is load-bearing for the chart pipeline.

  • ⚠️ Brand-specific workaround leaks into DBTimeChart.tsx:298-318resolveLogLevelColorForTimeChart hardcodes themeName !== 'hyperdx' and reads mantineTheme.colors.green.[6/7] directly. This rebuilds part of logLevelColor's decision tree and will silently break if a future brand also needs a Mantine-var-backed --color-chart-info. Consider moving the "resolve a semantic chart var that points to a Mantine var" concern into utils.ts (e.g. an optional Mantine-theme-aware resolver) rather than per-component branching.

  • ℹ️ Patch-level changeset for a user-visible color change → Charts that previously led with brand green (#00c28a) now lead with Observable blue (#437eef). This is called out in the PR description as intentional, but a patch bump understates the visual change for HyperDX users. Confirm with the team whether minor is more appropriate.

  • ✅ Test coverage updated (ChartUtils.test.ts switched to getChartColorInfo(); DBTimeChart.test.tsx mocks useAppTheme). SCSS partial is correctly @used and the named-by-position table in ChartColors.stories.tsx matches CATEGORICAL_ORDER. paletteKeyToCssSlug correctly produces light-blue from lightBlue.

No critical bugs or security issues found.

Introduce brand-scoped --color-chart-info (HyperDX Mantine greens,
ClickStack chart blue), apply the active theme class on <html> during
AppThemeProvider render so DOM reads align with React state, and pass
a HyperDX-specific logLevelColorFn from DBTimeChart (useMantineTheme)
into formatResponseForTimeChart so info series hex matches Mantine
immediately after a brand switch.

Co-authored-by: Cursor <cursoragent@cursor.com>
@github-actions github-actions Bot added review/tier-4 Critical — deep review + domain expert sign-off and removed review/tier-3 Standard — full human review required labels May 15, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

review/tier-4 Critical — deep review + domain expert sign-off

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant