From 3bc43ae7e267fbc0922c035f324de205f6cbea50 Mon Sep 17 00:00:00 2001 From: Mahmoud Mabrouk Date: Wed, 17 Jun 2026 20:24:55 +0200 Subject: [PATCH] fix(frontend): cap sidebar banner queue --- .../components/SidebarBanners/state/atoms.ts | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/web/oss/src/components/SidebarBanners/state/atoms.ts b/web/oss/src/components/SidebarBanners/state/atoms.ts index 6724400836..8697bd6e11 100644 --- a/web/oss/src/components/SidebarBanners/state/atoms.ts +++ b/web/oss/src/components/SidebarBanners/state/atoms.ts @@ -19,6 +19,13 @@ export const PRIORITY_ORDER: Record = { trial: 3, // Lowest priority - show after other banners are dismissed } +/** + * Maximum number of dismissible sidebar banners a user should have to clear. + * Apply this before dismissal filtering so older changelog entries do not + * backfill the sidebar after each close. + */ +export const MAX_DISMISSIBLE_SIDEBAR_BANNERS = 2 + /** * Persisted atom for dismissed banner IDs. * Uses localStorage to remember which banners the user has dismissed. @@ -107,8 +114,17 @@ export const activeBannersAtom = atom((get) => { export const visibleBannersAtom = atom((get) => { const allBanners = get(activeBannersAtom) const dismissedIds = get(dismissedBannerIdsAtom) + const sortedBanners = [...allBanners].sort( + (a, b) => PRIORITY_ORDER[a.type] - PRIORITY_ORDER[b.type], + ) + + const cappedDismissibleBanners = sortedBanners + .filter((banner) => banner.dismissible) + .slice(0, MAX_DISMISSIBLE_SIDEBAR_BANNERS) + + const nonDismissibleBanners = sortedBanners.filter((banner) => !banner.dismissible) - return allBanners + return [...cappedDismissibleBanners, ...nonDismissibleBanners] .filter((banner) => !dismissedIds.includes(banner.id)) .sort((a, b) => PRIORITY_ORDER[a.type] - PRIORITY_ORDER[b.type]) })