Tab is a common user interface pattern where contents are separated into different panes, each of which is viewable one at a time, allowing users to switch between different sections without changing the page.
Radix UI is a primitive, unstyled, customizable and accessibility focused React component library that provides a foundation for developers to build accessible components upon.
In this tutorial, you'll learn how to make Radix UI tabs URL based in NextJS without causing a full page reload. We'll start with setting up a new project, create a basic Radix UI tabs component, and finally make it URL based by integrating it with NextJS router.
Requirements
- Basic understanding of JavaScript and React
- Node.js and NPM installed on your machine
- A text editor like VS Code
Making Tabs URL-based significantly makes your web application more accessible and user-friendly. It gives users and developers the ability to directly link to a specific content within the app, makes the URL bookmarkable and allows users to share specific content state by simply sharing a URL. It also maintains the user's navigation state if they accidentally reloaded the page, they would conveniently get back to their last active tab.
An example URL could look like this:
https://app.com/page?tab=specificTab
Step 1: Setting Up the Project
To bootstrap a Next.js project, we'll use the official create-next-app CLI by running the following commands:
npx create-next-app@latest
When you run the command, it initiates an interactive session where you have to provide specific details like project name. Once you answer all the prompts, a new Next.js application will be created for you.
Navigate to the newly created project folder and open it with a text editor like VS Code.
Step 2: Creating a Basic Radix UI Tabs Component
The next step is to create a basic Radix UI tabs component. We'll use the Tabs component from @radix-ui/react-tabs package.
Install the package by running the following command:
# with npm
npm install @radix-ui/react-tabs
# with yarn
yarn add @radix-ui/react-tabs
The Tabs component is the parent component that wraps all the other components. It accepts a defaultValue prop that sets the default active tab. The TabList component is a wrapper for all the TabTrigger components. The TabTrigger component is a clickable element that triggers the tab change. The TabContent component is a wrapper for the tab content.
Next, create a Tabs component in pages/index.tsx file:
import * as Tabs from "@radix-ui/react-tabs";
const TabsDemo = () => {
return (
<Tabs.Root>
<Tabs.List>
<Tabs.Trigger value="tab1">Tab 1</Tabs.Trigger>
<Tabs.Trigger value="tab2">Tab 2</Tabs.Trigger>
<Tabs.Trigger value="tab3">Tab 3</Tabs.Trigger>
</Tabs.List>
<Tabs.Content value="tab1">Tab 1 content</Tabs.Content>
<Tabs.Content value="tab2">Tab 2 content</Tabs.Content>
<Tabs.Content value="tab3">Tab 3 content</Tabs.Content>
</Tabs.Root>
);
};
export default function Home() {
return <TabsDemo />;
}
Step 3: Integrating with NextJS Router
The first step to make Radix UI tabs URL based is to make it's state controlled by using React's useState hook to create a state variable that holds the active tab value. We'll then pass the state variable to the Tabs component as a value prop then create a function that handles the tab change and pass it to the Tabs component as an onValueChange prop.
import React from "react";
import * as Tabs from "@radix-ui/react-tabs";
const TabsDemo = () => {
const [activeTab, setActiveTab] = React.useState("tab1");
const handleTabChange = (value) => {
setActiveTab(value);
};
return (
<Tabs.Root
value={activeTab}
defaultValue="tab1"
onValueChange={handleTabChange}
>
<Tabs.List>
<Tabs.Trigger value="tab1">Tab 1</Tabs.Trigger>
<Tabs.Trigger value="tab2">Tab 2</Tabs.Trigger>
<Tabs.Trigger value="tab3">Tab 3</Tabs.Trigger>
</Tabs.List>
<Tabs.Content value="tab1">Tab 1 content</Tabs.Content>
<Tabs.Content value="tab2">Tab 2 content</Tabs.Content>
<Tabs.Content value="tab3">Tab 3 content</Tabs.Content>
</Tabs.Root>
);
};
Finally, we'll integrate the Tabs component with NextJS router by using the useRouter hook to get the current tab value from the URL query parameter and set it as the initial tab value. We'll also add a useEffect hook that listens to the router query parameter changes and updates the active tab value accordingly.
Here is the final code:
import React from "react";
import { useRouter } from "next/router";
import * as Tabs from "@radix-ui/react-tabs";
const TabsDemo = () => {
const router = useRouter();
const initialTab = router.query.tab;
const [activeTab, setActiveTab] = React.useState(initialTab || "tab1");
const handleTabChange = (value) => {
//update the state
setActiveTab(value);
// update the URL query parameter
router.push({ query: { tab: value } });
};
// if the query parameter changes, update the state
React.useEffect(() => {
setActiveTab(router.query.tab);
}, [router.query.tab]);
return (
<Tabs.Root
value={activeTab}
defaultValue="tab1"
onValueChange={handleTabChange}
>
<Tabs.List>
<Tabs.Trigger value="tab1">Tab 1</Tabs.Trigger>
<Tabs.Trigger value="tab2">Tab 2</Tabs.Trigger>
<Tabs.Trigger value="tab3">Tab 3</Tabs.Trigger>
</Tabs.List>
<Tabs.Content value="tab1">Tab 1 content</Tabs.Content>
<Tabs.Content value="tab2">Tab 2 content</Tabs.Content>
<Tabs.Content value="tab3">Tab 3 content</Tabs.Content>
</Tabs.Root>
);
};
Conclusion
In this tutorial, you learned how to make Radix UI tabs URL based in NextJS without causing a full page reload. You can find the full source code on GitHub and the live demo here.
Top comments (0)