From af859c27e1ccb5c275ce36e4a32c5a10bbfaefcc Mon Sep 17 00:00:00 2001 From: Felipe Freitag Date: Fri, 10 Jul 2026 17:09:47 -0300 Subject: [PATCH] fix(ui): switch toolbar tabs via shallow routing On statically built previews, router.push with a query-only change silently no-ops when the page was initially loaded with a query param the prerender didn't include, leaving the toolbar tabs unresponsive. The panel is client-side UI state, so use window.history.pushState (Next's supported shallow routing, which keeps useSearchParams in sync) instead of a router navigation. This also skips the RSC round-trip and the scroll-to-top on every tab switch. --- .changeset/toolbar-tabs-static-navigation.md | 6 ++++++ packages/ui/src/components/toolbar.tsx | 11 ++++++++--- 2 files changed, 14 insertions(+), 3 deletions(-) create mode 100644 .changeset/toolbar-tabs-static-navigation.md diff --git a/.changeset/toolbar-tabs-static-navigation.md b/.changeset/toolbar-tabs-static-navigation.md new file mode 100644 index 0000000000..637057f7cf --- /dev/null +++ b/.changeset/toolbar-tabs-static-navigation.md @@ -0,0 +1,6 @@ +--- +'@react-email/ui': patch +'react-email': patch +--- + +Fixed toolbar tabs not responding on statically built previews when the page was opened with a `toolbar-panel` query param in the URL. diff --git a/packages/ui/src/components/toolbar.tsx b/packages/ui/src/components/toolbar.tsx index f0df7fb636..ec87e202bc 100644 --- a/packages/ui/src/components/toolbar.tsx +++ b/packages/ui/src/components/toolbar.tsx @@ -2,7 +2,7 @@ import * as Tabs from '@radix-ui/react-tabs'; import { LayoutGroup } from 'framer-motion'; -import { usePathname, useRouter, useSearchParams } from 'next/navigation'; +import { usePathname, useSearchParams } from 'next/navigation'; import type { ComponentProps } from 'react'; import * as React from 'react'; import { nicenames } from '../actions/email-validation/caniemail-data'; @@ -72,7 +72,6 @@ const ToolbarInner = ({ }) => { const pathname = usePathname(); const searchParams = useSearchParams(); - const router = useRouter(); const { hasSetupResendIntegration } = useToolbarContext(); @@ -89,7 +88,13 @@ const ToolbarInner = ({ } else { params.set('toolbar-panel', newValue); } - router.push(`${pathname}?${params.toString()}${location.hash}`); + // Not router.push: on static builds it silently no-ops for query-only + // navigation when the page was loaded with a query param. + window.history.pushState( + null, + '', + `${pathname}?${params.toString()}${location.hash}`, + ); }; const [cachedSpamCheckingResult, setCachedSpamCheckingResult] =