From 916a116b1a4a152f245ef0d837b284f1568cf6dd Mon Sep 17 00:00:00 2001 From: feruzm Date: Mon, 24 Aug 2026 17:31:21 +0000 Subject: [PATCH 1/2] Prefetch chrome links on intent instead of viewport entry (#1666) --- .../_components/entry-page-breadcrumb.tsx | 6 +-- .../navbar/navbar-main-sidebar-toggle.tsx | 6 +-- .../features/shared/navbar/navbar-mobile.tsx | 6 +-- .../shared/navbar/navbar-text-menu.tsx | 6 +-- apps/web/src/features/ui/button/index.tsx | 9 +++-- .../web/src/specs/features/ui/button.spec.tsx | 38 +++++++++++++++++++ 6 files changed, 56 insertions(+), 15 deletions(-) diff --git a/apps/web/src/app/(dynamicPages)/entry/[category]/[author]/[permlink]/_components/entry-page-breadcrumb.tsx b/apps/web/src/app/(dynamicPages)/entry/[category]/[author]/[permlink]/_components/entry-page-breadcrumb.tsx index 7635ae976e..6168338159 100644 --- a/apps/web/src/app/(dynamicPages)/entry/[category]/[author]/[permlink]/_components/entry-page-breadcrumb.tsx +++ b/apps/web/src/app/(dynamicPages)/entry/[category]/[author]/[permlink]/_components/entry-page-breadcrumb.tsx @@ -1,4 +1,4 @@ -import Link from "next/link"; +import { IntentLink } from "@/features/shared/intent-link"; export interface BreadcrumbItem { name: string; @@ -34,9 +34,9 @@ export function EntryPageBreadcrumb({ items }: Props) { ) : ( <> - + {item.name} - + )} diff --git a/apps/web/src/features/shared/navbar/navbar-main-sidebar-toggle.tsx b/apps/web/src/features/shared/navbar/navbar-main-sidebar-toggle.tsx index d48b251f51..aa8498f820 100644 --- a/apps/web/src/features/shared/navbar/navbar-main-sidebar-toggle.tsx +++ b/apps/web/src/features/shared/navbar/navbar-main-sidebar-toggle.tsx @@ -2,7 +2,7 @@ import { Button } from "@/features/ui"; import { UilBars } from "@tooni/iconscout-unicons-react"; import i18next from "i18next"; import Image from "next/image"; -import Link from "next/link"; +import { IntentLink } from "@/features/shared/intent-link"; import defaults from "@/defaults"; interface Props { @@ -13,7 +13,7 @@ export function NavbarMainSidebarToggle({ onClick }: Props) { return (
); } diff --git a/apps/web/src/features/shared/navbar/navbar-mobile.tsx b/apps/web/src/features/shared/navbar/navbar-mobile.tsx index ef86b8f5d7..edc5281fed 100644 --- a/apps/web/src/features/shared/navbar/navbar-mobile.tsx +++ b/apps/web/src/features/shared/navbar/navbar-mobile.tsx @@ -17,7 +17,7 @@ import { Button } from "@ui/button"; import clsx from "clsx"; import i18next from "i18next"; import Image from "next/image"; -import Link from "next/link"; +import { IntentLink } from "@/features/shared/intent-link"; import { usePathname, useSearchParams } from "next/navigation"; import { useEffect, useState } from "react"; import defaults from "@/defaults"; @@ -132,11 +132,11 @@ export function NavbarMobile({ aria-label={i18next.t("navbar.toggle-menu")} aria-expanded={mainBarExpanded} /> - + {/* The image alt provides the link's accessible name (brand/home), distinct from the "Home" feed tab below. */} Ecency - + , router); + expect(router.prefetch).not.toHaveBeenCalled(); + }); + + it("prefetches on hover intent", async () => { + const router = makeRouter(); + await renderWithRouter(, router); + fireEvent.mouseEnter(screen.getByText("Perks").closest("a")!); + expect(router.prefetch).toHaveBeenCalledWith("/perks", expect.anything()); + }); +}); From 6e283d33dca2876af24f1736da2402dbc1c9b868 Mon Sep 17 00:00:00 2001 From: feruzm Date: Mon, 24 Aug 2026 17:46:51 +0000 Subject: [PATCH 2/2] Type the href-branch ref cast; pin ref forwarding through IntentLink --- apps/web/src/features/ui/button/index.tsx | 2 +- apps/web/src/specs/features/ui/button.spec.tsx | 15 +++++++++++++++ 2 files changed, 16 insertions(+), 1 deletion(-) diff --git a/apps/web/src/features/ui/button/index.tsx b/apps/web/src/features/ui/button/index.tsx index 3c792ea570..8bf3af6fd1 100644 --- a/apps/web/src/features/ui/button/index.tsx +++ b/apps/web/src/features/ui/button/index.tsx @@ -89,7 +89,7 @@ const ForwardedButton = forwardRef{props.children} : <>; return "href" in props ? ( - + }> {props.isLoading && props.loadingText ? props.loadingText : children} {icon} diff --git a/apps/web/src/specs/features/ui/button.spec.tsx b/apps/web/src/specs/features/ui/button.spec.tsx index f03f539d38..583f157f55 100644 --- a/apps/web/src/specs/features/ui/button.spec.tsx +++ b/apps/web/src/specs/features/ui/button.spec.tsx @@ -272,3 +272,18 @@ describe("Button href prefetch behavior (#1666)", () => { expect(router.prefetch).toHaveBeenCalledWith("/perks", expect.anything()); }); }); + +describe("Button href ref forwarding", () => { + it("forwards the ref through IntentLink to the anchor element", () => { + // React 19 passes ref as a prop through function components; IntentLink + // spreads it onto next/link, which attaches it to the rendered . + const ref = React.createRef(); + render( + + ); + expect(ref.current).toBeInstanceOf(HTMLAnchorElement); + expect(ref.current?.getAttribute("href")).toBe("/perks"); + }); +});