**Implementation Plan: Fix Bugs in Back Navigation Modal Dismissal** **Objective:** Resolve the three cleanup defects identified during investigation (`AppLightbox`, `AppDialog`, `AppContextMenu`) and add test coverage to prevent regression. The user-visible symptom (scroll‑locked page after back navigation from lightbox) is caused by Bug A; the other bugs cause degraded behavior (unresolved promises, lost focus) that should also be fixed. --- ### Changes Required #### 1. `AppLightbox._onPopstate()` (file `assets/js/components/lightbox.js`, lines ~93-97) - **After** calling `this.element.classList.remove('visible')`, add: - `document.body.style.overflow = '';` (or restore the original value captured when the lightbox opened – if no such capture exists, simply remove the inline `overflow` property) - `this.image.src = '';` (to free the image resource) - Restore focus: if `this.lastFocus` is set, call `this.lastFocus.focus()` and then set `this.lastFocus = null`. #### 2. `AppDialog` popstate handler (file `assets/js/components/dialog.js`, lines ~67-71) - Replace the current handler body with a call to `this.close()`. `this.close()` already handles removing the `visible` class, clearing the overlay, and invoking the promise resolver. Ensure that `close()` is called unconditionally (no guards needed – the handler fires only for a popstate event triggered by `history.back()` from the component itself). #### 3. `AppContextMenu` popstate handler (file `assets/js/components/context-menu.js`, lines ~54-58) - **After** removing the menu, add focus restoration: ```js if (this._lastFocusedElement) { this._lastFocusedElement.focus(); this._lastFocusedElement = null; } ``` #### 4. Test Coverage Add Playwright-based e2e tests that cover the browser‑back scenario for each modal type. Locate existing test files: - `tests/e2e/profile/search.py` – add a test method after `test_ui_media_lightbox_opens` that opens the lightbox, calls `page.go_back()`, and asserts: - The lightbox is not visible. - `document.body.style.overflow` is not `'hidden'`. - The page URL has not changed (i.e., it remains on the profile page, not a previous page). - `tests/e2e/ui/components.py` – add a test that opens a dialog, calls `page.go_back()`, and asserts the dialog is hidden and the page URL is unchanged. - (Optional but recommended) Add a similar test for context menu in the same file or in a relevant test file. All new tests must use `page.wait_for_selector('.modal-overlay', state='hidden')` or equivalent to avoid flakiness. --- ### Definition of Done - [ ] The three source‑code changes described above are applied to the correct files. - [ ] All new e2e tests (lightbox, dialog, context menu) pass when run against a local development server. - [ ] Existing unit tests still pass: `pip install -e '.[dev]' -q && make test-unit` - [ ] Linter reports zero errors: `pip install -q ruff && ruff check .` - [ ] Manual verification confirms: - Opening a lightbox, pressing browser back → lightbox hidden, page scrollable, URL unchanged. - Opening a dialog, pressing browser back → dialog closed, no hanging promise. - Opening a context menu, pressing browser back → menu removed, focus returns to the triggering element.