Skip to content

fix(app): refine Mantine theme (tabs, code bg, segmented control) - #2814

Merged
elizabetdev merged 6 commits into
mainfrom
elizabet/more-mantine-customization
Aug 5, 2026
Merged

fix(app): refine Mantine theme (tabs, code bg, segmented control)#2814
elizabetdev merged 6 commits into
mainfrom
elizabet/more-mantine-customization

Conversation

@elizabetdev

@elizabetdev elizabetdev commented Aug 5, 2026

Copy link
Copy Markdown
Contributor

Summary

Small Mantine theme refinements across the HyperDX and ClickStack themes:

  • Tabs: Mantine's default variant renders the list line as a ::before with a 1px border on all four sides of a zero-height box, so the top + bottom borders stack into a ~2px-looking line. Collapsed it to a true 1px bottom edge for horizontal tabs (vertical tabs keep their native side border). Also set non-active horizontal tab hover borders to 1px so they match the list line, while the active tab keeps its 2px indicator.
  • Code: Wired the Mantine Code component background to the shared --color-bg-code token in both themes. Fixed the ClickStack --color-bg-code values to reference defined tokens (--palette-slate-50 for light, --palette-neutral-725 for dark) — the previous light value referenced a non-existent --color-slate-50, which resolved to invalid.
  • SegmentedControl: Active indicator now has a 1px border, a small (2px) radius, and uses a dedicated --color-bg-option-active background token. Added that token to the Design Tokens storybook.
  • Buttons: Primary HyperDX buttons are now more prominent

Screenshots

Better segment controls
image

The tabs lines are now 1px

image

Buttons
image

image

Logo it is now the same in dark and light mode:

image

Test plan

  • Storybook → Design Tokens/Semantic Colors renders a color-bg-option-active swatch
  • Tabs show a single 1px gray underline; hovering a non-active tab shows a 1px border with no layout shift; active tab keeps its 2px indicator
  • Mantine Code blocks use the --color-bg-code background in both light/dark and both themes
  • SegmentedControl active option shows the bordered, slightly-rounded indicator in both themes

Made with Cursor

elizabetdev and others added 2 commits August 4, 2026 17:32
- Tabs: collapse default-variant list line to a true 1px bottom border and
  make non-active horizontal tab hover borders 1px (not 2px)
- Code: wire component background to the --color-bg-code token in both themes
- Fix clickstack --color-bg-code light value to a defined token
  (--palette-slate-50) and dark value to --palette-neutral-725
- SegmentedControl: add border + small radius and use --color-bg-option-active
  for the active indicator; add the token to the Design Tokens storybook

Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
@changeset-bot

changeset-bot Bot commented Aug 5, 2026

Copy link
Copy Markdown

🦋 Changeset detected

Latest commit: 9c97ed0

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

@vercel

vercel Bot commented Aug 5, 2026

Copy link
Copy Markdown

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

Project Deployment Actions Updated (UTC)
hyperdx-oss Ready Ready Preview Aug 5, 2026 3:25pm
hyperdx-storybook Ready Ready Preview Aug 5, 2026 3:25pm

Request Review

@github-actions github-actions Bot added the review/tier-2 Low risk — AI review + quick human skim label Aug 5, 2026
@github-actions

github-actions Bot commented Aug 5, 2026

Copy link
Copy Markdown
Contributor

🔵 Tier 2 — Low Risk

Small, isolated change with no API route or data model modifications.

Why this tier:

  • Standard feature/fix — introduces new logic or modifies core functionality

Review process: AI review + quick human skim (target: 5–15 min). Reviewer validates AI assessment and checks for domain-specific concerns.
SLA: Resolve within 4 business hours.

Stats
  • Production files changed: 7
  • Production lines changed: 95
  • Branch: elizabet/more-mantine-customization
  • Author: elizabetdev

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

@greptile-apps

greptile-apps Bot commented Aug 5, 2026

