Client Side Routing
Introduction
Intent UI components use React Aria for accessible link behavior. Components such as Link, MenuItem, and Tab accept an href to render a navigation link.
By default, links with an href use browser navigation. Use the render prop to pass React Aria's DOM props to your router's link component for client-side navigation. Intent UI still provides the styles, and React Aria still manages interactions and accessibility.
The examples below use the components already installed in your project. You do not need to replace their styles or rebuild them from React Aria primitives.
Next.js
Pass the DOM props to next/link. For a Link without an href, preserve React Aria's default span element.
"use client"
import NextLink from "next/link"
import { Link } from "@/components/ui/link"
export default function Example() {
return (
<Link
href="/about"
render={(domProps) =>
"href" in domProps ? (
<NextLink {...domProps} />
) : (
<span {...domProps} />
)
}
>
About
</Link>
)
}Next.js handles navigation and prefetching through its Link component. Keep passing the DOM props through so the ref, event handlers, accessibility attributes, and children reach the rendered element.
Laravel and Inertia.js
Render navigation links through Inertia's Link. This example uses its default GET navigation behavior.
import { Link as InertiaLink } from "@inertiajs/react"
import { Link } from "@/components/ui/link"
export default function Example() {
return (
<Link
href="/dashboard"
render={(domProps) =>
"href" in domProps ? (
<InertiaLink {...domProps} />
) : (
<span {...domProps} />
)
}
>
Dashboard
</Link>
)
}For actions that submit data, use a button or form rather than a navigation link. See the Inertia links documentation for its navigation options.
React Router
React Router uses to for the destination. Extract href from React Aria's DOM props and pass it as to, forwarding the remaining props to the router's Link.
import { Link as ReactRouterLink } from "react-router"
import { Link } from "@/components/ui/link"
export default function Example() {
return (
<Link
href="/about"
render={(domProps) => {
if ("href" in domProps) {
const { href, ...rest } = domProps
return <ReactRouterLink {...rest} to={href} />
}
return <span {...domProps} />
}}
>
About
</Link>
)
}Render this component inside your application's React Router context. Intent UI continues to use href, while React Router receives to.
TanStack Router
TanStack Router provides createLink to integrate custom link components with its typed navigation and preloading. Wrap the installed Intent UI component and use to for the destination.
import { createLink } from "@tanstack/react-router"
import { Link as IntentLink } from "@/components/ui/link"
export const Link = createLink(IntentLink)
export default function Example() {
return (
<Link to="/about" preload="intent">
About
</Link>
)
}Use a destination that exists in your route tree. TanStack Router checks route paths and parameters against your registered router types.
Wrap other components used as navigation links in the same way. For example, create a separate link version of MenuItem, keeping the original for actions:
import { createLink } from "@tanstack/react-router"
import { MenuItem } from "@/components/ui/menu"
export const MenuItemLink = createLink(MenuItem)Use MenuItemLink inside a menu with to instead of href. This keeps the existing component styles and intent variants.
See the TanStack Router custom link guide for more details.
Menu items and tabs
For routers that use the render prop, apply the same pattern to each navigation item. For example, this Next.js menu item can be placed inside your existing menu:
import NextLink from "next/link"
import { MenuItem } from "@/components/ui/menu"
export function AboutMenuItem() {
return (
<MenuItem
id="about"
href="/about"
render={(domProps) =>
"href" in domProps ? (
<NextLink {...domProps} />
) : (
<div {...domProps} />
)
}
>
About
</MenuItem>
)
}Use span as the fallback for Link, and div for MenuItem and Tab. Items without an href should keep their normal action or selection behavior.
For more on passing DOM props to custom components, see the React Aria customization guide.
