From c55d4863f33dbcc326477edcca9a168a97ad51f0 Mon Sep 17 00:00:00 2001 From: "sentry[bot]" <39604003+sentry[bot]@users.noreply.github.com> Date: Wed, 14 Oct 2026 22:39:59 +0000 Subject: [PATCH 1/4] ref(issueDetails): Break circular dependency between sidebar and detectorSection --- static/app/views/issueDetails/sidebar/detectorSection.tsx | 2 +- .../views/issueDetails/sidebar/mergedSidebarSection.tsx | 2 +- static/app/views/issueDetails/sidebar/sidebar.tsx | 6 ------ .../views/issueDetails/sidebar/sidebarSectionTitle.tsx | 8 ++++++++ .../issueDetails/sidebar/similarIssuesSidebarSection.tsx | 2 +- 5 files changed, 11 insertions(+), 9 deletions(-) create mode 100644 static/app/views/issueDetails/sidebar/sidebarSectionTitle.tsx diff --git a/static/app/views/issueDetails/sidebar/detectorSection.tsx b/static/app/views/issueDetails/sidebar/detectorSection.tsx index 175549860922..98a4d9824422 100644 --- a/static/app/views/issueDetails/sidebar/detectorSection.tsx +++ b/static/app/views/issueDetails/sidebar/detectorSection.tsx @@ -11,7 +11,7 @@ import {getConfigForIssueType} from 'sentry/utils/issueTypeConfig'; import {makeMonitorDetailsPathname} from 'sentry/views/detectors/pathnames'; import {useIssueDetails} from 'sentry/views/issueDetails/context'; import type {DetectorDetails} from 'sentry/views/issueDetails/sidebar/detectorDetails'; -import {SidebarSectionTitle} from 'sentry/views/issueDetails/sidebar/sidebar'; +import {SidebarSectionTitle} from 'sentry/views/issueDetails/sidebar/sidebarSectionTitle'; export function getDetectorDetails({ event, diff --git a/static/app/views/issueDetails/sidebar/mergedSidebarSection.tsx b/static/app/views/issueDetails/sidebar/mergedSidebarSection.tsx index 587424a7e60e..9ad5b866e0f0 100644 --- a/static/app/views/issueDetails/sidebar/mergedSidebarSection.tsx +++ b/static/app/views/issueDetails/sidebar/mergedSidebarSection.tsx @@ -2,7 +2,7 @@ import {Flex} from '@sentry/scraps/layout'; import {t} from 'sentry/locale'; import {useLocation} from 'sentry/utils/useLocation'; -import {SidebarSectionTitle} from 'sentry/views/issueDetails/sidebar/sidebar'; +import {SidebarSectionTitle} from 'sentry/views/issueDetails/sidebar/sidebarSectionTitle'; import {ViewButton} from 'sentry/views/issueDetails/sidebar/viewButton'; import {Tab, TabPaths} from 'sentry/views/issueDetails/types'; import {useGroupDetailsRoute} from 'sentry/views/issueDetails/useGroupDetailsRoute'; diff --git a/static/app/views/issueDetails/sidebar/sidebar.tsx b/static/app/views/issueDetails/sidebar/sidebar.tsx index 6a7e773394b1..a27bce489513 100644 --- a/static/app/views/issueDetails/sidebar/sidebar.tsx +++ b/static/app/views/issueDetails/sidebar/sidebar.tsx @@ -7,7 +7,6 @@ import {ExternalLink} from '@sentry/scraps/link'; import {ErrorBoundary} from 'sentry/components/errorBoundary'; import * as Layout from 'sentry/components/layouts/thirds'; -import * as SidebarSection from 'sentry/components/sidebarSection'; import {t, tct} from 'sentry/locale'; import type {Event} from 'sentry/types/event'; import type {Group, TeamParticipant, UserParticipant} from 'sentry/types/group'; @@ -140,11 +139,6 @@ const StyledBreak = styled('hr')` border-color: ${p => p.theme.tokens.border.primary}; `; -export const SidebarSectionTitle = styled(SidebarSection.Title)` - margin-bottom: ${p => p.theme.space.md}; - color: ${p => p.theme.tokens.content.primary}; -`; - const Side = styled(Layout.Side)<{isBottomSidebar: boolean}>` position: relative; padding: ${p => p.theme.space.lg} ${p => p.theme.space.xl}; diff --git a/static/app/views/issueDetails/sidebar/sidebarSectionTitle.tsx b/static/app/views/issueDetails/sidebar/sidebarSectionTitle.tsx new file mode 100644 index 000000000000..5a9e6da3ba0c --- /dev/null +++ b/static/app/views/issueDetails/sidebar/sidebarSectionTitle.tsx @@ -0,0 +1,8 @@ +import styled from '@emotion/styled'; + +import * as SidebarSection from 'sentry/components/sidebarSection'; + +export const SidebarSectionTitle = styled(SidebarSection.Title)` + margin-bottom: ${p => p.theme.space.md}; + color: ${p => p.theme.tokens.content.primary}; +`; diff --git a/static/app/views/issueDetails/sidebar/similarIssuesSidebarSection.tsx b/static/app/views/issueDetails/sidebar/similarIssuesSidebarSection.tsx index ebf9325cd8fe..3b446de937a2 100644 --- a/static/app/views/issueDetails/sidebar/similarIssuesSidebarSection.tsx +++ b/static/app/views/issueDetails/sidebar/similarIssuesSidebarSection.tsx @@ -2,7 +2,7 @@ import {Flex} from '@sentry/scraps/layout'; import {t} from 'sentry/locale'; import {useLocation} from 'sentry/utils/useLocation'; -import {SidebarSectionTitle} from 'sentry/views/issueDetails/sidebar/sidebar'; +import {SidebarSectionTitle} from 'sentry/views/issueDetails/sidebar/sidebarSectionTitle'; import {ViewButton} from 'sentry/views/issueDetails/sidebar/viewButton'; import {Tab, TabPaths} from 'sentry/views/issueDetails/types'; import {useGroupDetailsRoute} from 'sentry/views/issueDetails/useGroupDetailsRoute'; From 75b91fe29dbf10d7eb52c9e878980a5f976f5af0 Mon Sep 17 00:00:00 2001 From: Ryan Albrecht Date: Wed, 14 Oct 2026 20:01:54 -0700 Subject: [PATCH 2/4] ref(ui): Build SidebarSection.Title on the Heading primitive SidebarSection.Title was a styled h6, which the scraps prefer-primitives rule flags. It now renders Heading as an h6 at size md with the muted variant, keeping a styled layer only for the flex layout that centers trailing InfoTips and icons, and the top margin. The lint violation is gone, so the sidebarSection.tsx entry is removed from oxlint-suppressions.json. --- oxlint-suppressions.json | 5 ----- static/app/components/sidebarSection.tsx | 18 ++++++++++++++---- 2 files changed, 14 insertions(+), 9 deletions(-) diff --git a/oxlint-suppressions.json b/oxlint-suppressions.json index eaae08212db7..54ef217d9c24 100644 --- a/oxlint-suppressions.json +++ b/oxlint-suppressions.json @@ -1383,11 +1383,6 @@ "count": 1 } }, - "static/app/components/sidebarSection.tsx": { - "@sentry/scraps/prefer-primitives": { - "count": 1 - } - }, "static/app/components/slider/index.tsx": { "@sentry/scraps/prefer-primitives": { "count": 1 diff --git a/static/app/components/sidebarSection.tsx b/static/app/components/sidebarSection.tsx index 784d47e9e2bd..e9b78c754bca 100644 --- a/static/app/components/sidebarSection.tsx +++ b/static/app/components/sidebarSection.tsx @@ -1,18 +1,28 @@ import styled from '@emotion/styled'; import {Container, type ContainerProps} from '@sentry/scraps/layout'; +import {Heading} from '@sentry/scraps/text'; export function Wrap(props: ContainerProps) { return ; } -export const Title = styled('h6')` - color: ${p => p.theme.tokens.content.secondary}; +interface TitleProps { + children: React.ReactNode; + className?: string; + style?: React.CSSProperties; +} + +export function Title(props: TitleProps) { + return ; +} + +// Titles often carry a trailing InfoTip or icon that needs to sit centered next to the text +const StyledHeading = styled(Heading)` display: flex; align-items: center; gap: ${p => p.theme.space.xs}; - font-size: ${p => p.theme.font.size.md}; - margin: ${p => p.theme.space.md} 0 0; + margin-top: ${p => p.theme.space.md}; `; export const IconWrapper = styled('div')` From 57ec95f09c68d0ccc97017379f2bacf0f23f6dfd Mon Sep 17 00:00:00 2001 From: Ryan Albrecht Date: Wed, 14 Oct 2026 20:33:08 -0700 Subject: [PATCH 3/4] ref(issueDetails): Drop shared SidebarSectionTitle in favor of Title variant SidebarSection.Title now accepts a Heading variant, so the primary color no longer needs a styled override. Merged and Similar Issues render SidebarSection.Title directly, and detectorSection keeps a local styled title that only adds the bottom margin. --- static/app/components/sidebarSection.tsx | 1 + static/app/views/issueDetails/sidebar/detectorSection.tsx | 8 ++++++-- .../views/issueDetails/sidebar/mergedSidebarSection.tsx | 6 ++++-- .../views/issueDetails/sidebar/sidebarSectionTitle.tsx | 8 -------- .../issueDetails/sidebar/similarIssuesSidebarSection.tsx | 6 ++++-- 5 files changed, 15 insertions(+), 14 deletions(-) delete mode 100644 static/app/views/issueDetails/sidebar/sidebarSectionTitle.tsx diff --git a/static/app/components/sidebarSection.tsx b/static/app/components/sidebarSection.tsx index e9b78c754bca..45c7cd885569 100644 --- a/static/app/components/sidebarSection.tsx +++ b/static/app/components/sidebarSection.tsx @@ -11,6 +11,7 @@ interface TitleProps { children: React.ReactNode; className?: string; style?: React.CSSProperties; + variant?: React.ComponentProps['variant']; } export function Title(props: TitleProps) { diff --git a/static/app/views/issueDetails/sidebar/detectorSection.tsx b/static/app/views/issueDetails/sidebar/detectorSection.tsx index 98a4d9824422..0176ccc7a5e0 100644 --- a/static/app/views/issueDetails/sidebar/detectorSection.tsx +++ b/static/app/views/issueDetails/sidebar/detectorSection.tsx @@ -2,6 +2,7 @@ import styled from '@emotion/styled'; import {LinkButton} from '@sentry/scraps/button'; +import * as SidebarSection from 'sentry/components/sidebarSection'; import {t} from 'sentry/locale'; import type {Event} from 'sentry/types/event'; import type {Group} from 'sentry/types/group'; @@ -11,7 +12,6 @@ import {getConfigForIssueType} from 'sentry/utils/issueTypeConfig'; import {makeMonitorDetailsPathname} from 'sentry/views/detectors/pathnames'; import {useIssueDetails} from 'sentry/views/issueDetails/context'; import type {DetectorDetails} from 'sentry/views/issueDetails/sidebar/detectorDetails'; -import {SidebarSectionTitle} from 'sentry/views/issueDetails/sidebar/sidebarSectionTitle'; export function getDetectorDetails({ event, @@ -124,7 +124,7 @@ function DetectorSectionContent({ return (
- {title} + {title} {description && {description}} p.theme.space.md}; +`; + const DetectorDescription = styled('p')` margin: ${p => p.theme.space.md} 0; `; diff --git a/static/app/views/issueDetails/sidebar/mergedSidebarSection.tsx b/static/app/views/issueDetails/sidebar/mergedSidebarSection.tsx index 9ad5b866e0f0..6e96f39d5365 100644 --- a/static/app/views/issueDetails/sidebar/mergedSidebarSection.tsx +++ b/static/app/views/issueDetails/sidebar/mergedSidebarSection.tsx @@ -1,8 +1,8 @@ import {Flex} from '@sentry/scraps/layout'; +import * as SidebarSection from 'sentry/components/sidebarSection'; import {t} from 'sentry/locale'; import {useLocation} from 'sentry/utils/useLocation'; -import {SidebarSectionTitle} from 'sentry/views/issueDetails/sidebar/sidebarSectionTitle'; import {ViewButton} from 'sentry/views/issueDetails/sidebar/viewButton'; import {Tab, TabPaths} from 'sentry/views/issueDetails/types'; import {useGroupDetailsRoute} from 'sentry/views/issueDetails/useGroupDetailsRoute'; @@ -13,7 +13,9 @@ export function MergedIssuesSidebarSection() { return ( - {t('Merged Issues')} + + {t('Merged Issues')} + p.theme.space.md}; - color: ${p => p.theme.tokens.content.primary}; -`; diff --git a/static/app/views/issueDetails/sidebar/similarIssuesSidebarSection.tsx b/static/app/views/issueDetails/sidebar/similarIssuesSidebarSection.tsx index 3b446de937a2..97e66f7b2ba3 100644 --- a/static/app/views/issueDetails/sidebar/similarIssuesSidebarSection.tsx +++ b/static/app/views/issueDetails/sidebar/similarIssuesSidebarSection.tsx @@ -1,8 +1,8 @@ import {Flex} from '@sentry/scraps/layout'; +import * as SidebarSection from 'sentry/components/sidebarSection'; import {t} from 'sentry/locale'; import {useLocation} from 'sentry/utils/useLocation'; -import {SidebarSectionTitle} from 'sentry/views/issueDetails/sidebar/sidebarSectionTitle'; import {ViewButton} from 'sentry/views/issueDetails/sidebar/viewButton'; import {Tab, TabPaths} from 'sentry/views/issueDetails/types'; import {useGroupDetailsRoute} from 'sentry/views/issueDetails/useGroupDetailsRoute'; @@ -13,7 +13,9 @@ export function SimilarIssuesSidebarSection() { return ( - {t('Similar Issues')} + + {t('Similar Issues')} + Date: Wed, 14 Oct 2026 20:43:30 -0700 Subject: [PATCH 4/4] ref(issueDetails): Space detector title with Container instead of styled Heading has no margin props, so the detector title's bottom spacing now comes from a Container marginBottom rather than a local styled wrapper. --- .../app/views/issueDetails/sidebar/detectorSection.tsx | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/static/app/views/issueDetails/sidebar/detectorSection.tsx b/static/app/views/issueDetails/sidebar/detectorSection.tsx index 0176ccc7a5e0..bbe05af66fae 100644 --- a/static/app/views/issueDetails/sidebar/detectorSection.tsx +++ b/static/app/views/issueDetails/sidebar/detectorSection.tsx @@ -1,6 +1,7 @@ import styled from '@emotion/styled'; import {LinkButton} from '@sentry/scraps/button'; +import {Container} from '@sentry/scraps/layout'; import * as SidebarSection from 'sentry/components/sidebarSection'; import {t} from 'sentry/locale'; @@ -124,7 +125,9 @@ function DetectorSectionContent({ return (
- {title} + + {title} + {description && {description}} p.theme.space.md}; -`; - const DetectorDescription = styled('p')` margin: ${p => p.theme.space.md} 0; `;