Tabs
Underline tabs built on React Aria. The active tab paints a 2px blue underline over the baseline, and each tab optionally takes a leading icon and a trailing count badge, as in the example below.
Installation
You can add this tabs component using our CLI or manually:
- Install the following dependencies
npm install react-aria-components @remixicon/react - Create atabs.tsxfile and paste the following into it.
tabs.tsx
// components/base/tabs/tabs.tsx"use client"; import { Tab as AriaTab, TabList as AriaTabList, TabPanel as AriaTabPanel, Tabs as AriaTabs,} from "react-aria-components";import { cx } from "@/utils/cx"; // Underline tabs. The strip sits on a 1px border/button/default baseline; the// active tab paints a 2px blue/600 underline over it. Each tab takes an// optional leading icon (16px) and a trailing count badge.//// Built on react-aria Tabs: roving-tabindex arrow-key navigation, automatic// activation and TabList / TabPanel association. export function Tabs({ className, ...props }) { return ( <AriaTabs {...props} className={cx("flex w-full flex-col gap-4", className)} /> );} export function TabList({ className, ...props }) { return ( <AriaTabList {...props} className={cx( "flex w-full items-center gap-1 border-b border-border-button-default", className, )} /> );} export function Tab({ className, children, icon: Icon, count, ...props }) { return ( <AriaTab {...props} className={(state) => cx( "relative -mb-px inline-flex cursor-pointer items-center gap-2.5 border-b-2 border-transparent px-2.5 py-2 whitespace-nowrap", "outline-none transition-[color,border-color] duration-150 ease", state.isSelected && "border-blue-600", state.isDisabled && "cursor-not-allowed opacity-50", className, ) } > {({ isSelected }) => ( <> <span className={cx( "inline-flex items-center gap-1.5", isSelected ? "text-body-medium text-blue-600" : "text-body-regular text-text-primary", )} > {Icon && <Icon className="size-4 shrink-0" aria-hidden />} {children} </span> {count != null && ( <span className={cx( "inline-flex items-center justify-center rounded-sm px-1 py-px text-caption-1-medium", isSelected ? "bg-blue-100 text-blue-600" : "bg-black/10 text-text-primary opacity-50", )} > {count} </span> )} </> )} </AriaTab> );} export function TabPanel({ className, ...props }) { return <AriaTabPanel {...props} className={cx("outline-none", className)} />;} - Update the import paths to match your project setup.
Table of Contents
Tabs are built on React Aria for accessible, roving-tabindex keyboard navigation and automatic TabList / TabPanelassociation. We'll cover the following topics:
- Basic tabs
- Count badges & leading icons
- Keyboard navigation
- Controlled selection