Skip to content

Commit 4a058cc

Browse files
authored
feat(aci): Add onboarding banner (#112737)
1 parent 22abf26 commit 4a058cc

File tree

12 files changed

+288
-224
lines changed

12 files changed

+288
-224
lines changed
Lines changed: 4 additions & 181 deletions
Original file line numberDiff line numberDiff line change
@@ -1,196 +1,19 @@
1-
import {useCallback} from 'react';
2-
import {css, type Theme} from '@emotion/react';
3-
4-
import monitorsTourAlertsImage from 'sentry-images/spot/monitors-tour-alerts.svg';
5-
import monitorsTourConnectingImage from 'sentry-images/spot/monitors-tour-connecting.svg';
6-
import monitorsTourIntroImage from 'sentry-images/spot/monitors-tour-intro.svg';
7-
import monitorsTourMonitorsImage from 'sentry-images/spot/monitors-tour-monitors.svg';
8-
91
import {Button} from '@sentry/scraps/button';
10-
import {Stack} from '@sentry/scraps/layout';
11-
import {ExternalLink} from '@sentry/scraps/link';
12-
import {Text} from '@sentry/scraps/text';
132

14-
import {openModal} from 'sentry/actionCreators/modal';
15-
import {FeatureShowcase} from 'sentry/components/featureShowcase';
3+
import {openAlertsMonitorsShowcase} from 'sentry/components/workflowEngine/ui/alertsMonitorsShowcase';
164
import {IconInfo} from 'sentry/icons';
17-
import {t, tct} from 'sentry/locale';
18-
import {trackAnalytics} from 'sentry/utils/analytics';
5+
import {t} from 'sentry/locale';
196
import {useOrganization} from 'sentry/utils/useOrganization';
207

21-
const DOCS_URL = 'https://docs.sentry.io/product/new-monitors-and-alerts/';
22-
238
export function AlertsMonitorsShowcaseButton() {
249
const organization = useOrganization();
2510

26-
const handleClick = useCallback(() => {
27-
trackAnalytics('monitors.onboarding_modal_viewed', {organization, step: 0});
28-
openModal(
29-
deps => (
30-
<FeatureShowcase
31-
{...deps}
32-
onStepChange={step => {
33-
trackAnalytics('monitors.onboarding_modal_viewed', {
34-
organization,
35-
step,
36-
});
37-
}}
38-
>
39-
<FeatureShowcase.Step>
40-
<FeatureShowcase.Image
41-
src={monitorsTourIntroImage}
42-
alt={t('Introducing Monitors and Alerts')}
43-
/>
44-
<FeatureShowcase.StepTitle>
45-
{t('Introducing Monitors & Alerts')}
46-
</FeatureShowcase.StepTitle>
47-
<FeatureShowcase.StepContent>
48-
{t(
49-
'Monitors detect problems and create issues. These issues trigger Alerts to notify your team.'
50-
)}
51-
</FeatureShowcase.StepContent>
52-
<FeatureShowcase.StepActions />
53-
</FeatureShowcase.Step>
54-
<FeatureShowcase.Step>
55-
<FeatureShowcase.Image
56-
src={monitorsTourMonitorsImage}
57-
alt={t('Monitors detect problems and create issues')}
58-
/>
59-
<FeatureShowcase.StepTitle>
60-
{t('Monitors detect problems and create issues')}
61-
</FeatureShowcase.StepTitle>
62-
<FeatureShowcase.StepContent>
63-
<Text>
64-
{t(
65-
'Set conditions across your data and when a threshold is breached, Sentry creates an issue.'
66-
)}
67-
</Text>
68-
<Stack gap="sm">
69-
<Text bold>{t('Types of Monitors:')}</Text>
70-
<ul>
71-
<li>
72-
<Text>
73-
<Text bold as="span">
74-
{t('Metric')}
75-
</Text>
76-
{' — '}
77-
{t('span attributes, logs, custom metrics, and more')}
78-
</Text>
79-
</li>
80-
<li>
81-
<Text>
82-
<Text bold as="span">
83-
{t('Cron')}
84-
</Text>
85-
{' — '}
86-
{t('scheduled, recurring job health')}
87-
</Text>
88-
</li>
89-
<li>
90-
<Text>
91-
<Text bold as="span">
92-
{t('Uptime')}
93-
</Text>
94-
{' — '}
95-
{t('service availability and reliability')}
96-
</Text>
97-
</li>
98-
<li>
99-
<Text>
100-
<Text bold as="span">
101-
{t('Mobile Builds')}
102-
</Text>
103-
{' — '}
104-
{t('build size and regressions')}
105-
</Text>
106-
</li>
107-
<li>
108-
<Text>
109-
<Text bold as="span">
110-
{t('Error')}
111-
</Text>{' '}
112-
{t('(managed by Sentry)')}
113-
{' — '}
114-
{t(
115-
'groups incoming errors into issues based on your project settings'
116-
)}
117-
</Text>
118-
</li>
119-
</ul>
120-
</Stack>
121-
</FeatureShowcase.StepContent>
122-
<FeatureShowcase.StepActions />
123-
</FeatureShowcase.Step>
124-
<FeatureShowcase.Step>
125-
<FeatureShowcase.Image
126-
src={monitorsTourAlertsImage}
127-
alt={t('Alerts notify your team')}
128-
/>
129-
<FeatureShowcase.StepTitle>
130-
{t('Alerts notify your team')}
131-
</FeatureShowcase.StepTitle>
132-
<FeatureShowcase.StepContent>
133-
<Text>
134-
{t(
135-
'Alerts notify your team. Define who gets paged, when, and how — via Slack, email, PagerDuty, and more.'
136-
)}
137-
</Text>
138-
<Text>
139-
{t(
140-
'Scale and connect to many monitors, projects, and issue types. Configure your routing so the right people get notified when it matters.'
141-
)}
142-
</Text>
143-
</FeatureShowcase.StepContent>
144-
<FeatureShowcase.StepActions />
145-
</FeatureShowcase.Step>
146-
<FeatureShowcase.Step>
147-
<FeatureShowcase.Image
148-
src={monitorsTourConnectingImage}
149-
alt={t('Connecting Alerts and Monitors')}
150-
/>
151-
<FeatureShowcase.StepTitle>
152-
{t('Connecting Alerts & Monitors')}
153-
</FeatureShowcase.StepTitle>
154-
<FeatureShowcase.StepContent>
155-
<Text>
156-
{t(
157-
'When creating a Monitor you have the option of setting up a new Alert or connecting to an existing Alert at the same time.'
158-
)}
159-
</Text>
160-
<Text>
161-
{t(
162-
'When creating or editing Alerts you can connect to existing routing without ever touching your Monitor logic.'
163-
)}
164-
</Text>
165-
<Text>
166-
{tct('For more information, [link:read the docs].', {
167-
link: <ExternalLink href={DOCS_URL} />,
168-
})}
169-
</Text>
170-
</FeatureShowcase.StepContent>
171-
<FeatureShowcase.StepActions />
172-
</FeatureShowcase.Step>
173-
</FeatureShowcase>
174-
),
175-
{
176-
modalCss: (theme: Theme) => css`
177-
width: 490px;
178-
179-
[role='document'] {
180-
padding: ${theme.space['2xl']};
181-
padding-top: ${theme.space.lg};
182-
}
183-
`,
184-
}
185-
);
186-
}, [organization]);
187-
18811
return (
18912
<Button
19013
size="sm"
19114
icon={<IconInfo />}
192-
onClick={handleClick}
193-
aria-label={t('Feature tour')}
15+
onClick={() => openAlertsMonitorsShowcase({organization})}
16+
aria-label={t('Monitors and Alerts tour')}
19417
/>
19518
);
19619
}

static/app/components/workflowEngine/layout/list.tsx

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ import {Flex, Stack} from '@sentry/scraps/layout';
33
import * as Layout from 'sentry/components/layouts/thirds';
44
import {NoProjectMessage} from 'sentry/components/noProjectMessage';
55
import {PageHeadingQuestionTooltip} from 'sentry/components/pageHeadingQuestionTooltip';
6+
import {OnboardingBanner} from 'sentry/components/workflowEngine/ui/alertsMonitorsOnboardingBanner';
67
import {useOrganization} from 'sentry/utils/useOrganization';
78
import {TopBar} from 'sentry/views/navigation/topBar';
89
import {useHasPageFrameFeature} from 'sentry/views/navigation/useHasPageFrameFeature';
@@ -49,6 +50,7 @@ export function WorkflowEngineListLayout({
4950
<Layout.Body>
5051
<Layout.Main width="full">
5152
<Flex direction="column" gap="lg">
53+
<OnboardingBanner />
5254
{children}
5355
</Flex>
5456
</Layout.Main>
Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
import {Alert} from '@sentry/scraps/alert';
2+
import {Button} from '@sentry/scraps/button';
3+
import {Flex, Stack} from '@sentry/scraps/layout';
4+
import {ExternalLink} from '@sentry/scraps/link';
5+
import {Text} from '@sentry/scraps/text';
6+
7+
import {usePrompt} from 'sentry/actionCreators/prompts';
8+
import {openAlertsMonitorsShowcase} from 'sentry/components/workflowEngine/ui/alertsMonitorsShowcase';
9+
import {IconClose} from 'sentry/icons';
10+
import {t, tct} from 'sentry/locale';
11+
import {useOrganization} from 'sentry/utils/useOrganization';
12+
import {useUser} from 'sentry/utils/useUser';
13+
14+
const ONBOARDING_CUTOFF_DATE = new Date('2026-05-10T00:00:00Z');
15+
16+
export function OnboardingBanner() {
17+
const organization = useOrganization();
18+
const user = useUser();
19+
20+
// Do not show to users who joined after the GA date, they don't need this info
21+
const dateJoined = new Date(user.dateJoined);
22+
const shouldShowOnboardingBanner = dateJoined < ONBOARDING_CUTOFF_DATE;
23+
24+
const {isLoading, isError, isPromptDismissed, dismissPrompt} = usePrompt({
25+
feature: 'workflow_engine_onboarding_banner',
26+
organization,
27+
options: {enabled: shouldShowOnboardingBanner},
28+
});
29+
30+
if (!shouldShowOnboardingBanner || isLoading || isError || isPromptDismissed) {
31+
return null;
32+
}
33+
34+
return (
35+
<Alert
36+
variant="info"
37+
trailingItems={
38+
<Button
39+
aria-label={t('Dismiss banner')}
40+
icon={<IconClose variant="accent" />}
41+
priority="transparent"
42+
onClick={() => dismissPrompt()}
43+
size="zero"
44+
/>
45+
}
46+
>
47+
<Stack gap="xl">
48+
<Text as="p">
49+
{tct(
50+
'[bold:Alerts are now Monitors & Alerts.] Monitors detect problems and create issues. Issues trigger Alerts to notify your team. Your existing Alert Rules migrated automatically.',
51+
{bold: <strong />}
52+
)}
53+
</Text>
54+
<Flex gap="md" align="center">
55+
<Button
56+
size="xs"
57+
onClick={() => openAlertsMonitorsShowcase({organization})}
58+
aria-label={t('Take a tour')}
59+
>
60+
{t('Take a tour')}
61+
</Button>
62+
<ExternalLink href="https://sentry.zendesk.com/hc/en-us/articles/48882501173915">
63+
{t("Read what's changed")}
64+
</ExternalLink>
65+
</Flex>
66+
</Stack>
67+
</Alert>
68+
);
69+
}

0 commit comments

Comments
 (0)