From 1d69dec0872c3d2d1ca0baea4dfd2d39b02a8af7 Mon Sep 17 00:00:00 2001 From: gsxdsm Date: Sat, 4 Jul 2026 22:01:04 -0700 Subject: [PATCH] FN-7562: fix mobile oversight menu auto-focus opening a second native select popup Fixes the mobile oversight overflow menu rendering two overlapping menus by narrowing auto-focus to actionable button menuitems. - Change the menu-open auto-focus effect to query `button.detail-oversight-menu-item` instead of matching any `.detail-oversight-menu-item` element, since the native level `` triggered its OS option picker, which rendered as a second overlapping menu on top of the custom `role="menu"` popover. - Add regression tests covering: auto-focus landing on the first button menuitem when nudge/stop/explain are available, no fallback focus on the select when oversight is off (level-only state), and confirming the desktop inline select is unaffected. - Update dashboard-guide.md docs to describe the fixed auto-focus behavior. Files changed: docs/dashboard-guide.md | 2 +- packages/dashboard/app/components/TaskDetailModal.tsx | 3 +- .../app/components/__tests__/TaskDetailModal.oversight-mobile.test.tsx | 96 ++++++++++++++++++++++ 3 files changed, 99 insertions(+), 2 deletions(-) Fusion-Task-Id: FN-7562 Fusion-Task-Lineage: f39068f1-811f-4663-ade1-ff020a389ae5 Co-authored-by: Fusion (runfusion.ai) --- docs/dashboard-guide.md | 2 +- .../app/components/TaskDetailModal.tsx | 3 +- .../TaskDetailModal.oversight-mobile.test.tsx | 96 +++++++++++++++++++ 3 files changed, 99 insertions(+), 2 deletions(-) diff --git a/docs/dashboard-guide.md b/docs/dashboard-guide.md index f0b36d9e02..55afafc73b 100644 --- a/docs/dashboard-guide.md +++ b/docs/dashboard-guide.md @@ -201,7 +201,7 @@ Features: - The FN-7517 controls above carry a visible, non-interactive **`"Overseer controls"` group label** (`data-testid="detail-oversight-controls-label"`) so Nudge/Stop/Explain read as an identifiable cluster rather than unlabeled chips; the label is gated by the same `(hasTaskOversightOverride || workflowOversightResolved) && !oversightIsOff` condition as the buttons, so it never renders an empty shell when oversight is Off/unresolved. When **Nudge** is disabled, an always-visible helper line (`data-testid="detail-overseer-nudge-disabled-reason"`) states the reason in-DOM (mirroring the existing hover `title`) instead of relying on a mouse-hover tooltip alone. **Explain** is read-only and non-mutating, so it is never disabled purely because the overseer is inactive — clicking it always opens/closes the panel, which shows the overseer's live state when watching or an informative "not currently watching this task" message otherwise. Nudge's mutating enablement rule (`canNudgeOverseer`, including the human-control suppression cases) and Stop's confirmation dialog are unchanged. -- On mobile (viewport ≤ 768px), the level-select/nudge/stop/explain controls above collapse behind a single compact **"Oversight" overflow-menu button** (`data-testid="detail-oversight-menu-trigger"`, `MoreVertical` icon, `aria-haspopup="menu"`) that opens a `role="menu"` popover (mirroring the existing move-action dropdown pattern) listing the same controls as full-width, comfortably tappable `role="menuitem"` entries with the SAME testids and enablement/visibility rules as the desktop inline controls. The trigger itself is withheld entirely when none of those controls would render (no empty-shell overflow button for the oversight-off + overseer-inactive default). Desktop (>768px) keeps the inline cluster unchanged. +- On mobile (viewport ≤ 768px), the level-select/nudge/stop/explain controls above collapse behind a single compact **"Oversight" overflow-menu button** (`data-testid="detail-oversight-menu-trigger"`, `MoreVertical` icon, `aria-haspopup="menu"`) that opens a `role="menu"` popover (mirroring the existing move-action dropdown pattern) listing the same controls as full-width, comfortably tappable `role="menuitem"` entries with the SAME testids and enablement/visibility rules as the desktop inline controls. The trigger itself is withheld entirely when none of those controls would render (no empty-shell overflow button for the oversight-off + overseer-inactive default). Desktop (>768px) keeps the inline cluster unchanged. Opening the menu presents exactly one surface: menu-open auto-focus lands on the first actionable button menuitem, never the native level `; focusing the ` FIRST (it carries that class too) and focused it. Focusing a + native `