From 89ee151423aecec314018d6c31e4dc1920406358 Mon Sep 17 00:00:00 2001 From: Richard Roggenkemper Date: Mon, 13 Jul 2026 13:49:19 -0400 Subject: [PATCH] fix(issue-stream): Dismiss the Recommended sort badge after a sort is chosen The new-feature badge on the sort dropdown trigger announcing the Recommended sort default showed whenever the current sort was Recommended, so users who explicitly selected Recommended (or switched away and back) kept seeing an announcement about a default they already knew about, along with "pick a different sort and we'll remember your choice" copy that no longer fit. Show the trigger badge only while no stored sort exists. Any explicit sort choice, including re-selecting Recommended, writes the stored sort and permanently dismisses it. Also hide it on view pages, where sort changes are no longer remembered. The badge on the Recommended option inside the dropdown menu is unchanged. Co-Authored-By: Claude --- .../views/issueList/actions/sortOptions.tsx | 11 +++++++++- static/app/views/issueList/overview.spec.tsx | 21 +++++++++++++++++++ 2 files changed, 31 insertions(+), 1 deletion(-) diff --git a/static/app/views/issueList/actions/sortOptions.tsx b/static/app/views/issueList/actions/sortOptions.tsx index 24a5bd227663..1a9f9dc6f4d6 100644 --- a/static/app/views/issueList/actions/sortOptions.tsx +++ b/static/app/views/issueList/actions/sortOptions.tsx @@ -8,9 +8,11 @@ import type {DropdownButtonProps} from 'sentry/components/dropdownButton'; import {IconSort} from 'sentry/icons/iconSort'; import {t} from 'sentry/locale'; import {useOrganization} from 'sentry/utils/useOrganization'; +import {useParams} from 'sentry/utils/useParams'; import { FOR_REVIEW_QUERIES, getSortLabel, + getStoredIssueSort, IssueSortOptions, } from 'sentry/views/issueList/utils'; @@ -56,9 +58,13 @@ export function IssueListSortOptions({ showIcon = true, }: Props) { const organization = useOrganization(); + const {viewId} = useParams<{viewId?: string}>(); const hasRecommendedSortDefault = organization.features.includes( 'issue-stream-recommended-sort-default' ); + // The trigger badge announces the Recommended default. A stored sort means + // the user has already made an explicit choice, so stop announcing. + const hasChosenSort = getStoredIssueSort(organization.slug) !== null; const hasProgressSort = organization.features.includes('issue-stream-progress-sort') || sort === IssueSortOptions.PROGRESS; @@ -108,7 +114,10 @@ export function IssueListSortOptions({ size={triggerSize} icon={showIcon && } > - {hasRecommendedSortDefault && sortKey === IssueSortOptions.RECOMMENDED ? ( + {hasRecommendedSortDefault && + !hasChosenSort && + !viewId && + sortKey === IssueSortOptions.RECOMMENDED ? ( {triggerProps.children} { const recommendedOption = screen.getByRole('option', {name: /Recommended/}); expect(within(recommendedOption).getByLabelText('new')).toBeInTheDocument(); }); + + it('hides the trigger badge once the user has chosen a sort', async () => { + const featureOrg = OrganizationFixture({ + ...organization, + features: ['issue-stream-recommended-sort-default'], + }); + // An explicitly chosen sort (even Recommended itself) means the user has + // seen the dropdown, so the announcement badge no longer shows + setStoredIssueSort(featureOrg.slug, IssueSortOptions.RECOMMENDED); + render(, {organization: featureOrg, initialRouterConfig}); + + expect( + await screen.findByRole('button', {name: /Recommended/}) + ).toBeInTheDocument(); + expect(screen.queryByLabelText('new')).not.toBeInTheDocument(); + + // The Recommended option inside the dropdown keeps its badge + await userEvent.click(screen.getByRole('button', {name: /Recommended/})); + const recommendedOption = screen.getByRole('option', {name: /Recommended/}); + expect(within(recommendedOption).getByLabelText('new')).toBeInTheDocument(); + }); }); describe('transitionTo', () => {