Copy link
Copy Markdown
Contributor

Greptile Summary

The PR refines Mantine styling and shared theme tokens across the HyperDX and ClickStack themes.

  • Adds Code backgrounds based on the shared semantic token.
  • Adjusts horizontal tab borders and active indicators.
  • Updates SegmentedControl styling and semantic-color documentation.
  • Increases primary-button prominence and makes the HyperDX logomark theme-independent.

Confidence Score: 4/5

The PR is not yet safe to merge because SegmentedControl still draws the requested border around the entire control instead of the selected option.

In both Mantine themes, the border remains declared on the root slot while the indicator slot has no border, so the previously reported visual defect remains at the current head.

Files Needing Attention: packages/app/src/theme/themes/clickstack/mantineTheme.ts and packages/app/src/theme/themes/hyperdx/mantineTheme.ts

Important Files Changed

Filename Overview
packages/app/src/theme/themes/clickstack/mantineTheme.ts Adds Code and Tabs theme overrides, but the SegmentedControl border remains on the component root rather than its active indicator.
packages/app/src/theme/themes/hyperdx/mantineTheme.ts Mirrors the component refinements and repeats the outstanding SegmentedControl border-slot error.
packages/app/src/theme/themes/components.module.scss Adds horizontal-tab border overrides intended to preserve a stable 1px layout edge and 2px active indication.
packages/app/src/theme/themes/clickstack/_tokens.scss Replaces Code background values with defined palette-token references.
packages/app/src/theme/themes/hyperdx/_tokens.scss Updates brand and primary-button colors for stronger visual prominence.
packages/app/src/theme/themes/hyperdx/Logomark.tsx Replaces theme-dependent SVG fills with fixed brand and foreground colors.

Reviews (5): Last reviewed commit: "Merge branch 'main' into elizabet/more-m..." | Re-trigger Greptile

background: 'var(--color-bg-field)',
background: 'var(--color-bg-body)',
border: '1px solid var(--color-border)',
},

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

P1 Border targets the wrong slot

When any SegmentedControl uses either theme, the new border is applied to the component root while the active indicator receives no border, causing an outer border around the entire control instead of the intended 1px boundary around the selected option. The HyperDX theme repeats the same assignment.

Fix in Claude Code Fix in Conductor Fix in Cursor Fix in Codex

@github-actions

github-actions Bot commented Aug 5, 2026

Copy link
Copy Markdown
Contributor

E2E Test Results

All tests passed • 270 passed • 1 skipped • 1038s

Status Count
✅ Passed 270
❌ Failed 0
⚠️ Flaky 0
⏭️ Skipped 1

Tests ran across 4 shards in parallel.

View full report →

@github-actions

github-actions Bot commented Aug 5, 2026

Copy link
Copy Markdown
Contributor

<!-- deep-review -->

Deep Review

✅ No critical issues found. This is a visual-only theme change with no data, auth, or crash surface. Five P2 items below are worth resolving before merge — the first two are the substantive ones.

