Fix minor UI issues (#1382)

This commit is contained in:
Elizabet Oliveira 2025-11-20 15:00:42 +00:00 committed by GitHub
parent 59422a1aba
commit 562dd7ea28
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
24 changed files with 617 additions and 307 deletions

View file

@ -0,0 +1,5 @@
---
'@hyperdx/app': patch
---
Fix minor UI issues and enhance styling across various components

View file

@ -16,16 +16,40 @@ import '../styles/app.scss';
import { meHandler } from '../src/mocks/handlers';
import { ThemeWrapper } from '../src/ThemeWrapper';
export const parameters = {
layout: 'fullscreen',
options: {
showPanel: false,
storySort: (a, b) =>
a.title.localeCompare(b.title, undefined, { numeric: true }),
},
};
export const globalTypes = {
theme: {
name: 'Theme',
description: 'Mantine color scheme',
defaultValue: 'light',
toolbar: {
icon: 'mirror',
items: [
{ value: 'light', title: 'Light' },
{ value: 'dark', title: 'Dark' },
],
},
},
};
initialize();
const queryClient = new QueryClient();
const preview: Preview = {
decorators: [
Story => (
(Story, context) => (
<QueryClientProvider client={queryClient}>
<QueryParamProvider adapter={NextAdapter}>
<ThemeWrapper>
<ThemeWrapper colorScheme={context.globals.theme || 'light'}>
<Story />
</ThemeWrapper>
</QueryParamProvider>
@ -37,6 +61,7 @@ const preview: Preview = {
msw: {
handlers: [meHandler],
},
backgrounds: { disable: true },
},
};

View file

@ -111,6 +111,7 @@
"@storybook/addon-interactions": "^8.1.5",
"@storybook/addon-links": "^8.1.5",
"@storybook/addon-styling-webpack": "^1.0.0",
"@storybook/addon-themes": "^10.0.8",
"@storybook/blocks": "^8.1.5",
"@storybook/nextjs": "^8.1.5",
"@storybook/react": "^8.1.5",

View file

@ -293,7 +293,7 @@ export const AppNavLink = ({
const testId = `nav-link-${href.replace(/^\//, '').replace(/\//g, '-') || 'home'}`;
return (
<Group justify="space-between" px="md" py="6px">
<Group justify="space-between" px="md" py="6px" h="34px">
<Link
data-testid={testId}
href={href}

View file

@ -409,6 +409,7 @@ export default function AppNav({ fixed = false }: { fixed?: boolean }) {
const isCollapsed = isSmallScreen || isPreferCollapsed;
const navWidth = isCollapsed ? 50 : 230;
const navHeaderStyle = isCollapsed ? undefined : { height: 58 };
useEffect(() => {
HyperDX.addAction('user navigated', {
@ -604,7 +605,10 @@ export default function AppNav({ fixed = false }: { fixed?: boolean }) {
}}
>
<div style={{ width: navWidth }}>
<div className="p-3 d-flex flex-wrap justify-content-between align-items-center">
<div
className="p-3 d-flex flex-wrap justify-content-between align-items-center"
style={navHeaderStyle}
>
<Link href="/search" className="text-decoration-none">
{isCollapsed ? (
<div style={{ marginLeft: '-0.15rem' }}>

View file

@ -30,7 +30,7 @@ export default function LandingHeader({
right: 0,
background: 'var(--color-bg-body)',
backdropFilter: 'blur(12px)',
border: '1px solid var(--color-border)',
borderBottom: '1px solid var(--color-border)',
zIndex: 100,
}}
>
@ -47,12 +47,13 @@ export default function LandingHeader({
color="white"
/>
<Group gap="md" visibleFrom="lg" style={{ fontSize: 14 }}>
<Group gap="lg" visibleFrom="lg">
<Anchor
href="https://hyperdx.io"
c={activeKey === 'cloud' ? 'green' : 'gray'}
underline="never"
style={{ fontWeight: activeKey === 'cloud' ? 600 : 400 }}
size="sm"
>
HyperDX Cloud
</Anchor>
@ -61,6 +62,7 @@ export default function LandingHeader({
c={activeKey === 'docs' ? 'green' : 'gray'}
underline="never"
style={{ fontWeight: activeKey === 'docs' ? 600 : 400 }}
size="sm"
>
Docs
</Anchor>
@ -70,6 +72,7 @@ export default function LandingHeader({
c={activeKey === '/login' ? 'green' : 'gray'}
underline="never"
style={{ fontWeight: activeKey === '/login' ? 600 : 400 }}
size="sm"
>
Login
</Anchor>

View file

@ -1,263 +1,8 @@
import React from 'react';
import {
ActionIcon,
Button,
MantineProvider,
MantineTheme,
MantineThemeOverride,
rem,
Select,
Text,
} from '@mantine/core';
import { MantineProvider } from '@mantine/core';
import { Notifications } from '@mantine/notifications';
const makeTheme = ({
fontFamily = '"IBM Plex Sans", monospace',
}: {
fontFamily?: string;
}): MantineThemeOverride => ({
cursorType: 'pointer',
fontFamily,
primaryColor: 'green',
primaryShade: 8,
autoContrast: true,
white: '#fff',
fontSizes: {
xxs: '11px',
xs: '12px',
sm: '13px',
md: '15px',
lg: '16px',
xl: '18px',
},
spacing: {
xxxs: 'calc(0.375rem * var(--mantine-scale))',
xxs: 'calc(0.5rem * var(--mantine-scale))',
xs: 'calc(0.625rem * var(--mantine-scale))',
sm: 'calc(0.75rem * var(--mantine-scale))',
md: 'calc(1rem * var(--mantine-scale))',
lg: 'calc(1.25rem * var(--mantine-scale))',
xl: 'calc(2rem * var(--mantine-scale))',
},
colors: {
// https://uicolors.app/generate/00c28a
green: [
'#eafff6',
'#cdfee7',
'#a0fad5',
'#63f2bf',
'#25e2a5',
'#00c28a',
'#00a475',
'#008362',
'#00674e',
'#005542',
],
// https://mantine.dev/colors-generator/?color=A1A1AA
// Customized with FAFAFA, D7D8DB, A1A1AA
gray: [
'#FAFAFA', // Off White
'#e6e6ee',
'#D7D8DB', // Light Gray
'#aeaeb7',
'#A1A1AA', // Primary Gray
'#868691',
'#7e7e8b',
'#6c6c79',
'#5f5f6e',
'#515264',
],
dark: [
'#C1C2C5',
'#A6A7AB',
'#909296',
'#5C5F66',
'#373A40',
'#2C2E33',
'#25262B',
'#1A1B1E',
'#141517',
'#101113',
],
},
headings: {
fontFamily,
},
components: {
Modal: {
styles: {
header: {
fontFamily,
fontWeight: 'bold',
},
},
},
InputWrapper: {
styles: {
label: {
marginBottom: 4,
},
description: {
marginBottom: 8,
lineHeight: 1.3,
},
},
},
Select: Select.extend({
styles: {
input: {
border: '1px solid var(--color-border)',
},
},
}),
Input: {
styles: {
input: {
backgroundColor: 'var(--color-bg-field)',
border: '1px solid var(--color-border)',
},
},
},
Card: {
styles: (_theme: MantineTheme, props: { variant?: string }) => {
if (props.variant === 'muted') {
return {
root: {
backgroundColor: 'var(--color-bg-muted)',
border: '1px solid var(--color-border)',
},
};
}
return {
root: {
backgroundColor: 'var(--color-bg-body)',
},
};
},
},
Divider: {
styles: {
root: {
borderColor: 'var(--color-border)',
borderTopColor: 'var(--color-border)',
'--divider-color': 'var(--color-border)',
'--item-border-color': 'var(--color-border)',
},
},
},
Accordion: {
styles: {
control: {
'--item-border-color': 'var(--color-border)',
},
item: {
borderColor: 'var(--color-border)',
},
},
},
UnstyledButton: {
styles: {
root: {
'--item-border-color': 'var(--color-border)',
},
},
},
Paper: {
classNames: (_theme: MantineTheme, props: { variant?: string }) => {
if (props.variant === 'muted') {
return {
root: 'paper-muted',
};
}
return {};
},
styles: (_theme: MantineTheme, props: { variant?: string }) => {
if (props.variant === 'muted') {
return {
root: {
backgroundColor: 'var(--color-bg-muted)',
border: '1px solid var(--color-border)',
},
};
}
return {
root: {
border: '1px solid var(--color-border)',
},
};
},
},
Text: Text.extend({
styles: (theme, props) => {
if (props.variant === 'danger') {
return {
root: {
color: 'var(--color-text-danger)',
},
};
}
return {};
},
}),
Button: Button.extend({
vars: (theme, props) => {
if (props.size === 'xxs') {
return {
root: {
'--button-height': rem(22),
'--button-padding-x': rem(4),
'--button-fz': rem(12),
},
};
}
return { root: {} };
},
}),
ActionIcon: ActionIcon.extend({
defaultProps: {
variant: 'subtle',
color: 'gray',
},
styles: (theme, props) => {
// Subtle variant stays transparent
if (props.variant === 'subtle') {
return {
root: {
backgroundColor: 'transparent',
color: 'var(--color-text)',
'&:hover': {
backgroundColor: 'var(--color-bg-hover)',
},
'&:active': {
backgroundColor: 'var(--color-bg-muted)',
},
},
};
}
// Default variant
if (props.variant === 'default') {
return {
root: {
backgroundColor: 'var(--color-bg-hover)',
color: 'var(--color-text)',
border: 'none',
'&:hover': {
backgroundColor: 'var(--color-bg-muted)',
},
'&:active': {
backgroundColor: 'var(--color-bg-muted)',
},
},
};
}
return {};
},
}),
},
});
import { makeTheme, theme as defaultTheme } from './theme/mantineTheme';
export const ThemeWrapper = ({
fontFamily,
@ -268,8 +13,10 @@ export const ThemeWrapper = ({
colorScheme?: 'dark' | 'light';
children: React.ReactNode;
}) => {
const theme = React.useMemo(() => makeTheme({ fontFamily }), [fontFamily]);
const theme = React.useMemo(
() => (fontFamily ? makeTheme({ fontFamily }) : defaultTheme),
[fontFamily],
);
return (
<MantineProvider forceColorScheme={colorScheme} theme={theme}>
<Notifications zIndex={999999} />

View file

@ -18,6 +18,7 @@ type TimelineEventT = {
color: string;
body: React.ReactNode;
minWidthPerc?: number;
isError?: boolean;
};
const NewTimelineRow = memo(
@ -35,7 +36,9 @@ const NewTimelineRow = memo(
height: number;
scale: number;
offset: number;
eventStyles?: any;
eventStyles?:
| React.CSSProperties
| ((event: TimelineEventT) => React.CSSProperties);
onEventHover?: Function;
onEventClick?: (event: any) => any;
}) {
@ -84,7 +87,9 @@ const NewTimelineRow = memo(
minWidth: `${percWidth.toFixed(6)}%`,
width: `${percWidth.toFixed(6)}%`,
marginLeft: `${percMarginLeft.toFixed(6)}%`,
...eventStyles,
...(typeof eventStyles === 'function'
? eventStyles(e)
: eventStyles),
}}
>
<div style={{ margin: 'auto' }} className="px-2">
@ -166,7 +171,7 @@ function TimelineXAxis({
width: 1,
marginRight: -1,
marginLeft: i === 0 ? 0 : `${percSpacing.toFixed(6)}%`,
background: 'var(--color-bg-surface)',
background: 'var(--color-border-muted)',
}}
>
<div className="ms-2 fs-8.5">{renderMs(i * interval)}</div>
@ -179,10 +184,11 @@ function TimelineXAxis({
style={{
position: 'sticky',
top: 0,
height: 4,
height: 24,
paddingTop: 4,
zIndex: 200,
pointerEvents: 'none',
background: 'var(--color-bg-body)',
}}
>
<div className={`${cx('d-flex align-items-center')}`}>
@ -242,8 +248,8 @@ function TimelineCursor({
>
<div>
<span
className="p-2 rounded"
style={{ background: 'rgba(0,0,0,0.75)' }}
className="p-2 rounded border"
style={{ background: 'var(--color-bg-surface)' }}
>
{overlay}
</span>
@ -325,7 +331,7 @@ function TimelineMouseCursor({
overlay={renderMs(Math.max(cursorTime, 0))}
height={height}
labelWidth={labelWidth}
color="#ffffff88"
color="var(--color-bg-neutral)"
/>
) : null;
}
@ -590,13 +596,14 @@ export default function TimelineChart({
events={row.events}
height={rowHeight}
maxVal={maxVal}
eventStyles={{
eventStyles={(event: TimelineEventT) => ({
borderRadius: 2,
fontSize: rowHeight * 0.5,
border: '1px solid var(--color-border)',
backgroundColor: 'var(--color-bg-neutral)',
color: 'var(--color-text)',
}}
backgroundColor: event.isError
? 'var(--color-bg-danger)'
: 'var(--color-bg-inverted)',
color: 'var(--color-text-inverted)',
})}
scale={scale}
offset={offset}
/>

View file

@ -162,7 +162,7 @@ export function RowOverviewPanel({
return (
<div className="flex-grow-1 overflow-auto" data-testid={dataTestId}>
{!hideHeader && (
<Box px="32px" pt="md">
<Box px="sm" pt="md">
<DBRowSidePanelHeader
date={new Date(firstRow?.__hdx_timestamp ?? 0)}
mainContent={mainContent}
@ -182,6 +182,7 @@ export function RowOverviewPanel({
'topLevelAttributes',
]}
multiple
variant="noPadding"
>
{isHttpRequest && (
<Accordion.Item value="network">

View file

@ -182,6 +182,7 @@ export default function DBTracePanel({
<Button
ms="sm"
variant="outline"
color="gray"
onClick={() => setShowTraceIdInput(false)}
size="xs"
>

View file

@ -609,17 +609,19 @@ export function DBTraceWaterfallChartContainer({
onClick?.({ id, type: type ?? '' });
}}
>
<div className="d-flex">
<div className="d-flex align-items-center" style={{ height: 24 }}>
{Array.from({ length: result.level }).map((_, index) => (
<div
key={index}
style={{
borderLeft: '1px solid var(--color-border)',
marginLeft: 5,
marginLeft: 7,
width: 8,
minWidth: 8,
maxWidth: 8,
flexGrow: 1,
flexShrink: 0,
height: '100%',
}}
></div>
))}
@ -681,8 +683,9 @@ export function DBTraceWaterfallChartContainer({
end,
tooltip: `${displayText} ${tookMs >= 0 ? `took ${tookMs.toFixed(4)}ms` : ''} ${status ? `| Status: ${status}` : ''}`,
color: barColor({ isError, isWarn, isHighlighted }),
body: <span style={{ color: '#FFFFFFEE' }}>{displayText}</span>,
body: <span>{displayText}</span>,
minWidthPerc: 1,
isError,
},
],
};

View file

@ -0,0 +1,80 @@
import React from 'react';
import { ExceptionSubpanel } from './ExceptionSubpanel';
export default {
title: 'Components/ExceptionSubpanel',
component: ExceptionSubpanel,
};
const mockExceptionValues = [
{
type: 'TypeError',
value: 'Cannot read property "foo" of undefined',
mechanism: {
type: 'generic',
handled: false,
data: {
function: 'myFunction',
handler: 'errorHandler',
target: 'window',
},
},
stacktrace: {
frames: [
{
filename: 'App.js',
function: 'myFunction',
lineno: 42,
colno: 13,
in_app: true,
context_line: 'const foo = bar.foo;',
pre_context: ['function myFunction() {'],
post_context: ['return foo;'],
},
{
filename: 'index.js',
function: 'main',
lineno: 10,
colno: 5,
in_app: false,
context_line: 'main();',
pre_context: ['import App from "./App";'],
post_context: ['console.log("done");'],
},
],
},
},
];
const mockBreadcrumbs = [
{
category: 'ui.click',
message: 'Button clicked',
timestamp: 1700000000,
},
{
category: 'fetch',
message: 'GET /api/data',
data: { method: 'GET', url: '/api/data', status_code: 200 },
timestamp: 1700000001,
},
{
category: 'console',
message: 'Error: Something went wrong',
level: 'error',
timestamp: 1700000002,
},
];
const mockLogData = {
timestamp: 1700000000000,
};
export const Default = () => (
<ExceptionSubpanel
logData={mockLogData}
breadcrumbs={mockBreadcrumbs}
exceptionValues={mockExceptionValues}
/>
);

View file

@ -4,7 +4,7 @@
height: 100%;
width: 100%;
flex-direction: column;
padding: 0 4px;
padding: var(--mantine-spacing-xs);
font-size: 12px;
}

View file

@ -0,0 +1,24 @@
import React, { useState } from 'react';
import { QueryClient, QueryClientProvider } from '@tanstack/react-query';
import SQLEditor from './SQLEditor';
const story = {
title: 'Components/SQLEditor',
component: SQLEditor,
};
export default story;
export const Default = () => {
const [value, setValue] = useState('SELECT * FROM users');
const queryClient = new QueryClient();
return (
<QueryClientProvider client={queryClient}>
<SQLEditor
value={value}
onChange={setValue}
placeholder="Type your SQL query..."
/>
</QueryClientProvider>
);
};

View file

@ -0,0 +1,25 @@
import React, { useState } from 'react';
import { QueryClient, QueryClientProvider } from '@tanstack/react-query';
import SQLInlineEditor from './SQLInlineEditor';
export default {
title: 'Components/SQLInlineEditor',
component: SQLInlineEditor,
};
export const Default = () => {
const [value, setValue] = useState('SELECT * FROM table');
const queryClient = new QueryClient();
return (
<QueryClientProvider client={queryClient}>
<SQLInlineEditor
value={value}
onChange={setValue}
placeholder="Type your SQL query..."
label="SQL Query"
allowMultiline
/>
</QueryClientProvider>
);
};

View file

@ -30,12 +30,13 @@ $horizontalPadding: 12px;
}
th {
color: red;
color: var(--color-text-muted);
text-transform: uppercase;
font-size: 9px;
font-weight: 500;
letter-spacing: 1px;
padding: $normalVerticalPadding $horizontalPadding;
text-align: left;
}
td {

View file

@ -0,0 +1,39 @@
import React from 'react';
import { semanticColorsGrouped } from './semanticColorsGrouped';
const story = {
title: 'Design Tokens/Semantic Colors',
};
export default story;
export const AllSemanticColors = () => (
<div style={{ display: 'flex', flexDirection: 'column', gap: 32 }}>
{Object.entries(semanticColorsGrouped).map(([group, tokens]) => (
<div key={group} style={{ marginBottom: 24 }}>
<h3 style={{ fontSize: 16, marginBottom: 12 }}>
{group.charAt(0).toUpperCase() + group.slice(1)}
</h3>
<div style={{ display: 'flex', flexWrap: 'wrap', gap: 16 }}>
{tokens.map(name => (
<div key={name} style={{ width: 140 }}>
<div
style={{
background: `var(--${name})`,
height: 40,
border: '1px solid var(--color-border)',
marginBottom: 8,
borderRadius: 4,
}}
/>
<div style={{ fontSize: 12 }}>{name}</div>
<div
style={{ fontSize: 10, color: '#888' }}
>{`var(--${name})`}</div>
</div>
))}
</div>
</div>
))}
</div>
);

View file

@ -0,0 +1,280 @@
import {
ActionIcon,
Button,
MantineTheme,
MantineThemeOverride,
rem,
Select,
Text,
} from '@mantine/core';
export const makeTheme = ({
fontFamily = '"IBM Plex Sans", monospace',
}: {
fontFamily?: string;
}): MantineThemeOverride => ({
cursorType: 'pointer',
fontFamily,
primaryColor: 'green',
primaryShade: 8,
autoContrast: true,
white: '#fff',
fontSizes: {
xxs: '11px',
xs: '12px',
sm: '13px',
md: '15px',
lg: '16px',
xl: '18px',
},
spacing: {
xxxs: 'calc(0.375rem * var(--mantine-scale))',
xxs: 'calc(0.5rem * var(--mantine-scale))',
xs: 'calc(0.625rem * var(--mantine-scale))',
sm: 'calc(0.75rem * var(--mantine-scale))',
md: 'calc(1rem * var(--mantine-scale))',
lg: 'calc(1.25rem * var(--mantine-scale))',
xl: 'calc(2rem * var(--mantine-scale))',
},
colors: {
green: [
'#eafff6',
'#cdfee7',
'#a0fad5',
'#63f2bf',
'#25e2a5',
'#00c28a',
'#00a475',
'#008362',
'#00674e',
'#005542',
],
gray: [
'#FAFAFA',
'#e6e6ee',
'#D7D8DB',
'#aeaeb7',
'#A1A1AA',
'#868691',
'#7e7e8b',
'#6c6c79',
'#5f5f6e',
'#515264',
],
dark: [
'#C1C2C5',
'#A6A7AB',
'#909296',
'#5C5F66',
'#373A40',
'#2C2E33',
'#25262B',
'#1A1B1E',
'#141517',
'#101113',
],
},
headings: {
fontFamily,
},
components: {
Modal: {
styles: {
header: {
fontFamily,
fontWeight: 'bold',
},
},
},
InputWrapper: {
styles: {
label: {
marginBottom: 4,
},
description: {
marginBottom: 8,
lineHeight: 1.3,
},
},
},
Select: Select.extend({
styles: {
input: {
border: '1px solid var(--color-border)',
},
},
}),
Input: {
styles: {
input: {
backgroundColor: 'var(--color-bg-field)',
border: '1px solid var(--color-border)',
},
},
},
Card: {
styles: (_theme: MantineTheme, props: { variant?: string }) => {
if (props.variant === 'muted') {
return {
root: {
backgroundColor: 'var(--color-bg-muted)',
border: '1px solid var(--color-border)',
},
};
}
return {
root: {
backgroundColor: 'var(--color-bg-body)',
},
};
},
},
Divider: {
styles: {
root: {
borderColor: 'var(--color-border)',
borderTopColor: 'var(--color-border)',
'--divider-color': 'var(--color-border)',
'--item-border-color': 'var(--color-border)',
},
},
},
Accordion: {
styles: (_theme: MantineTheme, props: { variant?: string }) => {
const base = {
control: {
'--item-border-color': 'var(--color-border)',
},
item: {
borderColor: 'var(--color-border)',
},
};
if (props.variant === 'noPadding') {
return {
...base,
content: {
paddingInline: 0,
},
control: {
paddingInlineStart: 0,
},
};
}
return base;
},
},
UnstyledButton: {
styles: {
root: {
'--item-border-color': 'var(--color-border)',
},
},
},
Paper: {
classNames: (_theme: MantineTheme, props: { variant?: string }) => {
if (props.variant === 'muted') {
return {
root: 'paper-muted',
};
}
return {};
},
styles: (_theme: MantineTheme, props: { variant?: string }) => {
if (props.variant === 'muted') {
return {
root: {
backgroundColor: 'var(--color-bg-muted)',
border: '1px solid var(--color-border)',
},
};
}
return {
root: {
border: '1px solid var(--color-border)',
},
};
},
},
Text: Text.extend({
styles: (theme, props) => {
if (props.variant === 'danger') {
return {
root: {
color: 'var(--color-text-danger)',
},
};
}
return {};
},
}),
Button: Button.extend({
vars: (theme, props) => {
if (props.size === 'xxs') {
return {
root: {
'--button-height': rem(22),
'--button-padding-x': rem(4),
'--button-fz': rem(12),
},
};
}
return { root: {} };
},
}),
SegmentedControl: {
styles: {
root: {
background: 'var(--color-bg-field)',
},
indicator: {
background: 'var(--color-bg-field-highlighted)',
},
},
},
ActionIcon: ActionIcon.extend({
defaultProps: {
variant: 'subtle',
color: 'gray',
},
styles: (theme, props) => {
// Subtle variant stays transparent
if (props.variant === 'subtle') {
return {
root: {
backgroundColor: 'transparent',
color: 'var(--color-text)',
'&:hover': {
backgroundColor: 'var(--color-bg-hover)',
},
'&:active': {
backgroundColor: 'var(--color-bg-muted)',
},
},
};
}
// Default variant
if (props.variant === 'default') {
return {
root: {
backgroundColor: 'var(--color-bg-hover)',
color: 'var(--color-text)',
border: 'none',
'&:hover': {
backgroundColor: 'var(--color-bg-muted)',
},
'&:active': {
backgroundColor: 'var(--color-bg-muted)',
},
},
};
}
return {};
},
}),
},
});
export const theme = makeTheme({});

View file

@ -0,0 +1,47 @@
export const semanticColorsGrouped = {
backgrounds: [
'color-bg-body',
'color-bg-surface',
'color-bg-muted',
'color-bg-highlighted',
'color-bg-sidebar',
'color-bg-header',
'color-bg-hover',
'color-bg-active',
'color-bg-field',
'color-bg-field-highlighted',
'color-bg-neutral',
'color-bg-success',
'color-bg-danger',
'color-bg-warning',
'color-bg-brand',
'color-bg-modal',
'color-bg-code',
'color-bg-kbd',
],
borders: ['color-border', 'color-border-code', 'color-border-muted'],
text: [
'color-text',
'color-text-inverted',
'color-text-primary',
'color-text-primary-hover',
'color-text-secondary',
'color-text-muted',
'color-text-muted-hover',
'color-text-success',
'color-text-success-hover',
'color-text-danger',
],
icons: ['color-icon-primary', 'color-icon-muted'],
overlay: ['color-overlay', 'color-backdrop'],
states: ['color-state-hover', 'color-state-selected', 'color-state-focus'],
json: [
'color-json-string',
'color-json-number',
'color-json-boolean',
'color-json-key',
'color-json-object',
'color-json-array',
'color-json-punctuation',
],
};

View file

@ -97,7 +97,7 @@
.lineContext {
color: var(--color-text-secondary);
background-color: var(--color-bg-hover);
background-color: var(--color-bg-highlighted);
padding: 8px 0;
border-radius: 4px;
margin-top: 8px;
@ -149,7 +149,7 @@
cursor: pointer;
&:hover {
background-color: var(--color-bg-hover);
background-color: var(--color-bg-muted);
}
&:active {

View file

@ -6,7 +6,7 @@
height: 100%;
display: flex;
flex-direction: column;
background-color: var(--color-bg-muted);
background-color: var(--color-bg-sidebar);
word-break: break-all;
flex-shrink: 0;
flex-grow: 0;
@ -134,12 +134,12 @@
@keyframes highlight {
0% {
background-color: var(--color-bg-body);
background-color: var(--color-bg-highlighted);
transform: scale(1.02);
}
50% {
background-color: var(--color-bg-body);
background-color: var(--color-bg-highlighted);
transform: scale(1.01);
}

View file

@ -2,12 +2,13 @@
cursor: pointer;
&:hover {
background-color: var(--color-bg-muted);
background-color: var(--color-bg-highlighted);
}
}
.timelineRowActive {
background-color: var(--color-bg-surface);
background-color: var(--color-bg-highlighted);
border-radius: var(--mantine-radius-xs);
}
.labelContainer {

View file

@ -1,24 +1,26 @@
/* Dark Mode (default) */
[data-mantine-color-scheme='dark'] {
/* Backgrounds */
--color-bg-body: var(--mantine-color-dark-8);
--color-bg-body: var(--mantine-color-dark-9);
--color-bg-surface: var(--mantine-color-dark-5);
--color-bg-inverted: var(--mantine-color-dark-1);
--color-bg-muted: var(--mantine-color-dark-7);
--color-bg-highlighted: var(--mantine-color-dark-5);
--color-bg-sidebar: var(--mantine-color-dark-8);
--color-bg-header: var(--mantine-color-dark-8);
--color-bg-highlighted: rgb(55 58 64 / 70%);
--color-bg-sidebar: var(--mantine-color-dark-9);
--color-bg-header: var(--mantine-color-dark-9);
--color-bg-hover: var(--mantine-color-dark-6);
--color-bg-active: var(--mantine-color-dark-5);
--color-bg-field: var(--mantine-color-dark-6);
--color-bg-field-highlighted: var(--mantine-color-dark-4);
--color-bg-field-highlighted: var(--mantine-color-dark-3);
--color-bg-neutral: var(--mantine-color-dark-4);
--color-bg-success: var(--mantine-color-green-5);
--color-bg-danger: var(--mantine-color-red-5);
--color-bg-danger: var(--mantine-color-red-4);
--color-bg-warning: var(--mantine-color-orange-5);
--color-bg-brand: #4ffa7a;
/* Borders & Dividers */
--color-border: var(--mantine-color-dark-5);
--color-border-muted: rgb(255 255 255 / 8%);
/* Text */
--color-text: var(--mantine-color-dark-0);
@ -30,7 +32,7 @@
--color-text-muted-hover: var(--mantine-color-dark-1);
--color-text-success: var(--mantine-color-green-4);
--color-text-success-hover: var(--mantine-color-green-3);
--color-text-danger: var(--mantine-color-red-4);
--color-text-danger: var(--mantine-color-red-3);
/* Icons */
--color-icon-primary: var(--mantine-color-dark-1);
@ -51,12 +53,12 @@
--color-bg-kbd: var(--mantine-color-dark-9);
/* JSON Syntax Highlighting */
--color-json-string: var(--mantine-color-green-4);
--color-json-number: var(--mantine-color-orange-4);
--color-json-boolean: var(--mantine-color-orange-4);
--color-json-key: var(--mantine-color-violet-4);
--color-json-object: var(--mantine-color-green-4);
--color-json-array: var(--mantine-color-green-4);
--color-json-string: var(--mantine-color-green-3);
--color-json-number: var(--mantine-color-orange-3);
--color-json-boolean: var(--mantine-color-orange-3);
--color-json-key: var(--mantine-color-violet-3);
--color-json-object: var(--mantine-color-green-3);
--color-json-array: var(--mantine-color-green-3);
--color-json-punctuation: var(--mantine-color-dark-4);
/* Mantine Overrides */
@ -71,15 +73,16 @@
/* Backgrounds - inverted (dark becomes light) */
--color-bg-body: var(--mantine-color-white);
--color-bg-surface: var(--mantine-color-white);
--color-bg-inverted: var(--mantine-color-dark-3);
--color-bg-muted: #f6f6fa;
--color-bg-highlighted: #e6e8ed;
--color-bg-highlighted: rgb(230 232 237 / 70%);
--color-bg-sidebar: var(--mantine-color-white);
--color-bg-header: var(--mantine-color-gray-1);
--color-bg-modal: var(--mantine-color-white);
--color-bg-hover: var(--mantine-color-gray-3);
--color-bg-active: var(--mantine-color-gray-4);
--color-bg-field: #ececf5;
--color-bg-field-highlighted: var(--mantine-color-gray-1);
--color-bg-field-highlighted: var(--mantine-color-white);
--color-bg-neutral: var(--mantine-color-gray-5);
--color-bg-success: var(--mantine-color-green-8);
--color-bg-danger: var(--mantine-color-red-8);
@ -87,7 +90,8 @@
--color-bg-brand: var(--mantine-color-green-8);
/* Borders & Dividers - inverted */
--color-border: var(--mantine-color-gray-2);
--color-border: var(--mantine-color-gray-1);
--color-border-muted: rgb(0 0 0 / 5%);
/* Text - inverted */
--color-text: var(--mantine-color-dark-9);
@ -99,7 +103,7 @@
--color-text-muted-hover: var(--mantine-color-dark-9);
--color-text-success: var(--mantine-color-green-8);
--color-text-success-hover: var(--mantine-color-green-9);
--color-text-danger: var(--mantine-color-red-7);
--color-text-danger: var(--mantine-color-red-8);
/* Icons - inverted */
--color-icon-primary: var(--mantine-color-dark-8);

View file

@ -4288,6 +4288,7 @@ __metadata:
"@storybook/addon-interactions": "npm:^8.1.5"
"@storybook/addon-links": "npm:^8.1.5"
"@storybook/addon-styling-webpack": "npm:^1.0.0"
"@storybook/addon-themes": "npm:^10.0.8"
"@storybook/blocks": "npm:^8.1.5"
"@storybook/nextjs": "npm:^8.1.5"
"@storybook/react": "npm:^8.1.5"
@ -8267,6 +8268,17 @@ __metadata:
languageName: node
linkType: hard
"@storybook/addon-themes@npm:^10.0.8":
version: 10.0.8
resolution: "@storybook/addon-themes@npm:10.0.8"
dependencies:
ts-dedent: "npm:^2.0.0"
peerDependencies:
storybook: ^10.0.8
checksum: 10c0/5ab4c0a6cb2d1fed75cc8fb0183cef837127b01245da3dd2e5bbcb401a052aac7dd6fb33adad52d93cfdf7ded1ce2901cdee003fc680aa785c25c9139dca1069
languageName: node
linkType: hard
"@storybook/addon-toolbars@npm:8.1.5":
version: 8.1.5
resolution: "@storybook/addon-toolbars@npm:8.1.5"