Skip to content

popup: fix and improve the overlay, popup and panel shell from the October 2026 audit #326

Closed as duplicate

Description

@erkamyaman

Context

This comes from a code audit of the overlay, popup and panel shell, done during a comparison with other devtools in October 2026. Roadmap items live in #310, #311, #312 and #313. Items marked (to confirm) were not reproduced.

Problems

Medium

  • No retry after a failed first connection: connectDevframe runs once, and on rejection the panel sets connectionFailed and asks the user to reload. A dev server that starts slowly or restarts needs a manual reload. Retry with backoff (1, 2, 5, 10 s) while connectionFailed is set and add a "Retry now" button. The popup's findTarget also only retries on the next open (app/src/app.ts:913-947, app/src/app.ts:372-375, packages/devtools/src/popup.ts:114-121).

Low

  • Popup accepts theme messages from any window: onThemeMessage only rejects e.source === window, so any iframe or script on the host page can flip the popup theme, and the value is saved to localStorage. Accept the message only from iframe.contentWindow (or a frame inside it) with a matching origin (packages/devtools/src/popup.ts:827-832).
  • Theme posted to every ancestor with '*': ThemeService walks window.parent and posts pangular:theme-change with target origin '*', which leaks to unknown origins when the panel is embedded cross-origin. Post to the parent's origin (from document.referrer or ancestorOrigins), or rely on the BroadcastChannel for same-origin cases (app/src/theme.service.ts:36-47).
  • Tab strip is not a tablist: the inspector tabs are buttons with aria-current="page", with no roving tabindex or arrow keys, so ten tabs are ten tab stops before the content. Use role=tablist/tab/tabpanel with aria-selected and roving tabindex, or keep the nav pattern and add arrow-key handling (app/src/app.ts:346-358).
  • Opening the panel leaves focus on the FAB: togglePanel only moves focus on close. When opened from the keyboard (click with detail === 0), focus the iframe or its main once loaded (packages/devtools/src/popup.ts:670-675).
  • Hub views listed twice: HUB_VIEWS is defined in both the panel and the package, and the pangular: dock prefix is repeated too. Adding a dock in one place breaks followHubDocks and view titles silently. Export HUB_VIEWS and dockId from one module and import them in the app (app/src/app.ts:43-50, packages/devtools/src/hub-docks.ts:9-16, packages/devtools/src/hub-docks.ts:48, app/src/hub-dock-sync.ts:2, app/src/app.ts:1088).
  • Overlay and popup probe different bases: the overlay tries ['./', '/__pangular/', '/__devframes/pangular/'] and the popup tries ['/__pangular/', '/__devframes/pangular/', '/__devframe/', '/'], so one can find a server the other misses. Keep one exported list in panel-frame.ts and use it in both (packages/devtools/src/overlay.ts:177, packages/devtools/src/popup.ts:61).
  • Untyped hub:docks:activate call: the fallback dock switch casts the RPC client as unknown and calls hub:docks:activate. If the client has no top-level call, the panel quietly switches to the fallback tab instead of the dock. Use the typed hub client API and add a test that the hub path activates the dock (app/src/app.ts:1073-1094) (to confirm).
  • Short page id: the page id is 4 base36 characters from Math.random, and the BroadcastChannel claim only catches collisions inside one browser. Pages from other devices (NativeScript, Angular Native, a phone) reporting to one hub can collide. Use crypto.randomUUID().slice(0, 8) or longer, staying under the server's 50-character limit (packages/devtools/src/overlay.ts:96, packages/devtools/src/devframe.ts:272).

Improvements

  • Move limits, redaction, refreshMs and the action toggles from config-file-only to ctx.settings, with a Settings view in the panel (packages/devtools/src/config.ts, packages/devtools/src/devframe.ts, app/src/app.ts).
  • Export a programmatic buildReport() next to the CLI build, so CI and Analog/Vite builds can produce the static report without the CLI wrapper (packages/devtools/src/cli.ts, packages/devtools/package.json).
  • Remember scroll position and selection per tab, not only the tab id, in sessionStorage keyed by pageId, so a popup or extension reload returns to the same item (app/src/tab-memory.ts, app/src/app.ts).
  • A minimized "pill" launcher that shows the render count and error count on the FAB (packages/devtools/src/popup.ts).

Already tracked elsewhere

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething is broken or shows wrong datafeatureA feature request or a pull request that adds one

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions