Tabs

Tabs organize content into multiple sections and allow users to navigate between them.

Storybook@nextui-org/tabsReact AriaSourceStyles source
Zigma by NextUI (YC S24) - Connect your design files to production code in minutes | Product Hunt

We're live on Product Hunt! Join the conversation and help us get to #1 Product of the day 🚀


Installation

npx nextui-cli@latest add tabs
The above command is for individual installation only. You may skip this step if @nextui-org/react is already installed globally.

Import

NextUI exports 2 tabs-related components:

  • Tabs: The main component to display a tab list.
  • Tab: The component to display a tab item. The children of this component will be displayed as the content of the tab.

Usage

Dynamic

You can render tabs dynamically by using items prop.

Disabled

Disabled Item

Sizes

Radius

Colors

Variants

With Icons

Controlled

You can use the onSelectionChange and selectedKey props to control the selected tab.

Placement

You can change the position of the tabs by using the placement prop. The default value is top.

Vertical

Change the orientation of the tabs it will invalidate the placement prop when the value is true.

Tabs items can be rendered as links by passing the href prop to the Tab component. By default, links perform native browser navigation. However, you'll usually want to synchronize the selected tab with the current URL from your client side router. You can do this by doing the following:

  1. Set up your router at the root of your app. See Routing guide to learn how to do this.
  2. Use the selectedKey prop to set the selected tab based on the current URL.

Next.js

This example uses Next.js App router to set up routes for each tab and synchronize the selected tab with the current URL.

// app/tabs/page.tsx
"use client";
import {usePathname} from "next/navigation";
function ExampleClientRouterWithTabs() {
const pathname = usePathname();
return (
<Tabs aria-label="Options" selectedKey={pathname}>
<Tab key="photos" title="Photos" href="/photos">
<Card>
<CardBody>
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor
incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud
exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.
</CardBody>
</Card>
</Tab>
<Tab key="music" title="Music" href="/music">
<Card>
<CardBody>
Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea
commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum
dolore eu fugiat nulla pariatur.
</CardBody>
</Card>
</Tab>
<Tab key="videos" title="Videos" href="/videos">
<Card>
<CardBody>
Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt
mollit anim id est laborum.
</CardBody>
</Card>
</Tab>
</Tabs>
);
}

React Router

This example uses React Router to setup routes for each tab and synchronize the selection with the URL.

import {Route, Routes, useLocation} from "react-router-dom";
import {Tabs, Tab} from "@nextui-org/react";
function AppTabs() {
const {pathname} = useLocation();
return (
<div className="flex flex-col gap-2">
<Tabs selectedKey={pathname} aria-label="Tabs">
<Tab id="/" href="/" title="Home" />
<Tab id="/photos" href="/photos" title="Photos" />
<Tab id="/music" href="/music" title="Music" />
<Tab id="/videos" href="/videos" title="Videos" />
</Tabs>
<Routes>
<Route path="/" element={<HomePage />} />
<Route path="/photos" element={<PhotosPage />} />
<Route path="/music" element={<MusicPage />} />
<Route path="/videos" element={<VideosPage />} />
</Routes>
</div>
);
}

Note: See the Routing guide to learn how to set up the router for your framework.

With Form

Slots

  • base: The main tabs slot, it wraps the items and the panels.
  • tabList: The tab list slot, it wraps the tab items.
  • tab: The tab slot, it wraps the tab item.
  • tabContent: The tab content slot, it wraps the tab content.
  • cursor: The cursor slot, it wraps the cursor. This is only visible when disableAnimation=false
  • panel: The panel slot, it wraps the tab panel (content).

Custom Styles

You can customize the Tabs component by passing custom Tailwind CSS classes to the component slots.

Data Attributes

Tab has the following attributes on the base element:

  • data-selected: When the tab is selected.
  • data-disabled: When the tab is disabled.
  • data-hover: When the tab is being hovered. Based on useHover.
  • data-hover-selected: When the tab is being hovered and is not selected. Based on useHover and selected state.
  • data-focus: When the tab is being focused. Based on useFocusRing.
  • data-focus-visible: When the tab is being focused with the keyboard. Based on useFocusRing.
  • data-pressed: When the tab is pressed. Based on usePress.

Accessibility

  • Support for mouse, touch, and keyboard interactions on tabs.
  • Keyboard event support for arrows keys.
  • Support for disabled tabs.
  • Follows the tabs ARIA pattern, semantically linking tabs and their associated tab panels.
  • Focus management for tab panels without any focusable children.

API

Tabs Props

AttributeTypeDescriptionDefault
children*ReactNode | ((item: T) => ReactElement)The list of tabs.-
variantsolid | bordered | light | underlinedThe tabs appearance style.solid
colordefault | primary | secondary | success | warning | dangerThe tabs color theme.default
sizesm | md | lgThe tabs size.md
radiusnone | sm | md | lg | fullThe tabs border radius.-
fullWidthbooleanWhether the tabs should take the full width of its parent.false
itemsIterable<T>The list of tabs (dynamic).-
disabledKeysReact.Key[]The item keys that are disabled. These items cannot be selected, focused, or otherwise interacted with.-
selectedKeyReact.KeyThe key for the currently selected item.-
defaultSelectedKeyReact.KeyThe key for the initially selected item.-
shouldSelectOnPressUpbooleanWhether the tabs selection should occur on press up instead of press down.true
keyboardActivationautomatic | manualWhether tabs are activated automatically on focus or manually.automatic
motionPropsMotionPropsThe props to modify the cursor framer motion animation. Use the variants API to create your own animation.-
disableCursorAnimationbooleanWhether the cursor should be hidden.false
isDisabledbooleanWhether the tab list should be disabled.false
disableAnimationbooleanWhether the tab list should be animated.false
classNamesRecord<"base"| "tabList"| "tab"| "tabContent"| "cursor" | "panel", string>Allows to set custom class names for the card slots.-
placementtop | bottom | start | endThe position of the tabs.top
isVerticalbooleanWhether the tabs are vertical.false
destroyInactiveTabPanelbooleanWhether to destroy inactive tab panel when switching tabs. Inactive tab panels are inert and cannot be interacted with.true

Tabs Events

AttributeTypeDescription
onSelectionChange(key: React.Key) => anyHandler that is called when the selection changes.

Tab Props

AttributeTypeDescriptionDefault
children*ReactNodeThe content of the tab.-
titleReactNodeThe title of the tab.-
titleValuestringA string representation of the item's contents. Use this when the title is not readable.-
hrefstringA URL to link to. See MDN.-
targetHTMLAttributeAnchorTargetThe target window for the link. See MDN.-
relstringThe relationship between the linked resource and the current page. See MDN.-
downloadboolean | stringCauses the browser to download the linked URL. A string may be provided to suggest a file name. See MDN.-
pingstringA space-separated list of URLs to ping when the link is followed. See MDN.-
referrerPolicyHTMLAttributeReferrerPolicyHow much of the referrer to send when following the link. See MDN.-
shouldSelectOnPressUpbooleanWhether the tab selection should occur on press up instead of press down.-

Motion Props

export type MotionProps = HTMLMotionProps<"div">; // @see https://www.framer.com/motion/