Tabs

Navigate between views within a context.

Basic Tabs

Content for Tab 1. This panel is active by default.

Content for Tab 2. Click the tab to see this content.

Content for Tab 3. Use tabs to organize related content.

<div class="ui-tabs" data-ui-tabs>
  <div class="ui-tabs__list" role="tablist">
    <button class="ui-tabs__trigger" data-ui-tab="tab1">Tab 1</button>
    <button class="ui-tabs__trigger" data-ui-tab="tab2">Tab 2</button>
    <button class="ui-tabs__trigger" data-ui-tab="tab3">Tab 3</button>
  </div>
  <div class="ui-tabs__content">
    <div id="tab1" class="ui-tabs__panel ui-tabs__panel--active">Content 1</div>
    <div id="tab2" class="ui-tabs__panel">Content 2</div>
    <div id="tab3" class="ui-tabs__panel">Content 3</div>
  </div>
</div>
<div class="ui-tabs" data-ui-tabs>
  <div class="ui-tabs__list" role="tablist">
    <button class="ui-tabs__trigger"
            data-ui-tab="tab1"
            ng-click="onTabChange('tab1')">{{ tabs[0].label }}</button>
    <button class="ui-tabs__trigger"
            data-ui-tab="tab2"
            ng-click="onTabChange('tab2')">{{ tabs[1].label }}</button>
  </div>
  <div class="ui-tabs__content">
    <div id="tab1" class="ui-tabs__panel ui-tabs__panel--active">{{ tabs[0].content }}</div>
    <div id="tab2" class="ui-tabs__panel">{{ tabs[1].content }}</div>
  </div>
</div>
<div class="ui-tabs" data-ui-tabs>
  <div class="ui-tabs__list" role="tablist">
    <button class="ui-tabs__trigger"
            data-ui-tab="tab1"
            (click)="onTabChange('tab1')">{{ tabs[0].label }}</button>
    <button class="ui-tabs__trigger"
            data-ui-tab="tab2"
            (click)="onTabChange('tab2')">{{ tabs[1].label }}</button>
  </div>
  <div class="ui-tabs__content">
    <div id="tab1" class="ui-tabs__panel ui-tabs__panel--active">{{ tabs[0].content }}</div>
    <div id="tab2" class="ui-tabs__panel">{{ tabs[1].content }}</div>
  </div>
</div>
<div className="ui-tabs" data-ui-tabs>
  <div className="ui-tabs__list" role="tablist">
    <button className="ui-tabs__trigger"
            data-ui-tab="tab1"
            onClick={() => handleTabChange('tab1')}>{tabs[0].label}</button>
    <button className="ui-tabs__trigger"
            data-ui-tab="tab2"
            onClick={() => handleTabChange('tab2')}>{tabs[1].label}</button>
  </div>
  <div className="ui-tabs__content">
    <div id="tab1" className="ui-tabs__panel ui-tabs__panel--active">{tabs[0].content}</div>
    <div id="tab2" className="ui-tabs__panel">{tabs[1].content}</div>
  </div>
</div>

Pill Tabs

Add the ui-tabs--pills modifier for pill-style tabs.

Overview content
Details content
Settings content
<div class="ui-tabs ui-tabs--pills" data-ui-tabs>
  <div class="ui-tabs__list" role="tablist">
    <button class="ui-tabs__trigger" data-ui-tab="pill1">Overview</button>
    <button class="ui-tabs__trigger" data-ui-tab="pill2">Details</button>
    <button class="ui-tabs__trigger" data-ui-tab="pill3">Settings</button>
  </div>
  <div class="ui-tabs__content">
    <div id="pill1" class="ui-tabs__panel ui-tabs__panel--active">Overview content</div>
    <div id="pill2" class="ui-tabs__panel">Details content</div>
    <div id="pill3" class="ui-tabs__panel">Settings content</div>
  </div>
</div>

Events

Tabs emit custom events that you can listen to.

Event Description
ui:tabs:change Fired before tab change (cancelable)
ui:tabs:changed Fired after tab changed
document.addEventListener('ui:tabs:changed', (e) => {
  console.log('Tab changed:', e.detail);
});
// In your controller
angular.module('app').controller('TabsCtrl', function($scope, $document) {
  $document[0].addEventListener('ui:tabs:changed', function(e) {
    $scope.$apply(function() {
      $scope.activeTab = e.detail.tabId;
      console.log('Tab changed:', e.detail);
    });
  });
});
import { Component, OnInit, OnDestroy } from '@angular/core';

@Component({ ... })
export class TabsComponent implements OnInit, OnDestroy {
  activeTab: string;
  private changeHandler = (e: CustomEvent) => {
    this.activeTab = e.detail.tabId;
    console.log('Tab changed:', e.detail);
  };

  ngOnInit() {
    document.addEventListener('ui:tabs:changed', this.changeHandler);
  }

  ngOnDestroy() {
    document.removeEventListener('ui:tabs:changed', this.changeHandler);
  }
}
import { useEffect, useState } from 'react';

function TabsExample() {
  const [activeTab, setActiveTab] = useState('tab1');

  useEffect(() => {
    const handleChange = (e) => {
      setActiveTab(e.detail.tabId);
      console.log('Tab changed:', e.detail);
    };

    document.addEventListener('ui:tabs:changed', handleChange);
    return () => document.removeEventListener('ui:tabs:changed', handleChange);
  }, []);

  return ( /* ... */ );
}

Data Attributes

Attribute Description
data-ui-tabs Marks container as a tabs component (required)
data-ui-tab="panelId" Links trigger to panel by ID (without #)

CSS Classes Reference

Class Description
.ui-tabs Base tabs container
.ui-tabs--pills Pill-style variant
.ui-tabs__list Tab button container
.ui-tabs__trigger Individual tab button
.ui-tabs__trigger--active Active tab state
.ui-tabs__content Tab panels container
.ui-tabs__panel Individual tab panel (hidden by default)
.ui-tabs__panel--active Active panel state (visible)

Accessibility

  • Use role="tablist" on the tab list container
  • Use role="tab" on tab buttons
  • Use role="tabpanel" on content panels
  • Keyboard navigation: Arrow keys to move between tabs
  • Enter/Space to activate a tab