# Popup state persists when closed and immediately reopened

- **Pattern:** `ab-001363` (`extension-ux-performance.popup-responsiveness.popup-state-persists`)
- **Severity:** low
- **Lifecycle:** active
- **Last modified:** 2026-04-18
- **Canonical URL:** https://auditbuffet.com/patterns/ab-001363
- **License:** CC-BY-4.0 — attribute to AuditBuffet Pattern Catalog (https://auditbuffet.com/patterns/ab-001363)

## Why it matters

Chrome tears down the popup JavaScript context the moment the popup loses focus, so every piece of in-memory state — active tab, scroll position, half-typed search queries, expanded accordions — vanishes on close. Users who click out to copy a value from another tab return to a reset UI and lose their input. For extensions with multi-step forms or tabbed settings, this destroys the mental flow and trains users to avoid the popup entirely, driving them to the options page or uninstalling.

## Severity rationale

Low because lost state is an annoyance rather than a failure of core functionality or data integrity.

## Remediation

Persist transient UI state to `chrome.storage.session` before the popup unloads and restore it on the next open. Session storage clears when the browser closes, which matches user expectations for ephemeral UI state. Wire this up in `popup.js`:

```js
window.addEventListener('unload', () => {
  chrome.storage.session.set({ activeTab, searchQuery: input.value });
});
chrome.storage.session.get(['activeTab', 'searchQuery'], restore);
```

## Detection

- **ID:** `popup-state-persists`
- **Severity:** `low`
- **What to look for:** Examine whether the popup saves any transient state before it closes. Chrome destroys popup JS context when the popup closes, so any in-memory state is lost. Check whether the popup saves scroll position, form inputs, active tab selection, or user-entered data to `chrome.storage.local` or `chrome.storage.session`. Look for `window.beforeunload`, `visibilitychange`, or equivalent handlers that persist state. Count all instances found and enumerate each.
- **Pass criteria:** When the popup is closed and immediately reopened, stateful UI (active tab, scroll position, partially filled forms, expanded sections) is restored from storage. At minimum, the popup does not discard user input without warning. At least 1 implementation must be confirmed.
- **Fail criteria:** Closing and reopening the popup resets all UI state. Users lose partially entered form data, their tab selection resets to default, or scroll position returns to top — with no mechanism to restore it.
- **Skip (N/A) when:** The extension has no popup, or the popup is intentionally stateless (e.g., a simple one-action popup with no navigable state).
- **Detail on fail:** Describe what state is lost. Example: `"Active settings tab resets to 'General' on every open — user must renavigate to 'Advanced' each session"` or `"Search query entered in popup is discarded on close, requiring re-entry."`
- **Remediation:** Persist lightweight UI state to `chrome.storage.session` (cleared when browser closes) or `chrome.storage.local` (persists across sessions):

  ```js
  // Save state before popup closes
  window.addEventListener('unload', () => {
    chrome.storage.session.set({
      activeTab: currentTab,
      searchQuery: searchInput.value,
    });
  });

  // Restore on open
  chrome.storage.session.get(['activeTab', 'searchQuery'], (state) => {
    if (state.activeTab) switchToTab(state.activeTab);
    if (state.searchQuery) searchInput.value = state.searchQuery;
  });
  ```

Taxons: user-experience

HTML version: https://auditbuffet.com/patterns/ab-001363
