Skip to content

Commit 1b5f284

Browse files
JonasBaclaudegetsantry[bot]cursoragent
authored andcommitted
ref(nav) use topbar slot for feedback button (#112443)
Migrates the use of feedback buttons inside page headers to the Slot inside TopBar. When components are rendered into our feedback slot, they replace the fallback Feedback button with the provided component or in this case, a customized feedback button that allows). Users get an identical experience while developers get an entry point into being able to customize the slot. It is advisable to **not** set any size prop here and override the default button size provided by the SizeContext from our TopBar component and instead focus on the only replacing the button tags, text or other attributes. Before <img width="2752" height="232" alt="CleanShot 2026-04-08 at 03 17 12@2x" src="https://github.com/user-attachments/assets/d6ce6447-4ed0-4873-933a-7935ff92cc8b" /> After <img width="2720" height="270" alt="CleanShot 2026-04-08 at 03 17 22@2x" src="https://github.com/user-attachments/assets/941e6ca6-ddde-4b29-891a-1957234daf29" /> Fix DE-1069 --------- Co-authored-by: Claude <noreply@anthropic.com> Co-authored-by: getsantry[bot] <66042841+getsantry[bot]@users.noreply.github.com> Co-authored-by: Cursor Agent <cursoragent@cursor.com> Co-authored-by: Jonas <JonasBa@users.noreply.github.com>
1 parent e2ca3b0 commit 1b5f284

File tree

34 files changed

+520
-192
lines changed

34 files changed

+520
-192
lines changed

static/app/components/profiling/continuousProfileHeader.tsx

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,8 @@ import {trackAnalytics} from 'sentry/utils/analytics';
1313
import {generateLinkToEventInTraceView} from 'sentry/utils/discover/urls';
1414
import {useLocation} from 'sentry/utils/useLocation';
1515
import {useOrganization} from 'sentry/utils/useOrganization';
16+
import {TopBar} from 'sentry/views/navigation/topBar';
17+
import {useHasPageFrameFeature} from 'sentry/views/navigation/useHasPageFrameFeature';
1618

