diff --git a/apps/mana/apps/web/src/routes/(app)/+page.svelte b/apps/mana/apps/web/src/routes/(app)/+page.svelte
index cbabf5900..b4b89b8a7 100644
--- a/apps/mana/apps/web/src/routes/(app)/+page.svelte
+++ b/apps/mana/apps/web/src/routes/(app)/+page.svelte
@@ -413,7 +413,7 @@
bindAgentDialogOpen = true;
}
- function handleRequestRename(id: string) {
+ async function handleRequestRename(id: string) {
// Unified rename path: scroll the carousel to the scene header
// and focus its contenteditable
. Previously opened a modal
// dialog that read from the store while the live header might
@@ -423,13 +423,13 @@
if (!scene) return;
if (id !== activeSceneId) workbenchScenesStore.setActiveScene(id);
scrollCarouselToStart();
- // Next tick: the header is mounted + the scroll has started;
- // querying now lands on the active scene's h1 which
- // contenteditable plaintext-only focuses cleanly.
- setTimeout(() => {
- const h1 = document.querySelector('.scene-header .scene-name[contenteditable]');
- h1?.focus();
- }, 120);
+ // Await Svelte's flush so the activeScene → SceneHeader re-render
+ // has landed before we query. Previously we used a 120 ms
+ // setTimeout, which was brittle on slower hardware and sometimes
+ // fired before the header was updated, focusing the old scene's h1.
+ await tick();
+ const h1 = document.querySelector('.scene-header .scene-name[contenteditable]');
+ h1?.focus();
}
function handleDuplicateScene(id: string) {
workbenchScenesStore.duplicateScene(id);