From 5c26f39f2ced0d0e9bfe5149425c02470bb975c3 Mon Sep 17 00:00:00 2001 From: Dave Date: Thu, 17 Sep 2026 11:15:32 +0200 Subject: [PATCH] fix(nav): avoid Kanban flyout state update racing with RSC navigation A click outside the Kanban sidebar flyout called setOpen(false) even when the click was on a Link, so the deferred state update landed during the Link navigation's RSC stream and corrupted Turbopack's flight client (vercel/next.js#92362). Skip the close when the click target is inside an and flush the close synchronously from the Link's own onClick so the state update completes before navigation, not during RSC processing. --- src/components/shell/kanban-nav.tsx | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/src/components/shell/kanban-nav.tsx b/src/components/shell/kanban-nav.tsx index a05a2de..d977cf4 100644 --- a/src/components/shell/kanban-nav.tsx +++ b/src/components/shell/kanban-nav.tsx @@ -1,6 +1,7 @@ "use client"; import { useEffect, useRef, useState } from "react"; +import { flushSync } from "react-dom"; import Link from "next/link"; import { Kanban } from "lucide-react"; @@ -36,6 +37,11 @@ export function KanbanNav({ containerRef.current && !containerRef.current.contains(event.target as Node) ) { + // Skip closing when the click is on an anchor. The Link's own + // onClick closes the flyout via flushSync below, and racing a + // deferred state update with the navigation's RSC stream + // corrupts Turbopack's flight client (vercel/next.js#92362). + if ((event.target as HTMLElement).closest("a")) return; setOpen(false); } } @@ -80,7 +86,11 @@ export function KanbanNav({ setOpen(false)} + onClick={() => { + // Force the close to land before navigation, not + // during RSC stream processing — see #92362 above. + flushSync(() => setOpen(false)); + }} className="flex items-center justify-between gap-2 rounded-lg px-2 py-1.5 text-xs text-text-secondary transition-colors hover:bg-surface-raised hover:text-text-primary" > {project.name}