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)