1719
interface ContinuousProfileHeader {
1820
transaction: Event | null;
@@ -21,6 +23,7 @@ interface ContinuousProfileHeader {
2123
export function ContinuousProfileHeader({transaction}: ContinuousProfileHeader) {
2224
const location = useLocation();
2325
const organization = useOrganization();
26+
const hasPageFrameFeature = useHasPageFrameFeature();
2427

2528
// @TODO add breadcrumbs when other views are implemented
2629
const breadCrumbs = useMemo((): ProfilingBreadcrumbsProps['trails'] => {
@@ -51,7 +54,13 @@ export function ContinuousProfileHeader({transaction}: ContinuousProfileHeader)
5154
</SmallerProfilingBreadcrumbsWrapper>
5255
</SmallerHeaderContent>
5356
<StyledHeaderActions>
54-
<FeedbackButton />
57+
{hasPageFrameFeature ? (
58+
<TopBar.Slot name="feedback">
59+
<FeedbackButton>{null}</FeedbackButton>
60+
</TopBar.Slot>
61+
) : (
62+
<FeedbackButton />
63+
)}
5564
{transactionTarget && (
5665
<LinkButton size="sm" onClick={handleGoToTransaction} to={transactionTarget}>
5766
{t('Go to Trace')}

static/app/components/profiling/profileHeader.tsx

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,8 @@ import {generateLinkToEventInTraceView} from 'sentry/utils/discover/urls';
1313
import {isSchema, isSentrySampledProfile} from 'sentry/utils/profiling/guards/profile';
1414
import {useLocation} from 'sentry/utils/useLocation';
1515
import {useOrganization} from 'sentry/utils/useOrganization';
16+
import {TopBar} from 'sentry/views/navigation/topBar';
17+
import {useHasPageFrameFeature} from 'sentry/views/navigation/useHasPageFrameFeature';
1618
import {useProfiles} from 'sentry/views/profiling/profilesProvider';
1719

1820
function getTransactionName(input: Profiling.ProfileInput): string {
@@ -36,6 +38,7 @@ function ProfileHeader({transaction, projectId, eventId}: ProfileHeaderProps) {
3638
const location = useLocation();
3739
const organization = useOrganization();
3840
const profiles = useProfiles();
41+
const hasPageFrameFeature = useHasPageFrameFeature();
3942

4043
const transactionName =
4144
profiles.type === 'resolved' ? getTransactionName(profiles.data) : '';
@@ -89,7 +92,13 @@ function ProfileHeader({transaction, projectId, eventId}: ProfileHeaderProps) {
8992
</SmallerProfilingBreadcrumbsWrapper>
9093
</SmallerHeaderContent>
9194
<StyledHeaderActions>
92-
<FeedbackButton />
95+
{hasPageFrameFeature ? (
96+
<TopBar.Slot name="feedback">
97+
<FeedbackButton>{null}</FeedbackButton>
98+
</TopBar.Slot>
99+
) : (
100+
<FeedbackButton />
101+
)}
93102
{transactionTarget && (
94103
<LinkButton size="sm" onClick={handleGoToTransaction} to={transactionTarget}>
95104
{t('Go to Trace')}

static/app/views/alerts/list/header.tsx

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,8 @@ import {useLocation} from 'sentry/utils/useLocation';
1515
import {useNavigate} from 'sentry/utils/useNavigate';
1616
import {useOrganization} from 'sentry/utils/useOrganization';
1717
import {makeAlertsPathname} from 'sentry/views/alerts/pathnames';
18+
import {TopBar} from 'sentry/views/navigation/topBar';
19+
import {useHasPageFrameFeature} from 'sentry/views/navigation/useHasPageFrameFeature';
1820

1921
type Props = {
2022
activeTab: 'stream' | 'rules';
@@ -25,6 +27,7 @@ export function AlertHeader({activeTab}: Props) {
2527
const location = useLocation();
2628
const organization = useOrganization();
2729
const {selection} = usePageFilters();
30+
const hasPageFrameFeature = useHasPageFrameFeature();
2831
/**
2932
* Incidents list is currently at the organization level, but the link needs to
3033
* go down to a specific project scope.
@@ -79,7 +82,13 @@ export function AlertHeader({activeTab}: Props) {
7982
>
8083
{t('Create Alert')}
8184
</CreateAlertButton>
82-
<FeedbackButton />
85+
{hasPageFrameFeature ? (
86+
<TopBar.Slot name="feedback">
87+
<FeedbackButton>{null}</FeedbackButton>
88+
</TopBar.Slot>
89+
) : (
90+
<FeedbackButton />
91+
)}
8392
<LinkButton
8493
size="sm"
8594
onClick={handleNavigateToSettings}

static/app/views/automations/components/automationFeedbackButton.tsx

Lines changed: 23 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,31 @@
11
import {FeedbackButton} from 'sentry/components/feedbackButton/feedbackButton';
22
import {t} from 'sentry/locale';
3+
import {TopBar} from 'sentry/views/navigation/topBar';
4+
import {useHasPageFrameFeature} from 'sentry/views/navigation/useHasPageFrameFeature';
5+
6+
const automationFeedbackOptions = {
7+
messagePlaceholder: t('How can we improve the alerts experience?'),
8+
tags: {
9+
['feedback.source']: 'automations',
10+
['feedback.owner']: 'aci',
11+
},
12+
};
313

414
export function AutomationFeedbackButton() {
15+
const hasPageFrameFeature = useHasPageFrameFeature();
16+
17+
if (hasPageFrameFeature) {
18+
return (
19+
<TopBar.Slot name="feedback">
20+
<FeedbackButton feedbackOptions={automationFeedbackOptions}>
21+
{null}
22+
</FeedbackButton>
23+
</TopBar.Slot>
24+
);
25+
}
26+
527
return (
6-
<FeedbackButton
7-
size="sm"
8-
feedbackOptions={{
9-
messagePlaceholder: t('How can we improve the alerts experience?'),
10-
tags: {
11-
['feedback.source']: 'automations',
12-
['feedback.owner']: 'aci',
13-
},
14-
}}
15-
>
28+
<FeedbackButton size="sm" feedbackOptions={automationFeedbackOptions}>
1629
{t('Feedback')}
1730
</FeedbackButton>
1831
);

static/app/views/dashboards/manage/index.tsx

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,8 @@ import type {DashboardsLayout} from 'sentry/views/dashboards/manage/types';
5959
import {DashboardFilter, PREBUILT_DASHBOARD_LABEL} from 'sentry/views/dashboards/types';
6060
import type {DashboardDetails, DashboardListItem} from 'sentry/views/dashboards/types';
6161
import {PREBUILT_DASHBOARDS} from 'sentry/views/dashboards/utils/prebuiltConfigs';
62+
import {TopBar} from 'sentry/views/navigation/topBar';
63+
import {useHasPageFrameFeature} from 'sentry/views/navigation/useHasPageFrameFeature';
6264
import RouteError from 'sentry/views/routeError';
6365

6466
import DashboardGrid from './dashboardGrid';
@@ -162,6 +164,7 @@ function ManageDashboards() {
162164
const navigate = useNavigate();
163165
const location = useLocation();
164166
const api = useApi();
167+
const hasPageFrameFeature = useHasPageFrameFeature();
165168
const dashboardGridRef = useRef<HTMLDivElement>(null);
166169
const hasPrebuiltDashboards = organization.features.includes(
167170
'dashboards-prebuilt-insights-dashboards'
@@ -645,7 +648,13 @@ function ManageDashboards() {
645648
</TemplateSwitch>
646649
)}
647650

648-
<FeedbackButton />
651+
{hasPageFrameFeature ? (
652+
<TopBar.Slot name="feedback">
653+
<FeedbackButton>{null}</FeedbackButton>
654+
</TopBar.Slot>
655+
) : (
656+
<FeedbackButton />
657+
)}
649658
<Feature features={['dashboards-ai-generate']}>
650659
{({hasFeature: hasAiGenerate}) =>
651660
hasAiGenerate && areAiFeaturesAllowed ? (

static/app/views/detectors/components/monitorFeedbackButton.tsx

Lines changed: 21 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,29 @@
11
import {FeedbackButton} from 'sentry/components/feedbackButton/feedbackButton';
22
import {t} from 'sentry/locale';
3+
import {TopBar} from 'sentry/views/navigation/topBar';
4+
import {useHasPageFrameFeature} from 'sentry/views/navigation/useHasPageFrameFeature';
5+
6+
const monitorFeedbackOptions = {
7+
messagePlaceholder: t('How can we improve the monitor experience?'),
8+
tags: {
9+
['feedback.source']: 'monitors',
10+
['feedback.owner']: 'aci',
11+
},
12+
};
313

414
export function MonitorFeedbackButton() {
15+
const hasPageFrameFeature = useHasPageFrameFeature();
16+
17+
if (hasPageFrameFeature) {
18+
return (
19+
<TopBar.Slot name="feedback">
20+
<FeedbackButton feedbackOptions={monitorFeedbackOptions}>{null}</FeedbackButton>
21+
</TopBar.Slot>
22+
);
23+
}
24+
525
return (
6-
<FeedbackButton
7-
size="sm"
8-
feedbackOptions={{
9-
messagePlaceholder: t('How can we improve the monitor experience?'),
10-
tags: {
11-
['feedback.source']: 'monitors',
12-
['feedback.owner']: 'aci',
13-
},
14-
}}
15-
>
26+
<FeedbackButton size="sm" feedbackOptions={monitorFeedbackOptions}>
1627
{t('Feedback')}
1728
</FeedbackButton>
1829
);

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

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,8 @@ import {
1616
} from 'sentry/views/explore/errors/body';
1717
import {ErrorsFilterSection} from 'sentry/views/explore/errors/filterContent';
1818
import {useControlSectionExpanded} from 'sentry/views/explore/hooks/useControlSectionExpanded';
19+
import {TopBar} from 'sentry/views/navigation/topBar';
20+
import {useHasPageFrameFeature} from 'sentry/views/navigation/useHasPageFrameFeature';
1921

2022
export default function ErrorsContent() {
2123
const organization = useOrganization();
@@ -37,6 +39,7 @@ export default function ErrorsContent() {
3739
}
3840

3941
function ErrorsHeader() {
42+
const hasPageFrameFeature = useHasPageFrameFeature();
4043
return (
4144
<Layout.Header unified>
4245
<Layout.HeaderContent unified>
@@ -45,7 +48,13 @@ function ErrorsHeader() {
4548
</Layout.Title>
4649
</Layout.HeaderContent>
4750
<Layout.HeaderActions>
48-
<FeedbackButton />
51+
{hasPageFrameFeature ? (
52+
<TopBar.Slot name="feedback">
53+
<FeedbackButton>{null}</FeedbackButton>
54+
</TopBar.Slot>
55+
) : (
56+
<FeedbackButton />
57+
)}
4958
</Layout.HeaderActions>
5059
</Layout.Header>
5160
);

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

Lines changed: 20 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,8 @@ import {
3333
} from 'sentry/views/explore/queryParams/context';
3434
import {TraceItemDataset} from 'sentry/views/explore/types';
3535
import {useOnboardingProject} from 'sentry/views/insights/common/queries/useOnboardingProject';
36+
import {TopBar} from 'sentry/views/navigation/topBar';
37+
import {useHasPageFrameFeature} from 'sentry/views/navigation/useHasPageFrameFeature';
3638

3739
export default function LogsContent() {
3840
const organization = useOrganization();
@@ -93,12 +95,21 @@ export default function LogsContent() {
9395
);
9496
}
9597

98+
const logsFeedbackOptions = {
99+
messagePlaceholder: t('How can we make logs work better for you?'),
100+
tags: {
101+
['feedback.source']: 'logs-listing',
102+
['feedback.owner']: 'performance',
103+
},
104+
};
105+
96106
function LogsHeader() {
97107
const pageId = useQueryParamsId();
98108
const title = useQueryParamsTitle();
99109
const organization = useOrganization();
100110
const {data: savedQuery} = useGetSavedQuery(pageId);
101111
const onboardingProject = useOnboardingProject({property: 'hasLogs'});
112+
const hasPageFrameFeature = useHasPageFrameFeature();
102113

103114
const hasSavedQueryTitle =
104115
defined(pageId) && defined(savedQuery) && savedQuery.name.length > 0;
@@ -120,15 +131,15 @@ function LogsHeader() {
120131
</Layout.HeaderContent>
121132
<Layout.HeaderActions>
122133
<Grid flow="column" align="center" gap="md">
123-
<FeedbackButton
124-
feedbackOptions={{
125-
messagePlaceholder: t('How can we make logs work better for you?'),
126-
tags: {
127-
['feedback.source']: 'logs-listing',
128-
['feedback.owner']: 'performance',
129-
},
130-
}}
131-
/>
134+
{hasPageFrameFeature ? (
135+
<TopBar.Slot name="feedback">
136+
<FeedbackButton feedbackOptions={logsFeedbackOptions}>
137+
{null}
138+
</FeedbackButton>
139+
</TopBar.Slot>
140+
) : (
141+
<FeedbackButton feedbackOptions={logsFeedbackOptions} />
142+
)}
132143
{defined(onboardingProject) && <SetupLogsButton />}
133144
</Grid>
134145
</Layout.HeaderActions>

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

Lines changed: 20 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,8 @@ import {
2525
} from 'sentry/views/explore/queryParams/savedQuery';
2626
import {TraceItemDataset} from 'sentry/views/explore/types';
2727
import {useOnboardingProject} from 'sentry/views/insights/common/queries/useOnboardingProject';
28+
import {TopBar} from 'sentry/views/navigation/topBar';
29+
import {useHasPageFrameFeature} from 'sentry/views/navigation/useHasPageFrameFeature';
2830

2931
export default function MetricsContent() {
3032
const organization = useOrganization();
@@ -69,12 +71,21 @@ export default function MetricsContent() {
6971
);
7072
}
7173

74+
const metricsFeedbackOptions = {
75+
messagePlaceholder: t('How can we make metrics work better for you?'),
76+
tags: {
77+
['feedback.source']: 'metrics-listing',
78+
['feedback.owner']: 'performance',
79+
},
80+
};
81+
7282
function MetricsHeader() {
7383
const location = useLocation();
7484
const pageId = getIdFromLocation(location, ID_KEY);
7585
const title = getTitleFromLocation(location, TITLE_KEY);
7686
const organization = useOrganization();
7787
const {data: savedQuery} = useGetSavedQuery(pageId);
88+
const hasPageFrameFeature = useHasPageFrameFeature();
7889

7990
const hasSavedQueryTitle =
8091
defined(pageId) && defined(savedQuery) && savedQuery.name.length > 0;
@@ -97,15 +108,15 @@ function MetricsHeader() {
97108
</Layout.Title>
98109
</Layout.HeaderContent>
99110
<Layout.HeaderActions>
100-
<FeedbackButton
101-
feedbackOptions={{
102-
messagePlaceholder: t('How can we make metrics work better for you?'),
103-
tags: {
104-
['feedback.source']: 'metrics-listing',
105-
['feedback.owner']: 'performance',
106-
},
107-
}}
108-
/>
111+
{hasPageFrameFeature ? (
112+
<TopBar.Slot name="feedback">
113+
<FeedbackButton feedbackOptions={metricsFeedbackOptions}>
114+
{null}
115+
</FeedbackButton>
116+
</TopBar.Slot>
117+
) : (
118+
<FeedbackButton feedbackOptions={metricsFeedbackOptions} />
119+
)}
109120
</Layout.HeaderActions>
110121
</Layout.Header>
111122
);

static/app/views/explore/multiQueryMode/index.tsx

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,8 @@ import {useGetSavedQuery} from 'sentry/views/explore/hooks/useGetSavedQueries';
1616
import {MultiQueryModeContent} from 'sentry/views/explore/multiQueryMode/content';
1717
import {SavedQueryEditMenu} from 'sentry/views/explore/savedQueryEditMenu';
1818
import {StarSavedQueryButton} from 'sentry/views/explore/starSavedQueryButton';
19+
import {TopBar} from 'sentry/views/navigation/topBar';
20+
import {useHasPageFrameFeature} from 'sentry/views/navigation/useHasPageFrameFeature';
1921
import {makeTracesPathname} from 'sentry/views/traces/pathnames';
2022

2123
export default function MultiQueryMode() {
@@ -25,6 +27,7 @@ export default function MultiQueryMode() {
2527

2628
const id = getIdFromLocation(location);
2729
const {data: savedQuery} = useGetSavedQuery(id);
30+
const hasPageFrameFeature = useHasPageFrameFeature();
2831

2932
return (
3033
<Feature
@@ -58,7 +61,13 @@ export default function MultiQueryMode() {
5861
<Grid flow="column" align="center" gap="md">
5962
<StarSavedQueryButton />
6063
{defined(id) && savedQuery?.isPrebuilt === false && <SavedQueryEditMenu />}
61-
<FeedbackButton />
64+
{hasPageFrameFeature ? (
65+
<TopBar.Slot name="feedback">
66+
<FeedbackButton>{null}</FeedbackButton>
67+
</TopBar.Slot>
68+
) : (
69+
<FeedbackButton />
70+
)}
6271
</Grid>
6372
</Layout.HeaderActions>
6473
</Layout.Header>

0 commit comments

Comments
 (0)