diff --git a/static/app/utils/theme/theme.tsx b/static/app/utils/theme/theme.tsx index 525abd5f468a52..d7409cf88f1665 100644 --- a/static/app/utils/theme/theme.tsx +++ b/static/app/utils/theme/theme.tsx @@ -161,12 +161,13 @@ const generateThemeUtils = ( colors: ReturnType, aliases: Aliases ) => ({ - tooltipUnderline: (underlineColor: ColorOrAlias = 'gray300') => ({ + tooltipUnderline: (underlineColor: ColorOrAlias | string = 'gray300') => ({ textDecoration: 'underline' as const, textDecorationThickness: '0.75px', textUnderlineOffset: '1.25px', - // @ts-expect-error TS(7053): Element implicitly has an 'any' type because expre... Remove this comment to see the full error message - textDecorationColor: colors[underlineColor] ?? aliases[underlineColor], + textDecorationColor: + // @ts-expect-error TS(7053): Element implicitly has an 'any' type because expre... Remove this comment to see the full error message + colors[underlineColor] ?? aliases[underlineColor] ?? underlineColor, textDecorationStyle: 'dotted' as const, }), overflowEllipsis: css` diff --git a/static/app/utils/useHoverOverlay.tsx b/static/app/utils/useHoverOverlay.tsx index 42904bbf7b2214..9796c4bc146c5f 100644 --- a/static/app/utils/useHoverOverlay.tsx +++ b/static/app/utils/useHoverOverlay.tsx @@ -137,7 +137,7 @@ interface UseHoverOverlayProps { /** * Color of the dotted underline, if available. See also: showUnderline. */ - underlineColor?: ColorOrAlias; + underlineColor?: ColorOrAlias | string; } export function isOverflown(el: Element): boolean { diff --git a/static/app/views/performance/newTraceDetails/traceDrawer/details/styles.tsx b/static/app/views/performance/newTraceDetails/traceDrawer/details/styles.tsx index 01876dd865678d..5dd19485272058 100644 --- a/static/app/views/performance/newTraceDetails/traceDrawer/details/styles.tsx +++ b/static/app/views/performance/newTraceDetails/traceDrawer/details/styles.tsx @@ -1,5 +1,6 @@ import {Fragment, useMemo, useState, type PropsWithChildren} from 'react'; import {css, useTheme} from '@emotion/react'; +import type {Theme} from '@emotion/react'; import styled from '@emotion/styled'; import {useHover} from '@react-aria/interactions'; import type {LocationDescriptor} from 'history'; @@ -53,7 +54,7 @@ import type {Project} from 'sentry/types/project'; import {trackAnalytics} from 'sentry/utils/analytics'; import getDuration from 'sentry/utils/duration/getDuration'; import {MarkedText} from 'sentry/utils/marked/markedText'; -import type {Color, ColorOrAlias} from 'sentry/utils/theme'; +import type {Color} from 'sentry/utils/theme'; import {useLocation} from 'sentry/utils/useLocation'; import useOrganization from 'sentry/utils/useOrganization'; import {useParams} from 'sentry/utils/useParams'; @@ -254,24 +255,22 @@ const HeaderContainer = styled(FlexBox)` margin-bottom: ${space(1)}; `; -const DURATION_COMPARISON_STATUS_COLORS: { - equal: {light: ColorOrAlias; normal: ColorOrAlias}; - faster: {light: ColorOrAlias; normal: ColorOrAlias}; - slower: {light: ColorOrAlias; normal: ColorOrAlias}; -} = { - faster: { - light: 'green100', - normal: 'green300', - }, - slower: { - light: 'red100', - normal: 'red300', - }, - equal: { - light: 'gray100', - normal: 'gray300', - }, -}; +function makeDurationComparisonStatusColors(theme: Theme) { + return { + faster: { + light: theme.colors.green100, + normal: theme.colors.green400, + }, + slower: { + light: theme.colors.red100, + normal: theme.colors.red400, + }, + equal: { + light: theme.colors.gray100, + normal: theme.colors.gray400, + }, + }; +} const MIN_PCT_DURATION_DIFFERENCE = 10; @@ -284,6 +283,7 @@ type DurationComparison = { const getDurationComparison = ( baseline: number | undefined, duration: number, + theme: Theme, baseDescription?: string ): DurationComparison => { if (!baseline) { @@ -294,12 +294,10 @@ const getDurationComparison = ( const deltaPct = Math.round(Math.abs((delta / baseline) * 100)); const status = delta > 0 ? 'slower' : delta < 0 ? 'faster' : 'equal'; + const colors = makeDurationComparisonStatusColors(theme); + const formattedBaseDuration = ( - + {getDuration(baseline, 2, true)} ); @@ -332,6 +330,8 @@ type DurationProps = { }; function Duration(props: DurationProps) { + const theme = useTheme(); + if (typeof props.duration !== 'number' || Number.isNaN(props.duration)) { return {t('unknown')}; } @@ -348,6 +348,7 @@ function Duration(props: DurationProps) { const comparison = getDurationComparison( props.baseline, props.duration, + theme, props.baseDescription ); @@ -429,6 +430,7 @@ function Highlights({ }: HighlightProps) { const location = useLocation(); const organization = useOrganization(); + const theme = useTheme(); const isAiNode = getIsAiNode(node); const isMCPNode = getIsMCPNode(node); @@ -442,6 +444,7 @@ function Highlights({ const comparison = getDurationComparison( avgDuration, durationInSeconds, + theme, comparisonDescription ); @@ -650,9 +653,9 @@ const HiglightsDurationComparison = styled('div')< >` white-space: nowrap; border-radius: 12px; - color: ${p => p.theme[DURATION_COMPARISON_STATUS_COLORS[p.status].normal]}; - background-color: ${p => p.theme[DURATION_COMPARISON_STATUS_COLORS[p.status].light]}; - border: solid 1px ${p => p.theme[DURATION_COMPARISON_STATUS_COLORS[p.status].light]}; + color: ${p => makeDurationComparisonStatusColors(p.theme)[p.status].normal}; + background-color: ${p => makeDurationComparisonStatusColors(p.theme)[p.status].light}; + border: solid 1px ${p => makeDurationComparisonStatusColors(p.theme)[p.status].light}; font-size: ${p => p.theme.fontSize.xs}; padding: ${space(0.25)} ${space(1)}; display: inline-block; @@ -776,7 +779,7 @@ const DurationContainer = styled('span')` `; const Comparison = styled('span')<{status: 'faster' | 'slower' | 'equal'}>` - color: ${p => p.theme[DURATION_COMPARISON_STATUS_COLORS[p.status].normal]}; + color: ${p => makeDurationComparisonStatusColors(p.theme)[p.status].normal}; `; const TableValueRow = styled('div')`