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

@@ -3,6 +3,7 @@ import { useState, useEffect, useCallback } from "react";
import { getErrorMessage } from "@fusion/core";
import { fetchScripts, addScript, removeScript, type ScriptEntry } from "../api";
import type { ToastType } from "../hooks/useToast";
import { useOverlayDismiss } from "../hooks/useOverlayDismiss";
import {
X,
Plus,
@@ -51,6 +52,7 @@ export function ScriptsModal({ isOpen, onClose, addToast, projectId, onRunScript
const [saving, setSaving] = useState(false);
const [deleteConfirmName, setDeleteConfirmName] = useState<string | null>(null);
const [nameError, setNameError] = useState<string | null>(null);
const overlayDismissProps = useOverlayDismiss(onClose);
const loadScripts = useCallback(async () => {
try {
@@ -170,10 +172,9 @@ export function ScriptsModal({ isOpen, onClose, addToast, projectId, onRunScript
}));
return (
<div className="modal-overlay open" onClick={onClose} data-testid="scripts-modal">
<div className="modal-overlay open" {...overlayDismissProps} data-testid="scripts-modal">
<div
className="modal scripts-modal"
onClick={(e) => e.stopPropagation()}
role="dialog"
aria-modal="true"
aria-label="Scripts"