Skip to content

Escape key doesn't close drawer for case B (Monitoramento map-dot entry) #24

Description

@luandro

Context

PR #15 (ux/15-eventos, commits e4bf68f through 4650b4a) added the Eventos review drawer. Three entry paths open the drawer:

  • Case A: "Abrir evento" button on a review card → setEventOpener(..., "events") + hash change
  • Case B: Monitoramento map dot click → setEventOpener(..., "dashboard") + native <a href> navigation
  • Case C: Direct #/events/{id} URL load

After handleHashRoute opens the drawer, pressing Escape closes it for cases A and C but is a silent no-op for case B.

Root cause

Escape handler (app.js:1953-1974, round-2 RISK2 guard):

const openerView = eventOpener && eventOpener.view;
if (openerView && typeof eventosViewIsActive === "function" && !eventosViewIsActive(openerView)) return;

For case B, eventOpener.view = "dashboard" (round-4 RISK2 fix at app.js:2121, because the dot lives inside #view-dashboard which is display: none while events is active). When the drawer is open, the active view is always #view-events — never #view-dashboard. So eventosViewIsActive("dashboard") returns false and Escape silently bails.

The original purpose of this guard was to prevent Escape from silently closing a hidden drawer; in case B the guard fires for the wrong reason (it isn't the drawer that's hidden, it's the opener's origin view).

Reproduction

  1. Open http://127.0.0.1:8081, log in
  2. Click Monitoramento tab
  3. Click a colored dot on the minimap → drawer opens, eventos view active
  4. Press Escape → nothing happens
  5. (Contrast: same flow with Eventos tab + "+ Abrir evento" → Escape closes the drawer correctly)

Suggested fix

Gate Escape on the drawer's own visibility, not the opener's view:

const drawer = document.getElementById("eventos-drawer");
if (!drawer || drawer.hidden) return;
// separate signal: track whether the opener is in a still-active view
if (eventOpener && eventOpener.focusEl && document.body.contains(eventOpener.focusEl)) {
  try { eventOpener.focusEl.focus(); } catch {}
}

(document.body.contains(focusEl) already exists in closeEventDrawer at app.js:960 and correctly handles the dot-in-hidden-view case — focusing a detached or display:none element is a no-op in browsers anyway.)

Discovery

Sonnet r6 round-6 review (/tmp/sonnet-review-prompt-r6.md) flagged this as RISK. Acknowledged as out of scope for the PR.

Test gap

The vm test harness's document.addEventListener is a no-op, so Escape behavior has never been exercised by any of the 15 scenarios. A new test would need to either use the browser MCP / browser-harness or extend the stub to track listeners.

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions