Tabs

Our Tabs components allow you to easily create accessible tabs where the content remains in the DOM when the tab is not currently visible. Features include:

  • Makes use of the react-aria-components library to handle the tabs logic.
  • Content for all tabs remains in the DOM at all times (shouldForceMount={true} and className="data-[inert=true]:hidden" on the <TabPanel>)
  • Keyboard navigation and focus management
  • Supports vertical or horizontal orientation

Example

This is the content for tab 1 Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed a justo sapien. Nunc tempor, sem non feugiat vehicula, augue arcu feugiat ligula, quis efficitur nulla dui non magna. Mauris leo erat, suscipit id elit quis, sodales varius lacus. Ut tempus dignissim elit ut blandit. Aenean et dui ut metus lacinia ullamcorper quis non nisi. Etiam tincidunt sagittis scelerisque. Fusce consectetur accumsan sem non consequat. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Aenean ac sapien pharetra, aliquam leo sit amet, suscipit felis. Vivamus id malesuada justo. Quisque ultricies tortor sed massa sodales sodales.
This is the content for tab 2 Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed a justo sapien. Nunc tempor, sem non feugiat vehicula, augue arcu feugiat ligula, quis efficitur nulla dui non magna. Mauris leo erat, suscipit id elit quis, sodales varius lacus. Ut tempus dignissim elit ut blandit. Aenean et dui ut metus lacinia ullamcorper quis non nisi. Etiam tincidunt sagittis scelerisque. Fusce consectetur accumsan sem non consequat. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Aenean ac sapien pharetra, aliquam leo sit amet, suscipit felis. Vivamus id malesuada justo. Quisque ultricies tortor sed massa sodales sodales.
This is the content for tab 3 Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed a justo sapien. Nunc tempor, sem non feugiat vehicula, augue arcu feugiat ligula, quis efficitur nulla dui non magna. Mauris leo erat, suscipit id elit quis, sodales varius lacus. Ut tempus dignissim elit ut blandit. Aenean et dui ut metus lacinia ullamcorper quis non nisi. Etiam tincidunt sagittis scelerisque. Fusce consectetur accumsan sem non consequat. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Aenean ac sapien pharetra, aliquam leo sit amet, suscipit felis. Vivamus id malesuada justo. Quisque ultricies tortor sed massa sodales sodales.
<Tabs>
  <TabList aria-label="Tabs" className="flex w-fit flex-row gap-2 pt-2">
    {data.tabItems?.map((item, index) => (
      <Tab
        className="data-[selected=true]:text-primary-600 data-[selected=true]:after:bg-primary-600 data-[selected=true]:hover:bg-primary-100 focus-ring-inverse relative flex cursor-pointer gap-2.5 rounded-md px-2 py-1 font-semibold text-gray-600 after:absolute after:right-0 after:-bottom-1.5 after:left-0 after:h-[2px] after:rounded after:bg-transparent hover:bg-gray-100 hover:after:bg-gray-600 focus-visible:ring-2"
        key={index}
        id={index}
      >
        <RiFoldersLine aria-hidden="true" />
        {item.title}
      </Tab>
    ))}
  </TabList>
  <TabPanels className="mt-1 border-t-2 border-gray-100 pt-8">
    {data.tabItems?.map((item, index) => (
      <TabPanel
        id={index}
        key={index}
        shouldForceMount={true}
        className="focus-ring data-[inert=true]:hidden"
      >
        {item.content}
      </TabPanel>
    ))}
  </TabPanels>
</Tabs>

Vertical Tabs

Tabs can be arranged vertically by:

  1. Setting the orientation prop to "vertical" on the <Tabs>
  2. Styling the tabs so they appear vertical.
This is the content for tab 1 Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed a justo sapien. Nunc tempor, sem non feugiat vehicula, augue arcu feugiat ligula, quis efficitur nulla dui non magna. Mauris leo erat, suscipit id elit quis, sodales varius lacus. Ut tempus dignissim elit ut blandit. Aenean et dui ut metus lacinia ullamcorper quis non nisi. Etiam tincidunt sagittis scelerisque. Fusce consectetur accumsan sem non consequat. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Aenean ac sapien pharetra, aliquam leo sit amet, suscipit felis. Vivamus id malesuada justo. Quisque ultricies tortor sed massa sodales sodales.
This is the content for tab 2 Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed a justo sapien. Nunc tempor, sem non feugiat vehicula, augue arcu feugiat ligula, quis efficitur nulla dui non magna. Mauris leo erat, suscipit id elit quis, sodales varius lacus. Ut tempus dignissim elit ut blandit. Aenean et dui ut metus lacinia ullamcorper quis non nisi. Etiam tincidunt sagittis scelerisque. Fusce consectetur accumsan sem non consequat. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Aenean ac sapien pharetra, aliquam leo sit amet, suscipit felis. Vivamus id malesuada justo. Quisque ultricies tortor sed massa sodales sodales.
This is the content for tab 3 Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed a justo sapien. Nunc tempor, sem non feugiat vehicula, augue arcu feugiat ligula, quis efficitur nulla dui non magna. Mauris leo erat, suscipit id elit quis, sodales varius lacus. Ut tempus dignissim elit ut blandit. Aenean et dui ut metus lacinia ullamcorper quis non nisi. Etiam tincidunt sagittis scelerisque. Fusce consectetur accumsan sem non consequat. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Aenean ac sapien pharetra, aliquam leo sit amet, suscipit felis. Vivamus id malesuada justo. Quisque ultricies tortor sed massa sodales sodales.
<Tabs orientation="vertical" className="flex items-start gap-2">
  <TabList
    aria-label="Tabs"
    className="ml-2 flex w-fit flex-1 flex-col gap-2 border-l-2 border-gray-100 pl-1"
  >
    {data.tabItems?.map((item, index) => (
      <Tab
        className="data-[selected=true]:text-primary-600 data-[selected=true]:before:bg-primary-600 data-[selected=true]:hover:bg-primary-100 focus-ring-inverse relative flex w-max flex-1 cursor-pointer gap-2.5 rounded-md px-2 py-1 font-semibold text-gray-600 before:absolute before:top-0 before:bottom-0 before:-left-1.5 before:h-full before:w-[2px] before:bg-transparent hover:bg-gray-100 hover:before:bg-gray-600 focus-visible:ring-2"
        key={index}
        id={index}
      >
        <RiFoldersLine aria-hidden="true" />
        {item.title}
      </Tab>
    ))}
  </TabList>
  <TabPanels>
    {data.tabItems?.map((item, index) => (
      <TabPanel
        id={index}
        key={index}
        shouldForceMount={true}
        className="focus-ring data-[inert=true]:hidden"
      >
        {item.content}
      </TabPanel>
    ))}
  </TabPanels>
</Tabs>