# 112 — Let a single dashboard panel pop out into its own window ## Summary There's already a pop-out mechanism for whole primary sections (log, params, metrics, dashboards) — `PopOutButton` opens a new tab at `?section=` and `App.tsx` reads that query param at startup to render a standalone, full-page version of just that section (see `webapp/src/components/CollapsibleSection.tsx:193-232` and `webapp/src/App.tsx:129-140`, `:372-376`). That grain is a whole section, not a single panel — the Dashboards section can only be popped out in its entirety (all panels of the active dashboard, or all dashboards stacked via `AllDashboardsView`, `Dashboards.tsx:107-135`). This ticket adds the finer-grained version: popping out one panel from one dashboard into its own window, independent of the rest of that dashboard. ## Where - `webapp/src/components/Dashboards.tsx:46-92` (`PanelPreview`) is the component that would need to render standalone, full-page, the same way `StandaloneLog`/`StandaloneParams`/`StandaloneRanged` do today for whole sections (referenced in `App.tsx:373-376`, exact component locations elsewhere in `Dashboards.tsx`/`Metrics.tsx` per the skeleton read during this ticket's writeup — re-read `Dashboards.tsx` in full before implementing, since it was read via repowise's skeleton view here and several ranges (`:1-45`, `:136- 434`) were elided). - `webapp/src/components/CollapsibleSection.tsx:193-206` (`PopOutSectionId`, `popOutUrl`) — the existing section-grain pop-out routing. A panel-grain pop-out needs to identify a specific `(dashboardId, panelId)` pair in the URL, not just a section name — either extend this query-param scheme with `dashboardId`/`panelId` params alongside `section=dashboards`, or give panels their own distinct query shape if reusing `PopOutSectionId` doesn't fit cleanly. - `webapp/src/App.tsx:129-140` (`parsePopOutQuery`), `:372-376` (the dispatch on parsed `section`) — where the new panel-grain case needs a branch, reading whatever new params are added above. - Each `Panel` (`webapp/src/lib/api.ts`'s `Panel` type, imported at `Dashboards.tsx:19`) needs a stable identifier already, or one to add, so a popped-out URL can point back at "this exact panel of this exact dashboard" — check whether `Panel` already carries an `id` field before inventing a new addressing scheme. ## Direction - Mirror the existing section pop-out exactly: a small pop-out button per panel (using or extending `PopOutButton`, `CollapsibleSection.tsx:209-232`) that opens `?section=dashboards& dashboardId=&panelId=`, plus range params the same way `popOutUrl` already carries over a rolling preset or fixed range (`CollapsibleSection.tsx:196-206`). - The standalone page for this case renders just that one panel's `PanelPreview` (or a thin wrapper around it) full-page — no dashboard chrome, no other panels — analogous to how `StandaloneRanged` (`App.tsx:179-...`) drives `LogTimeline`'s picker UI on its own poll cadence for the metrics/dashboards standalone views. - The popped-out panel window should keep polling independently (same `POLL_MS` pattern `PanelPreview` already uses, `Dashboards.tsx:52-55`) rather than freezing at open time. ## Scope - One panel popping into a new browser tab/window, matching the existing section pop-out's mechanism (new tab via `window.open`, not an in-app floating/detached window widget) — stay consistent with the pattern already established for log/params/metrics/ dashboards rather than introducing a second, different pop-out mechanism. - Out of scope: editing a panel's query/chart type from the popped-out view — read-only preview only, matching what pop-out gives you for the other sections today. - Out of scope: [[110-legend-click-to-focus-series]] and [[111-scrollable-panel-legend]] — this ticket is purely about the window/routing mechanism; the popped-out panel should get those legend behaviors for free once they land in `PanelChart`, since it's the same component, but implementing them isn't this ticket's job.