From 23820ddbafa53ba5a66de35fa9e29f87d8d1fa67 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9=20Padez?= Date: Fri, 21 Aug 2026 02:27:09 +0000 Subject: [PATCH] the preview never had a tab: the URL param is :section, not :tabId MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Selecting a tab put its id in the URL and the preview still said "Select a tab to preview". A plugin gets exactly two routes from the shell — / and //:section — so :section is the only param name that ever arrives, whatever the plugin means by it. This read :tabId, which was right while it was a platform screen with its own /browser/:tabId route and stayed in place through the extraction. The route matched, the id was in the URL, and useParams().tabId was undefined. Nothing typechecks this: the param is a string key, and the wrong one is simply absent. Co-Authored-By: Claude Opus 5 --- web/shared.ts | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/web/shared.ts b/web/shared.ts index add7537..ecac19b 100644 --- a/web/shared.ts +++ b/web/shared.ts @@ -17,7 +17,16 @@ export type BrowserTarget = { export const browserTabPath = (id: string) => `/browser/${encodeURIComponent(id)}`; /** The previewed tab, or null on the bare `/browser` route — the list with nothing open. */ -export const useSelectedTabId = (): string | null => useParams<{ tabId?: string }>().tabId ?? null; +/** + * Which tab is open, from the URL. + * + * The param is `section`, not `tabId`. A plugin gets exactly two routes from the shell — `/` and + * `//:section` — so `:section` is the only param name that ever arrives, whatever the plugin + * means by it. This read `tabId` while it was a platform screen with its own `/browser/:tabId` route, + * and kept reading it after becoming a plugin: the id was in the URL, the route matched, and the panel + * saw undefined. The preview said "Select a tab to preview" with a tab plainly selected. + */ +export const useSelectedTabId = (): string | null => useParams<{ section?: string }>().section ?? null; // Both panels want this list and React Query serves both observers from one key, so the preview being // able to tell "no tab open" from "that tab is gone" costs no extra request. It needs to: a CDP target