mirror of
https://github.com/hyperdxio/hyperdx
synced 2026-04-21 13:37:15 +00:00
fix: Fix HyperDX primary button styling and SSR hydration (#1706)
Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
parent
6241c38892
commit
42820f3925
4 changed files with 38 additions and 12 deletions
7
.changeset/fix-hyperdx-theme-ssr-buttons.md
Normal file
7
.changeset/fix-hyperdx-theme-ssr-buttons.md
Normal file
|
|
@ -0,0 +1,7 @@
|
|||
---
|
||||
'@hyperdx/app': patch
|
||||
---
|
||||
|
||||
fix: Apply theme CSS class during SSR to prevent button styling mismatch
|
||||
|
||||
Adds the theme class (e.g., `theme-hyperdx`) to the HTML element during server-side rendering in `_document.tsx`. This ensures CSS variables for button styling are correctly applied from the first render, preventing a hydration mismatch that caused primary buttons to display with Mantine's default styling instead of the custom theme styling when `NEXT_PUBLIC_THEME` was explicitly set.
|
||||
|
|
@ -2,6 +2,17 @@ import { Head, Html, Main, NextScript } from 'next/document';
|
|||
|
||||
import { ibmPlexMono, inter, roboto, robotoMono } from '@/fonts';
|
||||
|
||||
// Get theme class for SSR - must match ThemeProvider's resolution
|
||||
// This ensures CSS variables are applied during server-side rendering
|
||||
// to prevent hydration mismatch with button styling
|
||||
function getThemeClass(): string {
|
||||
const envTheme = process.env.NEXT_PUBLIC_THEME;
|
||||
// Default to hyperdx if not set or invalid
|
||||
const themeName =
|
||||
envTheme === 'hyperdx' || envTheme === 'clickstack' ? envTheme : 'hyperdx';
|
||||
return `theme-${themeName}`;
|
||||
}
|
||||
|
||||
export default function Document() {
|
||||
const fontClasses = [
|
||||
ibmPlexMono.variable,
|
||||
|
|
@ -10,8 +21,10 @@ export default function Document() {
|
|||
roboto.variable,
|
||||
].join(' ');
|
||||
|
||||
const themeClass = getThemeClass();
|
||||
|
||||
return (
|
||||
<Html lang="en" className={fontClasses}>
|
||||
<Html lang="en" className={`${fontClasses} ${themeClass}`}>
|
||||
<Head>
|
||||
{/* eslint-disable-next-line @next/next/no-sync-scripts */}
|
||||
<script src="/__ENV.js" />
|
||||
|
|
|
|||
|
|
@ -30,10 +30,10 @@
|
|||
--color-bg-danger: var(--mantine-color-red-4);
|
||||
--color-bg-warning: var(--mantine-color-orange-5);
|
||||
|
||||
/* Primary Button */
|
||||
--color-primary-button-bg: var(--palette-brand-300);
|
||||
--color-primary-button-bg-hover: var(--color-brand-200);
|
||||
--color-primary-button-text: var(--color-text-inverted);
|
||||
/* Primary Button - uses brand green colors */
|
||||
--color-primary-button-bg: var(--mantine-color-green-light);
|
||||
--color-primary-button-bg-hover: var(--mantine-color-green-light-hover);
|
||||
--color-primary-button-text: var(--mantine-color-green-light-color);
|
||||
|
||||
/* Borders & Dividers */
|
||||
--color-border: var(--mantine-color-dark-5);
|
||||
|
|
@ -136,6 +136,11 @@
|
|||
--color-bg-danger: var(--mantine-color-red-8);
|
||||
--color-bg-warning: var(--mantine-color-orange-8);
|
||||
|
||||
/* Primary Button - uses brand green colors */
|
||||
--color-primary-button-bg: var(--mantine-color-green-light);
|
||||
--color-primary-button-bg-hover: var(--mantine-color-green-light-hover);
|
||||
--color-primary-button-text: var(--mantine-color-green-light-color);
|
||||
|
||||
/* Borders & Dividers - inverted */
|
||||
--color-border: var(--mantine-color-gray-1);
|
||||
--color-border-muted: rgb(0 0 0 / 5%);
|
||||
|
|
|
|||
|
|
@ -243,11 +243,12 @@ export const makeTheme = ({
|
|||
baseVars['--button-fz'] = rem(12);
|
||||
}
|
||||
|
||||
// Use Mantine's built-in CSS vars for hover support
|
||||
// Use semantic CSS vars for primary button styling
|
||||
if (props.variant === 'primary') {
|
||||
baseVars['--button-bg'] = 'var(--mantine-color-green-light)';
|
||||
baseVars['--button-hover'] = 'var(--mantine-color-green-light-hover)';
|
||||
baseVars['--button-color'] = 'var(--mantine-color-green-light-color)';
|
||||
baseVars['--button-bg'] = 'var(--color-primary-button-bg)';
|
||||
baseVars['--button-hover'] = 'var(--color-primary-button-bg-hover)';
|
||||
baseVars['--button-color'] = 'var(--color-primary-button-text)';
|
||||
baseVars['--button-color-hover'] = 'var(--color-primary-button-text)';
|
||||
}
|
||||
|
||||
if (props.variant === 'secondary') {
|
||||
|
|
@ -305,9 +306,9 @@ export const makeTheme = ({
|
|||
}
|
||||
|
||||
if (props.variant === 'primary') {
|
||||
baseVars['--ai-bg'] = 'var(--mantine-color-green-light)';
|
||||
baseVars['--ai-hover'] = 'var(--mantine-color-green-light-hover)';
|
||||
baseVars['--ai-color'] = 'var(--mantine-color-green-light-color)';
|
||||
baseVars['--ai-bg'] = 'var(--color-primary-button-bg)';
|
||||
baseVars['--ai-hover'] = 'var(--color-primary-button-bg-hover)';
|
||||
baseVars['--ai-color'] = 'var(--color-primary-button-text)';
|
||||
}
|
||||
|
||||
if (props.variant === 'secondary') {
|
||||
|
|
|
|||
Loading…
Reference in a new issue