fix(dashboard): no resize-drag dismiss across all resizable modals + Claude CLI in Authenticated group

When a user drags the native CSS resize grip from inside a modal and
releases the mouse over the overlay, the synthesised click event
targets the common ancestor (the overlay) — fooling the existing
e.target === e.currentTarget dismiss check. Audited every modal with
`resize: both` and switched them to a shared mousedown→mouseup tracking
pattern (new useOverlayDismiss hook) so dismiss only fires when both
events land on the overlay.

Modals fixed: TaskDetail, Settings, FileBrowser, GitHubImport,
GitManager, ScheduledTasks, Scripts, WorkflowStepManager. (Terminal
and AgentDetail were already fixed in 95566795e; PlanningModeModal
already had the right pattern inline.)

Also: in Settings → Authentication, the "Anthropic via Claude CLI"
card now lives inside the Authenticated group when authenticated and
the Available group otherwise, instead of floating at the top.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
gsxdsm
2026-04-27 19:36:24 -07:00
parent 95566795ea
commit b196ab42b4
9 changed files with 87 additions and 44 deletions

View File

@@ -5,6 +5,7 @@ import { getErrorMessage } from "@fusion/core";
import type { ToastType } from "../hooks/useToast";
import { useConfirm } from "../hooks/useConfirm";
import { useModalResizePersist } from "../hooks/useModalResizePersist";
import { useOverlayDismiss } from "../hooks/useOverlayDismiss";
import type {
GitStatus,
GitCommit,
@@ -179,6 +180,7 @@ export function GitManagerModal({ isOpen, onClose, tasks: _tasks, addToast, proj
const [sectionError, setSectionError] = useState<string | null>(null);
const modalRef = useRef<HTMLDivElement>(null);
useModalResizePersist(modalRef, isOpen, "fusion:git-modal-size");
const overlayDismissProps = useOverlayDismiss(onClose);
const copyToClipboard = useCopyToClipboard(addToast);
// ── Status state
@@ -738,7 +740,7 @@ export function GitManagerModal({ isOpen, onClose, tasks: _tasks, addToast, proj
if (!isOpen) return null;
return (
<div className="modal-overlay open" onClick={(e) => e.target === e.currentTarget && onClose()} role="dialog" aria-modal="true">
<div className="modal-overlay open" {...overlayDismissProps} role="dialog" aria-modal="true">
<div className="modal gm-modal" ref={modalRef}>
<div className="modal-header">
<h3>