fix(ui): prevent showControls cross-tab state leak via localStorage

Fixes #23232.

Opening an Artifacts preview in one tab would silently write
localStorage.showControls = 'true' through an unconditional store
subscriber in (app)/+layout.svelte. Any tab navigating to Home after
that would read the value on mount and auto-expand the Controls panel,
even though the user never interacted with it.

Root cause: showControls.subscribe() in onMount() persisted every
store mutation to localStorage — including programmatic ones triggered
by Artifacts, Citations, and other internal components.

Fix: remove the subscriber from the layout. The layout still reads
localStorage.showControls once on mount to restore the user's last
preference. Persistence is now only written in Navbar.svelte when the
user explicitly clicks the Controls toggle button, keeping localStorage
in sync with deliberate user intent only.

No behaviour change for users who manually toggle Controls — their
preference is still saved and restored across page loads.
This commit is contained in:
AKIBUZZAMAN AKIB 2026-04-15 18:55:02 +00:00
parent 70a6a24f14
commit 75e5c594f1
2 changed files with 6 additions and 6 deletions

View file

@ -217,7 +217,9 @@
<button
class=" flex cursor-pointer px-2 py-2 rounded-xl hover:bg-gray-50 dark:hover:bg-gray-850 transition"
on:click={async () => {
await showControls.set(!$showControls);
const next = !$showControls;
await showControls.set(next);
localStorage.showControls = next ? 'true' : 'false';
}}
aria-label="Controls"
>

View file

@ -344,12 +344,10 @@
checkForVersionUpdates();
}
}
// Persist showControls: track open/close state separately from saved size
// chatControlsSize always retains the last width for openPane()
// Restore showControls from the user's last explicit toggle.
// We intentionally do NOT subscribe here — programmatic changes from
// Artifacts or Citations must not bleed into other tabs via localStorage.
await showControls.set(!$mobile ? localStorage.showControls === 'true' : false);
showControls.subscribe((value) => {
localStorage.showControls = value ? 'true' : 'false';
});
// Persist selectedTerminalId across page loads
selectedTerminalId.set(localStorage.selectedTerminalId ?? null);