Skip to content

Commit ba5329c

Browse files
natemoo-reclaudecursoragent
authored
ref(nav): migrate breadcrumbs to TopBar.Title (#112672)
When the `page-frame` feature is active, we need to render detail page breadcrumbs via `<TopBar.Slot name="title">` so they appear in the sticky TopBar. Closes DE-1081, DE-1086, DE-1087, DE-1093, DE-1089, DE-1092, DE-1091, DE-1088, DE-1090 --------- Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com> Co-authored-by: Cursor Agent <cursoragent@cursor.com>
1 parent 5312096 commit ba5329c

File tree

12 files changed

+197
-64
lines changed

12 files changed

+197
-64
lines changed

static/app/views/dashboards/detail.tsx

Lines changed: 34 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1179,27 +1179,45 @@ class DashboardDetail extends Component<Props, State> {
11791179
<MetricsResultsMetaProvider>
11801180
<NoProjectMessage organization={organization}>
11811181
{this.isEmbedded ? null : (
1182-
<Layout.Header>
1183-
<Layout.HeaderContent>
1184-
<Breadcrumbs
1185-
crumbs={[
1186-
{
1187-
label: t('Dashboards'),
1188-
to: `/organizations/${organization.slug}/dashboards/`,
1189-
},
1190-
{
1191-
label: this.getBreadcrumbLabel(),
1192-
},
1193-
]}
1194-
/>
1195-
<Layout.Title>
1182+
<Layout.Header unified={this.props.hasPageFrameFeature}>
1183+
{this.props.hasPageFrameFeature ? (
1184+
<TopBar.Slot name="title">
1185+
<Breadcrumbs
1186+
crumbs={[
1187+
{
1188+
label: t('Dashboards'),
1189+
to: `/organizations/${organization.slug}/dashboards/`,
1190+
},
1191+
]}
1192+
/>
11961193
<DashboardTitle
11971194
dashboard={modifiedDashboard ?? dashboard}
11981195
onUpdate={this.setModifiedDashboard}
11991196
isEditingDashboard={this.isEditingDashboard}
12001197
/>
1201-
</Layout.Title>
1202-
</Layout.HeaderContent>
1198+
</TopBar.Slot>
1199+
) : (
1200+
<Layout.HeaderContent>
1201+
<Breadcrumbs
1202+
crumbs={[
1203+
{
1204+
label: t('Dashboards'),
1205+
to: `/organizations/${organization.slug}/dashboards/`,
1206+
},
1207+
{
1208+
label: this.getBreadcrumbLabel(),
1209+
},
1210+
]}
1211+
/>
1212+
<Layout.Title>
1213+
<DashboardTitle
1214+
dashboard={modifiedDashboard ?? dashboard}
1215+
onUpdate={this.setModifiedDashboard}
1216+
isEditingDashboard={this.isEditingDashboard}
1217+
/>
1218+
</Layout.Title>
1219+
</Layout.HeaderContent>
1220+
)}
12031221
{this.props.hasPageFrameFeature ? (
12041222
<TopBar.Slot name="actions">
12051223
<Controls

static/app/views/detectors/components/details/common/header.tsx

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,8 @@ import {
1414
makeMonitorTypePathname,
1515
} from 'sentry/views/detectors/pathnames';
1616
import {getDetectorTypeLabel} from 'sentry/views/detectors/utils/detectorTypeConfig';
17+
import {TopBar} from 'sentry/views/navigation/topBar';
18+
import {useHasPageFrameFeature} from 'sentry/views/navigation/useHasPageFrameFeature';
1719

1820
type DetectorDetailsHeaderProps = {
1921
detector: Detector;
@@ -46,10 +48,19 @@ export function DetectorDetailsDefaultHeaderContent({
4648
detector: Detector;
4749
project: Project;
4850
}) {
51+
const hasPageFrameFeature = useHasPageFrameFeature();
4952
return (
5053
<DetailLayout.HeaderContent>
51-
<DetectorDetailsBreadcrumbs detector={detector} />
52-
<DetailLayout.Title title={detector.name} project={project} />
54+
{hasPageFrameFeature ? (
55+
<TopBar.Slot name="title">
56+
<DetectorDetailsBreadcrumbs detector={detector} />
57+
</TopBar.Slot>
58+
) : (
59+
<DetectorDetailsBreadcrumbs detector={detector} />
60+
)}
61+
{!hasPageFrameFeature && (
62+
<DetailLayout.Title title={detector.name} project={project} />
63+
)}
5364
</DetailLayout.HeaderContent>
5465
);
5566
}

static/app/views/detectors/components/forms/newDetectorLayout.tsx

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,8 @@ import {DetectorNameField} from 'sentry/views/detectors/components/forms/common/
1818
import {NewDetectorFooter} from 'sentry/views/detectors/components/forms/common/footer';
1919
import {MonitorFeedbackButton} from 'sentry/views/detectors/components/monitorFeedbackButton';
2020
import {useCreateDetectorFormSubmit} from 'sentry/views/detectors/hooks/useCreateDetectorFormSubmit';
21+
import {TopBar} from 'sentry/views/navigation/topBar';
22+
import {useHasPageFrameFeature} from 'sentry/views/navigation/useHasPageFrameFeature';
2123

2224
type NewDetectorLayoutProps<TFormData, TUpdatePayload> = {
2325
children: React.ReactNode;
@@ -47,6 +49,7 @@ export function NewDetectorLayout<
4749
const theme = useTheme();
4850
const maxWidth = theme.breakpoints.xl;
4951
const {projects} = useProjects();
52+
const hasPageFrame = useHasPageFrameFeature();
5053

5154
const initialProjectId = useMemo(() => {
5255
const queryProjectId = location.query.project as string | undefined;
@@ -97,7 +100,13 @@ export function NewDetectorLayout<
97100
<EditLayout formProps={formProps}>
98101
<EditLayout.Header maxWidth={maxWidth}>
99102
<EditLayout.HeaderContent>
100-
<NewDetectorBreadcrumbs detectorType={detectorType} />
103+
{hasPageFrame ? (
104+
<TopBar.Slot name="title">
105+
<NewDetectorBreadcrumbs detectorType={detectorType} />
106+
</TopBar.Slot>
107+
) : (
108+
<NewDetectorBreadcrumbs detectorType={detectorType} />
109+
)}
101110
</EditLayout.HeaderContent>
102111

103112
<div>

static/app/views/detectors/new.tsx

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,8 @@ import {
1818
} from 'sentry/views/detectors/components/detectorTypeForm';
1919
import {MonitorFeedbackButton} from 'sentry/views/detectors/components/monitorFeedbackButton';
2020
import {makeMonitorBasePathname} from 'sentry/views/detectors/pathnames';
21+
import {TopBar} from 'sentry/views/navigation/topBar';
22+
import {useHasPageFrameFeature} from 'sentry/views/navigation/useHasPageFrameFeature';
2123

2224
function NewDetectorBreadcrumbs() {
2325
const organization = useOrganization();
@@ -42,6 +44,7 @@ export default function DetectorNew() {
4244
useWorkflowEngineFeatureGate({redirect: true});
4345
const theme = useTheme();
4446
const maxWidth = theme.breakpoints.xl;
47+
const hasPageFrame = useHasPageFrameFeature();
4548
const [detectorType] = useDetectorTypeQueryState();
4649
const [projectId] = useQueryState('project', parseAsString);
4750

@@ -65,8 +68,14 @@ export default function DetectorNew() {
6568
<SentryDocumentTitle title={t('New Monitor')} />
6669
<EditLayout.Header maxWidth={maxWidth}>
6770
<EditLayout.HeaderContent>
68-
<NewDetectorBreadcrumbs />
69-
<EditLayout.Title title={t('Select monitor type')} />
71+
{hasPageFrame ? (
72+
<TopBar.Slot name="title">
73+
<NewDetectorBreadcrumbs />
74+
</TopBar.Slot>
75+
) : (
76+
<NewDetectorBreadcrumbs />
77+
)}
78+
{!hasPageFrame && <EditLayout.Title title={t('Select monitor type')} />}
7079
<Text as="p" size="md" variant="muted">
7180
{tct(
7281
'Monitors detect problems in your application and send alerts when they occur. [docsLink:Read the Docs].',

static/app/views/explore/components/breadcrumb.tsx

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,10 @@ import {makeTracesPathname} from 'sentry/views/traces/pathnames';
1010

1111
export function ExploreBreadcrumb({
1212
traceItemDataset,
13+
savedQueryName,
1314
}: {
1415
traceItemDataset: TraceItemDataset;
16+
savedQueryName?: string;
1517
}) {
1618
const organization = useOrganization();
1719
const crumbs: Crumb[] = [];
@@ -40,7 +42,7 @@ export function ExploreBreadcrumb({
4042
});
4143
}
4244
crumbs.push({
43-
label: t('Saved Query'),
45+
label: savedQueryName ?? t('Saved Query'),
4446
});
4547

4648
return <Breadcrumbs crumbs={crumbs} />;

static/app/views/explore/logs/content.tsx

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -126,7 +126,10 @@ function LogsHeader() {
126126
/>
127127
) : null}
128128
{title && defined(pageId) ? (
129-
<ExploreBreadcrumb traceItemDataset={TraceItemDataset.LOGS} />
129+
<ExploreBreadcrumb
130+
traceItemDataset={TraceItemDataset.LOGS}
131+
savedQueryName={savedQuery?.name}
132+
/>
130133
) : null}
131134

132135
<Layout.Title>{title ? title : t('Logs')}</Layout.Title>

static/app/views/explore/metrics/content.tsx

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -102,7 +102,10 @@ function MetricsHeader() {
102102
/>
103103
) : null}
104104
{title && defined(pageId) ? (
105-
<ExploreBreadcrumb traceItemDataset={TraceItemDataset.TRACEMETRICS} />
105+
<ExploreBreadcrumb
106+
traceItemDataset={TraceItemDataset.TRACEMETRICS}
107+
savedQueryName={savedQuery?.name}
108+
/>
106109
) : null}
107110
<Layout.Title>
108111
{title ? title : METRICS_TITLE}

static/app/views/explore/spans/content.tsx

Lines changed: 47 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -167,19 +167,53 @@ function SpansTabHeader() {
167167
orgSlug={organization?.slug}
168168
/>
169169
) : null}
170-
{title && defined(id) ? (
171-
<ExploreBreadcrumb traceItemDataset={TraceItemDataset.SPANS} />
172-
) : null}
173-
<Layout.Title>
174-
{title ? title : t('Traces')}
175-
<PageHeadingQuestionTooltip
176-
docsUrl="https://github.com/getsentry/sentry/discussions/81239"
177-
title={t(
178-
'Find problematic spans/traces or compute real-time metrics via aggregation.'
179-
)}
180-
linkLabel={t('Read the Discussion')}
181-
/>
182-
</Layout.Title>
170+
{hasPageFrameFeature ? (
171+
title && defined(id) ? (
172+
<TopBar.Slot name="title">
173+
<ExploreBreadcrumb
174+
traceItemDataset={TraceItemDataset.SPANS}
175+
savedQueryName={savedQuery?.name}
176+
/>
177+
<PageHeadingQuestionTooltip
178+
docsUrl="https://github.com/getsentry/sentry/discussions/81239"
179+
title={t(
180+
'Find problematic spans/traces or compute real-time metrics via aggregation.'
181+
)}
182+
linkLabel={t('Read the Discussion')}
183+
/>
184+
</TopBar.Slot>
185+
) : (
186+
<TopBar.Slot name="title">
187+
{title ? title : t('Traces')}
188+
<PageHeadingQuestionTooltip
189+
docsUrl="https://github.com/getsentry/sentry/discussions/81239"
190+
title={t(
191+
'Find problematic spans/traces or compute real-time metrics via aggregation.'
192+
)}
193+
linkLabel={t('Read the Discussion')}
194+
/>
195+
</TopBar.Slot>
196+
)
197+
) : (
198+
<Fragment>
199+
{title && defined(id) ? (
200+
<ExploreBreadcrumb
201+
traceItemDataset={TraceItemDataset.SPANS}
202+
savedQueryName={savedQuery?.name}
203+
/>
204+
) : null}
205+
<Layout.Title>
206+
{title ? title : t('Traces')}
207+
<PageHeadingQuestionTooltip
208+
docsUrl="https://github.com/getsentry/sentry/discussions/81239"
209+
title={t(
210+
'Find problematic spans/traces or compute real-time metrics via aggregation.'
211+
)}
212+
linkLabel={t('Read the Discussion')}
213+
/>
214+
</Layout.Title>
215+
</Fragment>
216+
)}
183217
</Layout.HeaderContent>
184218
{hasPageFrameFeature ? (
185219
<Fragment>

static/app/views/issueDetails/streamline/header/header.tsx

Lines changed: 32 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -118,20 +118,39 @@ export function StreamlinedGroupHeader({event, group, project}: GroupHeaderProps
118118
<Header>
119119
<Flex justify="between">
120120
<Flex align="center" gap="md">
121-
<StyledBreadcrumbs
122-
crumbs={[
123-
{
124-
label: 'Issues',
125-
to: {
126-
pathname: `/organizations/${organization.slug}/issues/`,
127-
query,
121+
{hasPageFrameFeature ? (
122+
<TopBar.Slot name="title">
123+
<StyledBreadcrumbs
124+
crumbs={[
125+
{
126+
label: 'Issues',
127+
to: {
128+
pathname: `/organizations/${organization.slug}/issues/`,
129+
query,
130+
},
131+
},
132+
{
133+
label: <IssueIdBreadcrumb project={project} group={group} />,
134+
},
135+
]}
136+
/>
137+
</TopBar.Slot>
138+
) : (
139+
<StyledBreadcrumbs
140+
crumbs={[
141+
{
142+
label: 'Issues',
143+
to: {
144+
pathname: `/organizations/${organization.slug}/issues/`,
145+
query,
146+
},
147+
},
148+
{
149+
label: <IssueIdBreadcrumb project={project} group={group} />,
128150
},
129-
},
130-
{
131-
label: <IssueIdBreadcrumb project={project} group={group} />,
132-
},
133-
]}
134-
/>
151+
]}
152+
/>
153+
)}
135154
{hasErrorUpsampling && (
136155
<Tooltip
137156
title={t(

static/app/views/performance/newTraceDetails/traceHeader/index.tsx

Lines changed: 25 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -89,16 +89,31 @@ export function TraceMetaDataHeader(props: TraceMetadataHeaderProps) {
8989
<TraceHeaderComponents.HeaderLayout>
9090
<TraceHeaderComponents.HeaderContent>
9191
<TraceHeaderComponents.HeaderRow>
92-
<Breadcrumbs
93-
crumbs={getTraceViewBreadcrumbs({
94-
organization: props.organization,
95-
location,
96-
moduleURLBuilder,
97-
traceSlug: props.traceSlug,
98-
project,
99-
view,
100-
})}
101-
/>
92+
{hasPageFrameFeature ? (
93+
<TopBar.Slot name="title">
94+
<Breadcrumbs
95+
crumbs={getTraceViewBreadcrumbs({
96+
organization: props.organization,
97+
location,
98+
moduleURLBuilder,
99+
traceSlug: props.traceSlug,
100+
project,
101+
view,
102+
})}
103+
/>
104+
</TopBar.Slot>
105+
) : (
106+
<Breadcrumbs
107+
crumbs={getTraceViewBreadcrumbs({
108+
organization: props.organization,
109+
location,
110+
moduleURLBuilder,
111+
traceSlug: props.traceSlug,
112+
project,
113+
view,
114+
})}
115+
/>
116+
)}
102117
<Grid flow="column" align="center" gap="md">
103118
{hasPageFrameFeature ? (
104119
<TopBar.Slot name="feedback">

0 commit comments

Comments
 (0)