DEV Community

Yinka Adedire
Yinka Adedire

Posted on

How to make Radix UI Tabs URL based in NextJS

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
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

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 />;
}
Enter fullscreen mode Exit fullscreen mode

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>
  );
};
Enter fullscreen mode Exit fullscreen mode

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>
  );
};
Enter fullscreen mode Exit fullscreen mode

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.

Resources

Top comments (0)