Skip to main content

Tabs

Used to display a list of tabs that can be used to navigate between different sections of a page.

Anatomy

  1. Tab Wrapper
  2. Tab List
  3. Tab
  4. Tab Panel

Import

import { TabsProvider, TabsList, Tab, TabsPanel } from '@pluralsight/react'

Usage

In order for the Tabs be accessible, you must provide a matching id and value for each Tab that is unique to the Tab list.

Static Tabs

When you want to display set of Tabs that use static content, you can render all the components directly.

function StaticTabs() {
  const tabs = useMemo(() => {
    return [
      {
        id: 'tab-1',
        label: 'Tab 1',
        panel: 'panel-1',
      },
      {
        id: 'tab-2',
        label: 'Tab 2',
        panel: 'panel-2',
      },
      {
        id: 'tab-3',
        label: 'Tab 3',
        panel: 'panel-3',
      },
    ]
  }, [])

  return (
    <TabsProvider defaultActiveTab={tabs[0].id}>
      <TabsList>
        <For each={tabs}>
          {(tab) => (
            <Tab key={tab.id} controls={tab.panel} id={tab.id} value={tab.id}>
              {tab.label}
            </Tab>
          )}
        </For>
      </TabsList>

      <For each={tabs}>
        {(tab) => (
          <TabsPanel key={tab.panel} labelledBy={tab.id} id={tab.panel}>
            {tab.panel} Content
          </TabsPanel>
        )}
      </For>
    </TabsProvider>
  )
}

Dynamic Tabs

When you want to display a set of Tabs that use dynamic content, you can use the useTabs hook to render the Tabs and Panels.

When fetching data for a Tab Panel, the Tabs will automatically display a loading state until the data is available. This is because we utilize Supsense under the hood.

export default function App() {
  const data: string = "world"

  return <h1>Hello {data}</h1>
}

Disabled Tabs

When you want to disable a Tab, you can use the disabled prop on the Tab component.

function StaticTabs() {
  const tabs = useMemo(() => {
    return [
      {
        id: 'tab-1',
        label: 'Tab 1',
        panel: 'panel-1',
      },
      {
        id: 'tab-2',
        label: 'Tab 2',
        panel: 'panel-2',
      },
      {
        id: 'tab-3',
        label: 'Tab 3',
        panel: 'panel-3',
      },
    ]
  }, [])

  return (
    <TabsProvider defaultActiveTab={tabs[0].id}>
      <TabsList>
        <For each={tabs}>
          {(tab) => (
            <Tab
              key={tab.id}
              controls={tab.panel}
              disabled={tab.id === 'tab-2'}
              id={tab.id}
              value={tab.id}
            >
              {tab.label}
            </Tab>
          )}
        </For>
      </TabsList>

      <For each={tabs}>
        {(tab) => (
          <TabsPanel key={tab.panel} labelledBy={tab.id} id={tab.panel}>
            {tab.panel} Content
          </TabsPanel>
        )}
      </For>
    </TabsProvider>
  )
}

Custom Tabs Components

When you want to customize the Tab family of components, you can use any of the native React features to overwrite styling for the elements.

export default function App() {
  const data: string = "world"

  return <h1>Hello {data}</h1>
}

Headless Styles

When you want to create a set of your own Tab components from scratch, you can use the Headless Styles API along with the React Aria to make them accessible.

import {
  getTabWrapperStyles,
  getTabListStyles,
  splitClassNameProp,
} from '@pluralsight/headless-styles'
import {
  useAriaTabList,
  type UseTabListOptions,
} from '@pluralsight/react-aria'

interface CustomTabListProps extends HTMLAttributes<HTMLDivElement>, UseTabListOptions {
  activeTab: string,
}

export function CustomTabList(props: CustomTabListProps) {
  const { activeTab, labelledBy, setFocus, tabsRefList, ...nativeProps } = props
  const pandoStyles = getTabListStyles({
    classNames: splitClassNameProp(nativeProps.className),
  })
  const ariaProps = useAriaTabList({
    activeTabValue: ,
    labelledBy,
    setFocus: onTabClick,
    tabsRefList,
  })

  return <div {...nativeProps} {...pandoStyles} {...ariaProps} />
}

Behavoir

Patterns

Do use Tabs when you need to display different content relative to the same page.

Don't use Tabs to navigate to different areas of a page or app.

Do keep the Tabs restricted to a single row.

Don't use present multiple rows of Tabs.

Usage

Do restrict the use of Tabs to once per page.

Don't use multiple Tabs within the same page.

Do keep the Tabs located on top of the panel content it is displaying.

Don't position the Tabs or realign them outside of the default top-left positioning.

API

TabsProvider

The TabsProvider component is used to provide the context for the Tabs components. It is required to be used in order for the Tabs components to work.

Props

PropTypeDescription
defaultActiveTabstringThe default active tab value. This is used to set the initial active tab.

TabsList

The TabsList component is used to wrap the Tab components. It is required to be used in order for the Tabs components to work.

Props

PropTypeDescription
labelledBystringThe id of a Form Label associated with the Tab group.

Tab

The Tab component is used to represent a single tab within the TabsList component.

Props

PropTypeDescription
controlsstringThe id of the TabsPanel component that the Tab controls.
disabledbooleanWhether or not the Tab is disabled.
idstringThe id of the Tab.
valuestringThe value of the Tab which should match the id.

TabsPanel

The TabsPanel component is used to represent the content of a single tab within the TabsList component.

Props

PropTypeDescription
labelledBystringThe id of the Tab component that the Tab Panel is associated with.
idstringThe id of the Tab Panel.

Accessibility

The Tabs component is built to be accessible to screen readers and keyboard users alike.

Screen Reader Interactions

Screen readers will announce the following:

  1. The number of Tabs
  2. The selected Tab
  3. The Tab Panel content

Keyboard Interactions

KeyDescription
TabMoves focus to the next focusable element.
Shift + TabMoves focus to the previous focusable element.
Left ArrowMoves focus to the previous Tab.
Right ArrowMoves focus to the next Tab.
HomeMoves focus to the first Tab.
EndMoves focus to the last Tab.
SpaceSelects the current Tab.
EnterSelects the current Tab.