Ariakit
/

Tab with Next.js App Router

Using Next.js Parallel Routes to create accessible Tabs and tab panels that are rendered on the server and controlled by the URL.

Open in new tab
import Link from "next/link.js";
import type { ReactNode } from "react";
import "./style.css";
import { Tab, TabList, TabPanel, Tabs } from "./tabs.tsx";
export default function Layout(props: { tabs: ReactNode }) {
return (
<main className="main">
<h1 className="heading">Posts</h1>
<p>
Check out the{" "}
<Link href="/previews/tab-next-router" className="link">
trending posts
</Link>{" "}
or stay up to date with the{" "}
<Link href="/previews/tab-next-router/new" className="link">
latest posts
</Link>
</p>
<div className="wrapper">
<Tabs>
<Tab href="/previews/tab-next-router">Hot</Tab>
<Tab href="/previews/tab-next-router/new">New</Tab>
</TabList>
<TabPanel>{props.tabs}</TabPanel>
</Tabs>
</div>
</main>
);
}

Components

Abstracting the Tab components

In this example, we're abstracting the Ariakit Tab components into higher-level components with a simpler API integrated with the Next.js App Router. Check out the tabs.tsx file above to see the source code.

Controlling the Tab state

To control the selected tab state, you can pass the selectedId and setSelectedId props to TabProvider. These props allow you to synchronize the tab state with other state sources, such as the browser history.

const router = useRouter();
const pathname = usePathname();
selectedId={pathname}
setSelectedId={(id) => {
router.push(id || pathname)
}}
>

You can learn more about controlled state on the Component providers guide.

Rendering a single TabPanel

It's possible to render a single TabPanel component and use the tabId prop to point to the selected tab.

const tabId = useStoreState(tab, "selectedId");
<TabPanel tabId={tabId}>{props.children}</TabPanel>;

Stay tuned

Join 1,000+ subscribers and receive monthly tips & updates on new Ariakit content.

No spam. Unsubscribe anytime. Read latest issue