diff --git a/src/components/dispatch/calltracking.tsx b/src/components/dispatch/calltracking.tsx index de1ac80..3d7eacb 100644 --- a/src/components/dispatch/calltracking.tsx +++ b/src/components/dispatch/calltracking.tsx @@ -111,6 +111,14 @@ export const CallTrackingTable: React.FC = ({ const [closingCallId, setClosingCallId] = React.useState(null); const [openMenuToken, setOpenMenuToken] = React.useState(null); const previousOpenCallIdRef = React.useRef(null); + // HeroUI/react-aria's Popover can spuriously fire onOpenChange(false) a few + // milliseconds after opening, with no user interaction (a known upstream + // focus/blur-tracking race — see adobe/react-spectrum#4533). Real users + // never dismiss a menu that fast, so ignore closes inside this window + // unless they came from an actual selection (onAction). + const TEAM_STATUS_MENU_CLOSE_GUARD_MS = 150; + const teamStatusMenuOpenedAtRef = React.useRef(0); + const teamStatusMenuSelectedRef = React.useRef(false); const { notesTexts, setNotesTexts, @@ -437,9 +445,15 @@ export const CallTrackingTable: React.FC = ({ onOpenChange={(isOpen) => { if (isOpen) { if (isResolvedCall && !showResolvedCalls) return; + teamStatusMenuOpenedAtRef.current = Date.now(); setOpenMenuToken(`team-status:${call.id}:${team}`); return; } + const selected = teamStatusMenuSelectedRef.current; + teamStatusMenuSelectedRef.current = false; + if (!selected && Date.now() - teamStatusMenuOpenedAtRef.current < TEAM_STATUS_MENU_CLOSE_GUARD_MS) { + return; + } setOpenMenuToken((current) => current === `team-status:${call.id}:${team}` ? null : current ); @@ -456,7 +470,10 @@ export const CallTrackingTable: React.FC = ({ handleTeamStatusChange(call.id, team, key as string)} + onAction={(key) => { + teamStatusMenuSelectedRef.current = true; + handleTeamStatusChange(call.id, team, key as string); + }} > {statusOptions.map((status: string) => ( {status}