Skip to content

Commit a46d84c

Browse files
committed
breadcrumbs: add breadcrumb events
1 parent 7bfb714 commit a46d84c

File tree

7 files changed

+45
-39
lines changed

7 files changed

+45
-39
lines changed

static/app/components/breadcrumbs.stories.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ export default Storybook.story('Breadcrumbs', story => {
1515
<Breadcrumbs
1616
crumbs={[
1717
{label: 'Organization', to: '/organizations/sentry/'},
18-
{label: 'Projects', to: '/organizations/sentry/projects/'},
18+
{label: 'Projects'},
1919
{
2020
label: 'Project Settings',
2121
to: '/settings/projects/javascript/',

static/app/components/breadcrumbs.tsx

Lines changed: 20 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -3,22 +3,17 @@ import {Fragment} from 'react';
33
import {Flex} from '@sentry/scraps/layout';
44
import {Text} from '@sentry/scraps/text';
55

6-
import {Chevron} from 'sentry/components/chevron';
76
import type {LinkProps} from 'sentry/components/core/link';
87
import {Link} from 'sentry/components/core/link';
98
import GlobalSelectionLink from 'sentry/components/globalSelectionLink';
9+
import {IconChevron} from 'sentry/icons';
10+
import {trackAnalytics} from 'sentry/utils/analytics';
1011

1112
export interface Crumb {
1213
/**
1314
* Label of the crumb
1415
*/
15-
label: React.ReactNode;
16-
17-
/**
18-
* Component will try to come up with unique key, but you can provide your own
19-
* (used when mapping over crumbs)
20-
*/
21-
key?: string;
16+
label: NonNullable<React.ReactNode>;
2217

2318
/**
2419
* It will keep the page filter values (projects, environments, time) in the
@@ -45,6 +40,7 @@ export function Breadcrumbs({crumbs, ...props}: BreadcrumbsProps) {
4540
}
4641

4742
if (crumbs[crumbs.length - 1]?.to) {
43+
// We should not be mutating the crumbs
4844
crumbs[crumbs.length - 1]!.to = null;
4945
}
5046

@@ -53,8 +49,8 @@ export function Breadcrumbs({crumbs, ...props}: BreadcrumbsProps) {
5349
gap="xs"
5450
align="center"
5551
padding="md 0"
56-
{...props}
5752
data-test-id="breadcrumb-list"
53+
{...props}
5854
>
5955
{crumbs.map((crumb, index) => {
6056
return (
@@ -63,7 +59,9 @@ export function Breadcrumbs({crumbs, ...props}: BreadcrumbsProps) {
6359
crumb={crumb}
6460
variant={index === crumbs.length - 1 ? 'primary' : 'muted'}
6561
/>
66-
{index < crumbs.length - 1 ? <BreadcumbChevron /> : null}
62+
{index < crumbs.length - 1 ? (
63+
<IconChevron size="xs" direction="right" color="subText" />
64+
) : null}
6765
</Fragment>
6866
);
6967
})}
@@ -77,30 +75,29 @@ interface BreadCrumbItemProps {
7775
}
7876

7977
function BreadCrumbItem(props: BreadCrumbItemProps) {
78+
function onBreadcrumbLinkClick() {
79+
if (props.crumb.to) {
80+
trackAnalytics('breadcrumbs.link.clicked', {organization: null});
81+
}
82+
}
83+
8084
if (props.crumb.to) {
8185
return (
8286
<BreadcrumbLink
8387
to={props.crumb.to}
8488
preservePageFilters={props.crumb.preservePageFilters}
8589
data-test-id="breadcrumb-link"
90+
onClick={onBreadcrumbLinkClick}
8691
>
87-
<Text as="span" variant="muted">
88-
{props.crumb.label}
89-
</Text>
92+
<Text variant={props.variant}>{props.crumb.label}</Text>
9093
</BreadcrumbLink>
9194
);
9295
}
93-
return (
94-
<Flex data-test-id="breadcrumb-item" maxWidth="400px" align="center">
95-
<Text as="span" ellipsis variant={props.variant}>
96-
{props.crumb.label}
97-
</Text>
98-
</Flex>
99-
);
96+
97+
return <Text variant={props.variant}>{props.crumb.label}</Text>;
10098
}
10199

102-
interface BreadcrumbLinkProps {
103-
to: LinkProps['to'];
100+
interface BreadcrumbLinkProps extends LinkProps {
104101
children?: React.ReactNode;
105102
preservePageFilters?: boolean;
106103
}
@@ -109,15 +106,6 @@ function BreadcrumbLink(props: BreadcrumbLinkProps) {
109106
if (props.preservePageFilters) {
110107
return <GlobalSelectionLink {...props} />;
111108
}
112-
return <Link {...props} />;
113-
}
114109

115-
function BreadcumbChevron() {
116-
return (
117-
<Text variant="muted">
118-
<Flex flexShrink={0} align="center">
119-
<Chevron direction="right" color="subText" />
120-
</Flex>
121-
</Text>
122-
);
110+
return <Link {...props} />;
123111
}

static/app/utils/analytics.tsx

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,8 @@ import {
4040

4141
import type {AgentMonitoringEventParameters} from './analytics/agentMonitoringAnalyticsEvents';
4242
import {agentMonitoringEventMap} from './analytics/agentMonitoringAnalyticsEvents';
43+
import type {BreadcrumbsAnalyticsEventParameters} from './analytics/breadcrumbsAnalyticsEvents';
44+
import {breadcrumbsAnalyticsEventMap} from './analytics/breadcrumbsAnalyticsEvents';
4345
import type {CoreUIEventParameters} from './analytics/coreuiAnalyticsEvents';
4446
import {coreUIEventMap} from './analytics/coreuiAnalyticsEvents';
4547
import type {DashboardsEventParameters} from './analytics/dashboardsAnalyticsEvents';
@@ -98,6 +100,7 @@ interface EventParameters
98100
extends GrowthEventParameters,
99101
AgentMonitoringEventParameters,
100102
AlertsEventParameters,
103+
BreadcrumbsAnalyticsEventParameters,
101104
CoreUIEventParameters,
102105
DashboardsEventParameters,
103106
DiscoverEventParameters,
@@ -135,6 +138,7 @@ interface EventParameters
135138
const allEventMap: Record<string, string | null> = {
136139
...agentMonitoringEventMap,
137140
...alertsEventMap,
141+
...breadcrumbsAnalyticsEventMap,
138142
...coreUIEventMap,
139143
...dashboardsEventMap,
140144
...discoverEventMap,
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
export type BreadcrumbsAnalyticsEventParameters = {
2+
'breadcrumbs.link.clicked': {organization: null};
3+
'breadcrumbs.menu.clicked': {organization: null};
4+
};
5+
6+
export type BreadcrumbsAnalyticsKey = keyof BreadcrumbsAnalyticsEventParameters;
7+
8+
export const breadcrumbsAnalyticsEventMap: Record<
9+
BreadcrumbsAnalyticsKey,
10+
string | null
11+
> = {
12+
'breadcrumbs.link.clicked': 'Breadcrumbs: Link Clicked',
13+
'breadcrumbs.menu.clicked': 'Breadcrumbs: Menu Clicked',
14+
};

static/app/views/discover/landing.tsx

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -187,12 +187,10 @@ function DiscoverLanding() {
187187
<Breadcrumbs
188188
crumbs={[
189189
{
190-
key: 'discover-homepage',
191190
label: t('Discover'),
192191
to: getDiscoverLandingUrl(organization),
193192
},
194193
{
195-
key: 'discover-saved-queries',
196194
label: t('Saved Queries'),
197195
},
198196
]}

static/app/views/preprod/buildComparison/header/buildCompareHeaderContent.tsx

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -37,14 +37,14 @@ export function BuildCompareHeaderContent(props: BuildCompareHeaderContentProps)
3737
const breadcrumbs: Crumb[] = [
3838
{
3939
to: '#',
40-
label: 'Releases',
40+
label: t('Releases'),
4141
},
4242
{
4343
to: `/organizations/${organization.slug}/preprod/${projectId}/${buildDetails.id}/`,
44-
label: buildDetails.app_info.version,
44+
label: buildDetails.app_info.version ?? t('Build Version'),
4545
},
4646
{
47-
label: 'Compare',
47+
label: t('Compare'),
4848
},
4949
];
5050

static/app/views/replays/detail/header/replayDetailsPageBreadcrumbs.tsx

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,9 @@ export default function ReplayDetailsPageBreadcrumbs({readerResult}: Props) {
6969
},
7070
label: project ? (
7171
<ProjectBadge disableLink project={project} avatarSize={16} />
72-
) : null,
72+
) : (
73+
t('Project')
74+
),
7375
};
7476

7577
const replayCrumb = {

0 commit comments

Comments
 (0)