🟡 P2 -- recommended

  • packages/app/src/theme/themes/components.module.scss:5 -- The new rule keys off data-orientation on an ancestor ([data-orientation='horizontal'] .tabsList::before), so it only applies if Mantine v9 tags the Tabs root and not just the list element, and it also matches a vertical Tabs nested anywhere under a horizontal-orientation ancestor, replacing that inner list's side border with a bottom border under !important.
    • Fix: Anchor the selector to the list element itself — .tabsList[data-orientation='horizontal']::before and .tabsList[data-orientation='horizontal'] > .tabsTab:not([data-active]) — so the rule cannot silently miss and cannot reach nested tabs of a different orientation.
    • correctness-reviewer, maintainability-reviewer
  • packages/app/src/theme/themes/clickstack/mantineTheme.ts:328 -- The active indicator's only visual cue is now background: var(--color-bg-option-active) with boxShadow: 'none' and no border on the indicator, which resolves to #f6f7fa on a #fff track in ClickStack light (~1.06:1) and #ebebef on #fff in HyperDX light (~1.19:1), far under the 3:1 non-text threshold.
    • Fix: Give the indicator its own 1px solid var(--color-border) edge or retain a subtle shadow, or point it at a token with real separation from --color-bg-body.
  • packages/app/src/theme/themes/hyperdx/_tokens.scss:263 -- Wiring --code-bg to --color-bg-code newly exposes the HyperDX light-mode value var(--mantine-color-dark-1) = #A6A7AB; the theme's dark palette array is scheme-independent, so every <Code> in light mode renders on a mid-grey block while every other light surface token is near-white and ClickStack's equivalent is #f6f7fa.
    • Fix: Repoint the light-mode --color-bg-code at a light-palette value such as var(--mantine-color-gray-1), and check --color-border-code and --color-bg-kbd in the same block for the same dark-palette carryover.
  • packages/app/src/theme/themes/clickstack/mantineTheme.ts:85 -- The components blocks of the two theme files are identical for all 18 shared overrides (~290 lines each), and this change had to hand-copy the Code block and the SegmentedControl edit into both; the two copies have already drifted, with the byte-identical Button.vars block carrying contradictory explanatory comments in each file.
    • Fix: Extract the shared overrides into one baseComponents object spread into each theme, leaving only fontFamily, primaryColor, primaryShade, colors, focusClassName, and ClickStack's Checkbox/Radio/Switch as per-theme deltas.
    • maintainability-reviewer, kieran-typescript-reviewer
  • packages/app/src/theme/themes/hyperdx/mantineTheme.ts:99 -- The Code and SegmentedControl overrides change rendered output across four theme × color-scheme combinations with no test added; vars/styles emit inline custom properties that are not stubbed by the identity-obj-proxy mapping in jest.config.js, so this is directly assertable in the existing jsdom setup, and the only theme test present (src/theme/__tests__/index.test.ts) covers registry shape only.
    • Fix: Add an RTL test asserting the rendered --code-bg and indicator background per theme, plus a static check that every --color-* referenced from mantineTheme.ts and components.module.scss is declared in both _tokens.scss files in both schemes, using the existing semanticColorsGrouped.ts list as the source of truth.
    • testing-reviewer, kieran-typescript-reviewer
🔵 P3 nitpicks (5)
  • packages/app/src/theme/themes/clickstack/_tokens.scss:134 -- The --color-bg-option-active doc comment still scopes the token to "an interactive row inside a floating surface (Select/Combobox options, Menu items, popover/dropdown lists)" in all four declaration blocks, but it now also drives the SegmentedControl indicator.
    • Fix: Broaden the comment to cover inline active-state fills, or introduce a distinct --color-bg-control-active token for the indicator.
  • packages/app/src/theme/themes/hyperdx/mantineTheme.ts:102 -- '--code-bg' is assumed to be the variable Mantine's Code reads, and the new SCSS comments assert specific Mantine internals ("1px border on all four sides of a zero-height box", "bottom border defaults to 2px"); @mantine/core is pinned at ^9.0.0 and node_modules was absent, so none of this could be verified and a rename would make both overrides silent no-ops.
    • Fix: Confirm the variable name and ::before geometry against the installed Mantine v9 stylesheet and record the verified version in the comment.
  • packages/app/src/theme/themes/components.module.scss:6 -- border-width: 0 0 1px !important forces the list edge to the bottom unconditionally, including for [data-inverted] horizontal tabs where Mantine draws the line along the top.
    • Fix: Exclude the inverted case with :not([data-inverted]), or set the corresponding border-top-width for it.
  • packages/app/src/theme/themes/components.module.scss:13 -- Setting non-active tabs to a 1px bottom border while the active tab keeps 2px makes the content box differ by 1px between states, so labels shift by ~1px when the active tab changes — the same class of shift the at-rest application was meant to remove.
    • Fix: Keep the border width uniform at 2px and vary only border-bottom-color between active and non-active tabs.
  • packages/app/src/theme/themes/hyperdx/mantineTheme.ts:102 -- var(--color-bg-code) has no fallback, so any render where the color-scheme attribute is absent (a Storybook story or unit render without MantineProvider) yields a transparent Code background rather than a sane default.
    • Fix: Write it as var(--color-bg-code, <literal>) with a concrete fallback value.

