From 47e71c4753b362b255ae96e6738e2196aa54e32f Mon Sep 17 00:00:00 2001 From: chihlasm Date: Sat, 4 Apr 2026 00:43:48 +0000 Subject: [PATCH] fix: opaque overflow menu, add Update button to cockpit and assistant headers The IncidentHeader overflow menu was see-through due to bg-elevated on bg-card. Switched to bg-card with shadow-xl and fixed-scrim dismiss pattern matching production FlowPilotSessionPage. Replaced unicode ellipsis with MoreHorizontal icon + aria-label. Added Update button (StatusUpdateModal) to IncidentHeader and FlowPilotPage header bar for feature parity with production. Co-Authored-By: Claude Opus 4.6 (1M context) --- .../components/assistant/IncidentHeader.tsx | 81 ++++++++++--------- frontend/src/pages/CockpitPage.tsx | 1 + frontend/src/pages/FlowPilotPage.tsx | 28 ++++++- 3 files changed, 71 insertions(+), 39 deletions(-) diff --git a/frontend/src/components/assistant/IncidentHeader.tsx b/frontend/src/components/assistant/IncidentHeader.tsx index 4a84d2be..023ffd55 100644 --- a/frontend/src/components/assistant/IncidentHeader.tsx +++ b/frontend/src/components/assistant/IncidentHeader.tsx @@ -1,5 +1,5 @@ import { useState, useRef, useEffect } from 'react' -import { Pencil, X, Check, ExternalLink, Pause, XCircle, Link2 } from 'lucide-react' +import { Pencil, X, Check, ExternalLink, Pause, XCircle, Link2, MoreHorizontal, FileText } from 'lucide-react' import { cn } from '@/lib/utils' import { toast } from '@/lib/toast' import type { TriageMeta } from '@/types/ai-session' @@ -9,6 +9,7 @@ interface IncidentHeaderProps { psaTicketId: string | null onFieldSave: (field: keyof TriageMeta, value: string) => void onResolve: () => void + onStatusUpdate?: () => void onPause?: () => void onClose?: () => void } @@ -98,22 +99,14 @@ function HeaderField({ label, value, placeholder, onSave, isHypothesis }: Header function OverflowMenu({ onPause, onClose }: { onPause?: () => void; onClose?: () => void }) { const [open, setOpen] = useState(false) - const menuRef = useRef(null) useEffect(() => { if (!open) return - const handleClickOutside = (e: MouseEvent) => { - if (menuRef.current && !menuRef.current.contains(e.target as Node)) setOpen(false) - } const handleEsc = (e: KeyboardEvent) => { if (e.key === 'Escape') setOpen(false) } - document.addEventListener('mousedown', handleClickOutside) document.addEventListener('keydown', handleEsc) - return () => { - document.removeEventListener('mousedown', handleClickOutside) - document.removeEventListener('keydown', handleEsc) - } + return () => { document.removeEventListener('keydown', handleEsc) } }, [open]) const handleCopyLink = () => { @@ -123,41 +116,45 @@ function OverflowMenu({ onPause, onClose }: { onPause?: () => void; onClose?: () } return ( -
+
{open && ( -
- {onPause && ( + <> +
setOpen(false)} /> +
+ {onPause && ( + + )} - )} - - {onClose && ( - - )} -
+ {onClose && ( + + )} +
+ )}
) @@ -168,6 +165,7 @@ export function IncidentHeader({ psaTicketId, onFieldSave, onResolve, + onStatusUpdate, onPause, onClose, }: IncidentHeaderProps) { @@ -215,6 +213,15 @@ export function IncidentHeader({ > Resolve + {onStatusUpdate && ( + + )}
diff --git a/frontend/src/pages/CockpitPage.tsx b/frontend/src/pages/CockpitPage.tsx index ed954d05..86c8fea4 100644 --- a/frontend/src/pages/CockpitPage.tsx +++ b/frontend/src/pages/CockpitPage.tsx @@ -273,6 +273,7 @@ export default function CockpitPage() { psaTicketId={psaTicketId} onFieldSave={handleTriageFieldSave} onResolve={() => session.setShowConclude(true)} + onStatusUpdate={session.messages.length >= 2 ? () => session.setShowStatusUpdate(true) : undefined} onClose={() => session.setShowConclude(true)} /> {/* View toggle bar — desktop only (mobile has it in the header) */} diff --git a/frontend/src/pages/FlowPilotPage.tsx b/frontend/src/pages/FlowPilotPage.tsx index f1b97156..1790b3d9 100644 --- a/frontend/src/pages/FlowPilotPage.tsx +++ b/frontend/src/pages/FlowPilotPage.tsx @@ -128,8 +128,32 @@ export default function FlowPilotPage() { {session.activeChatId ? ( <> - {/* Desktop view toggle bar */} -
+ {/* Desktop view toggle + action bar */} +
+
+ {session.messages.length >= 2 && ( + <> + + + + )} +