fix(ui): DIAGNOSTICS menu detach, focus loss on F-key, listener cleanup #182

Open
opened 2026-09-28 13:58:43 +00:00 by gabogg · 0 comments
Owner

Follow-up from review pass 2 on #173 (deferred P3s, all in app/static/js/src/ui/deck_menu.js).

Findings

  1. Menu detaches from its button when the button scrolls out of the strip. The capture-phase scroll listener (around line 108) repositions from getBoundingClientRect(). When the button is clipped by the deck selector's overflow-x, menuPlacement clamps left to 0 or the right viewport edge (around line 47). The menu stays open at the viewport edge, away from a button that is not visible. Also, the left clamp uses a margin of 0, while the right clamp uses VIEWPORT_MARGIN (8px).
  2. An F-key pressed with the menu open loses keyboard focus. syncActive() calls close() without restoring focus (around line 167). If F4/F6/F7 is pressed while a menu item has focus, the item becomes display:none and focus falls to <body>.
  3. Listeners are never removed. The document mousedown/keydown and window resize/scroll listeners (around lines 103–109) are added in the constructor and there is no destroy(). This is harmless today, since initDiagnosticsMenu creates only one menu, but it matters if DeckMenu is reused (e.g. for #170).

Acceptance criteria

  • While the menu is open, it closes once its button leaves the deck selector's visible area. The left and right viewport margins are the same.
  • A deck switch through syncActive() while focus is inside the menu returns focus to the DIAGNOSTICS button.
  • DeckMenu has a destroy() that removes every listener it added.
  • Each behaviour is covered in tests/frontend/test_deck_menu.test.js.
Follow-up from review pass 2 on #173 (deferred P3s, all in `app/static/js/src/ui/deck_menu.js`). ## Findings 1. **Menu detaches from its button when the button scrolls out of the strip.** The capture-phase scroll listener (around line 108) repositions from `getBoundingClientRect()`. When the button is clipped by the deck selector's `overflow-x`, `menuPlacement` clamps `left` to 0 or the right viewport edge (around line 47). The menu stays open at the viewport edge, away from a button that is not visible. Also, the left clamp uses a margin of 0, while the right clamp uses `VIEWPORT_MARGIN` (8px). 2. **An F-key pressed with the menu open loses keyboard focus.** `syncActive()` calls `close()` without restoring focus (around line 167). If F4/F6/F7 is pressed while a menu item has focus, the item becomes `display:none` and focus falls to `<body>`. 3. **Listeners are never removed.** The document mousedown/keydown and window resize/scroll listeners (around lines 103–109) are added in the constructor and there is no `destroy()`. This is harmless today, since `initDiagnosticsMenu` creates only one menu, but it matters if `DeckMenu` is reused (e.g. for #170). ## Acceptance criteria - [ ] While the menu is open, it closes once its button leaves the deck selector's visible area. The left and right viewport margins are the same. - [ ] A deck switch through `syncActive()` while focus is inside the menu returns focus to the DIAGNOSTICS button. - [ ] `DeckMenu` has a `destroy()` that removes every listener it added. - [ ] Each behaviour is covered in `tests/frontend/test_deck_menu.test.js`.
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
gabogg/hikcentral#182
No description provided.