Reviewers (5): correctness, testing, maintainability, project-standards, kieran-typescript.

Testing gaps:

  • No visual-regression coverage for the Tabs underline change; it is unobservable in jsdom (SCSS modules map to identity-obj-proxy, no layout engine), so a Storybook story driven through the existing playwright.config.ts is the only path that would actually exercise it.
  • No story or test covers the Tabs variant/mode matrix (default/outline/pills × horizontal/vertical × inverted/placement), which is what would surface the selector-anchoring and inverted-edge issues above.
  • No nested-Tabs case (vertical Tabs inside a horizontal Tabs panel) exists to exercise the leakage path.
  • No contrast assertion for the SegmentedControl indicator against its track across the four theme × scheme combinations.

Coverage note: Bash was non-functional in this environment (bwrap sandbox failure), no Grep/Glob tool was available, and node_modules was not installed. The diff itself could not be retrieved — findings are based on directly reading the changed files at HEAD, so before/after attribution rests on the commit scope rather than a hunk-level diff, and no claim about Mantine v9's shipped CSS could be verified. project-standards returned zero findings: no theme-scoped standards file exists, stylelint.config.mjs has no !important or global-selector rule, and the root AGENTS.md changeset requirement is satisfied.

Primary buttons now use the solid brand green background (via --color-bg-brand)
instead of the subtle green-light tint, and the brand green is bumped a shade
for stronger presence. Also update the HyperDX logomark to fixed brand colors.

Co-authored-by: Cursor <cursoragent@cursor.com>
@github-actions

github-actions Bot commented Aug 5, 2026

Copy link
Copy Markdown
Contributor

Deep Review

No critical issues found. This is a presentational theme diff — no auth, data, or API surface is touched, and nothing here can crash a happy path.

🟡 P2 — recommended

  • packages/app/src/theme/themes/clickstack/mantineTheme.ts:328 — The active-segment indicator resolves to --color-bg-option-active (#f6f7fa in ClickStack light via --click-global-color-background-muted) painted on a --color-bg-body track (#fff), giving ~1.05:1 contrast, and boxShadow: 'none' removes Mantine's default indicator elevation while the new 1px border sits on root rather than indicator — so in light mode the selected segment is distinguishable only by label color. HyperDX light mode has the same shape at ~1.13:1 (#ebebef on #fff, hyperdx/mantineTheme.ts:341).
    • Fix: Give the indicator its own visible edge (a 1px solid var(--color-border) on the indicator key, or retain a subtle shadow) instead of relying on a near-white fill against a white track.
  • packages/app/src/theme/semanticColorsGrouped.ts:14 — This file is a hand-typed mirror of token names defined in two separate _tokens.scss files with nothing verifying the two agree in either direction, and this diff leans on it as the Storybook deliverable for color-bg-option-active; a wrong or removed name degrades to a blank swatch rather than failing the build.
    • Fix: Add a unit test asserting every entry in semanticColorsGrouped resolves to a custom property defined in both themes' light and dark blocks, and that every --color-* token defined in both files appears in the list.
    • testing, maintainability
🔵 P3 nitpicks (4)
  • packages/app/src/theme/semanticColorsGrouped.ts:7 — The entry color-bg-sidebar has no corresponding custom property; both theme files define --color-bg-sidenav, so this swatch renders transparent in the Design Tokens story (pre-existing, but it is live proof of the drift the finding above describes).
    • Fix: Rename the entry to color-bg-sidenav.
    • testing, maintainability
  • packages/app/src/theme/themes/hyperdx/mantineTheme.ts:99 — The Code and SegmentedControl blocks were added byte-for-byte identically to both theme files, which now stand at 422 and 438 lines against the 300-line ceiling in AGENTS.md:88, and nothing fails when an override lands in one theme but not the other; the two files' otherwise-identical Button vars blocks already carry divergent comments (hyperdx/mantineTheme.ts:294 vs clickstack/mantineTheme.ts:281), showing the duplication does drift unnoticed.
    • Fix: Extract the brand-invariant component overrides into a shared factory consumed by both themes, or add a test comparing the two components maps key-by-key.
  • packages/app/src/theme/themes/_base-tokens.scss:12 — The @use './clickstack/tokens' namespace is never @included, which reads as dead code, but the imported file's body is top-level .theme-clickstack[...] selectors that Sass emits purely by virtue of the @use, so deleting the line would silently drop the entire ClickStack token block unless another entry point also imports it.
    • Fix: Add a one-line comment stating the import is load-bearing for CSS emission rather than mixin access, so it is not "cleaned up" later.
  • packages/app/src/theme/themes/components.module.scss:22Tabs.extend applies tabsList/tabsTab unconditionally, so the border-bottom-width and inset 0 -1px 0 var(--tabs-color) rules also hit variant="outline" and variant="pills" tabs, where an inset bottom line is not part of the variant's design; usage of those variants could not be confirmed in this environment, so treat this as unverified rather than an observed break.
    • Fix: Scope the three rules to the default variant via a data-variant guard so non-default Tabs variants keep their native borders.

Reviewers (4): correctness-of-scope analysis by the orchestrator, testing, maintainability, project-standards, agent-native.

Testing gaps:

  • No automated assertion that a CSS custom property referenced by a Mantine override (--color-bg-code, --color-bg-option-active) is defined across all four theme × color-scheme combinations plus the unscoped SSR fallback; all four are correctly defined today, but an omission would degrade silently.
  • No parity check that the two mantineTheme.ts components maps expose the same keys.
  • The pixel-level Tabs behavior this diff tunes (single 1px list line, no 1px hover shift, 2px active indicator) is verified only by manual inspection; no snapshot or visual-regression coverage exists.

Coverage caveats: git, grep, and shell access were unavailable in this environment, so the diff was reconstructed by reading the theme files directly — findings are anchored to verified file contents and line numbers, but changed-vs-unchanged attribution is inferred rather than read from the diff. Three dispatched reviewers (correctness, kieran-typescript, learnings-researcher) had not returned before this report was finalized, so logic-level and TypeScript-level coverage is thinner than a normal run. Presence of a .changeset/ entry — required by AGENTS.md:205 for user-facing @hyperdx/app changes — could not be verified without directory listing.

@pulpdrew

pulpdrew commented Aug 5, 2026

Copy link
Copy Markdown
Contributor

Super minor, but is it intentional that the icons here shift up by a pixel when the tab is selected?

Screen.Recording.2026-08-05.at.10.55.44.AM.mov

@elizabetdev

Copy link
Copy Markdown
Contributor Author

@pulpdrew, it is not intentional. Let me fix it! 🙌🏽

…ab line

Keep the active tab's border-bottom-width at 1px (matching non-active tabs) and
render the 2px indicator via an inset shadow so selecting a tab no longer nudges
its icon/label up by 1px. Also point the non-active/gray tab line at
--color-border via --tab-border-color in both themes.

Co-authored-by: Cursor <cursoragent@cursor.com>

@pulpdrew pulpdrew left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

LGTM!

@elizabetdev
elizabetdev merged commit a42db64 into main Aug 5, 2026
28 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

review/tier-2 Low risk — AI review + quick human skim

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants