Skip to content

Commit 506b161

Browse files
authored
feature(webapp): Show a v3 deprecation notice in the side bar (#3090)
- If your project is v3, show a v3 deprecation panel in the side menu - If there is an active incident, show the incident panel instead - Links to the Migration guide in the docs - Displays when the side menu is collapsed https://github.com/user-attachments/assets/f8492713-c58b-4f83-bcce-0e85f4a967ef <img width="972" height="694" alt="CleanShot 2026-02-19 at 08 13 59@2x" src="https://github.com/user-attachments/assets/0599dd20-d598-48c6-b83c-208648cee071" />
1 parent 1ec7722 commit 506b161

File tree

2 files changed

+116
-5
lines changed

2 files changed

+116
-5
lines changed

apps/webapp/app/components/navigation/SideMenu.tsx

Lines changed: 105 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,13 +2,15 @@ import {
22
AdjustmentsHorizontalIcon,
33
ArrowPathRoundedSquareIcon,
44
ArrowRightOnRectangleIcon,
5+
ArrowTopRightOnSquareIcon,
56
BeakerIcon,
67
BellAlertIcon,
78
ChartBarIcon,
89
ChevronRightIcon,
910
ClockIcon,
1011
Cog8ToothIcon,
1112
CogIcon,
13+
ExclamationTriangleIcon,
1214
FolderIcon,
1315
FolderOpenIcon,
1416
GlobeAmericasIcon,
@@ -45,7 +47,7 @@ import { useHasAdminAccess } from "~/hooks/useUser";
4547
import { type UserWithDashboardPreferences } from "~/models/user.server";
4648
import { useCurrentPlan } from "~/routes/_app.orgs.$organizationSlug/route";
4749
import { type FeedbackType } from "~/routes/resources.feedback";
48-
import { IncidentStatusPanel } from "~/routes/resources.incidents";
50+
import { IncidentStatusPanel, useIncidentStatus } from "~/routes/resources.incidents";
4951
import { cn } from "~/utils/cn";
5052
import {
5153
accountPath,
@@ -164,6 +166,8 @@ export function SideMenu({
164166
const isAdmin = useHasAdminAccess();
165167
const { isManagedCloud } = useFeatures();
166168
const featureFlags = useFeatureFlags();
169+
const incidentStatus = useIncidentStatus();
170+
const isV3Project = project.engine === "V1";
167171

168172
const persistSideMenuPreferences = useCallback(
169173
(data: {
@@ -598,7 +602,18 @@ export function SideMenu({
598602
</div>
599603
</div>
600604
<div>
601-
<IncidentStatusPanel isCollapsed={isCollapsed} />
605+
<IncidentStatusPanel
606+
isCollapsed={isCollapsed}
607+
title={incidentStatus.title}
608+
hasIncident={incidentStatus.hasIncident}
609+
isManagedCloud={incidentStatus.isManagedCloud}
610+
/>
611+
<V3DeprecationPanel
612+
isCollapsed={isCollapsed}
613+
isV3={isV3Project}
614+
hasIncident={incidentStatus.hasIncident}
615+
isManagedCloud={incidentStatus.isManagedCloud}
616+
/>
602617
<motion.div
603618
layout
604619
transition={{ duration: 0.2, ease: "easeInOut" }}
@@ -623,6 +638,94 @@ export function SideMenu({
623638
);
624639
}
625640

641+
function V3DeprecationPanel({
642+
isCollapsed,
643+
isV3,
644+
hasIncident,
645+
isManagedCloud,
646+
}: {
647+
isCollapsed: boolean;
648+
isV3: boolean;
649+
hasIncident: boolean;
650+
isManagedCloud: boolean;
651+
}) {
652+
if (!isManagedCloud || !isV3 || hasIncident) {
653+
return null;
654+
}
655+
656+
return (
657+
<Popover>
658+
<div className="p-1">
659+
<motion.div
660+
initial={false}
661+
animate={{
662+
height: isCollapsed ? 0 : "auto",
663+
opacity: isCollapsed ? 0 : 1,
664+
}}
665+
transition={{ duration: 0.15 }}
666+
className="overflow-hidden"
667+
>
668+
<V3DeprecationContent />
669+
</motion.div>
670+
671+
<motion.div
672+
initial={false}
673+
animate={{
674+
height: isCollapsed ? "auto" : 0,
675+
opacity: isCollapsed ? 1 : 0,
676+
}}
677+
transition={{ duration: 0.15 }}
678+
className="overflow-hidden"
679+
>
680+
<SimpleTooltip
681+
button={
682+
<PopoverTrigger className="flex !h-8 w-full items-center justify-center rounded border border-amber-500/30 bg-amber-500/15 transition-colors hover:border-amber-500/50 hover:bg-amber-500/25">
683+
<ExclamationTriangleIcon className="size-5 text-amber-400" />
684+
</PopoverTrigger>
685+
}
686+
content="V3 deprecation warning"
687+
side="right"
688+
sideOffset={8}
689+
disableHoverableContent
690+
asChild
691+
/>
692+
</motion.div>
693+
</div>
694+
<PopoverContent side="right" sideOffset={8} align="start" className="w-52 !min-w-0 p-0">
695+
<V3DeprecationContent />
696+
</PopoverContent>
697+
</Popover>
698+
);
699+
}
700+
701+
function V3DeprecationContent() {
702+
return (
703+
<div className="flex flex-col gap-2 rounded border border-amber-500/30 bg-amber-500/10 p-2 pt-1.5">
704+
<div className="flex items-center gap-1 border-b border-amber-500/30 pb-1">
705+
<ExclamationTriangleIcon className="size-4 text-amber-400" />
706+
<Paragraph variant="small/bright" className="text-amber-300">
707+
V3 deprecation warning
708+
</Paragraph>
709+
</div>
710+
<Paragraph variant="extra-small/bright" className="text-amber-300">
711+
This is a v3 project. V3 deploys will stop working on 1 April 2026. Full shutdown is 1 July
712+
2026 where all v3 runs will stop executing. Migrate to v4 to avoid downtime.
713+
</Paragraph>
714+
<LinkButton
715+
variant="secondary/small"
716+
to="https://trigger.dev/docs/migrating-from-v3"
717+
target="_blank"
718+
fullWidth
719+
TrailingIcon={ArrowTopRightOnSquareIcon}
720+
trailingIconClassName="text-amber-300"
721+
className="border-amber-500/30 bg-amber-500/15 hover:!border-amber-500/50 hover:!bg-amber-500/25"
722+
>
723+
<span className="text-amber-300">View migration guide</span>
724+
</LinkButton>
725+
</div>
726+
);
727+
}
728+
626729
function ProjectSelector({
627730
project,
628731
organization,

apps/webapp/app/routes/resources.incidents.tsx

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -70,9 +70,17 @@ export function useIncidentStatus() {
7070
};
7171
}
7272

73-
export function IncidentStatusPanel({ isCollapsed = false }: { isCollapsed?: boolean }) {
74-
const { title, hasIncident, isManagedCloud } = useIncidentStatus();
75-
73+
export function IncidentStatusPanel({
74+
isCollapsed = false,
75+
title,
76+
hasIncident,
77+
isManagedCloud,
78+
}: {
79+
isCollapsed?: boolean;
80+
title: string | null;
81+
hasIncident: boolean;
82+
isManagedCloud: boolean;
83+
}) {
7684
if (!isManagedCloud || !hasIncident) {
7785
return null;
7886
}

0 commit comments

Comments
 (0)