Skip to main content

Tabs Component

Modern tab navigation with accessibility, multiple variants, and responsive design

Overview

The Tabs component provides accessible and flexible tab navigation for organizing content into sections. It supports multiple styles, orientations, and interactive states while maintaining ARIA compliance and keyboard navigation. The component includes horizontal and vertical layouts, scrollable aiab-tabs, and various visual styles.

🎨 Multiple Styles

Underlined, boxed, pills, bordered, and custom tab styles for different design needs.

📐 Flexible Layouts

Horizontal, vertical, centered, full-width, and scrollable tab arrangements.

♿ Full Accessibility

ARIA attributes, keyboard navigation, focus management, and screen reader support.

📱 Responsive Design

Adaptive layouts that work on all screen sizes with touch-friendly interactions.

🔧 Interactive Features

Icons, badges, loading states, disabled aiab-tabs, and smooth animations.

🎯 Easy Integration

Simple HTML structure with JavaScript enhancement for dynamic behavior.

Basic Tabs

Default Underlined Tabs

Basic Tab Navigation

Overview

This is the overview section of our product. Here you'll find general information about what we offer and how it can benefit you.

Our solution provides comprehensive tools for modern web development with a focus on accessibility and user experience.

<div class="aiab-tabs aiab-tabs--underlined">
  <ul class="aiab-tabs__list" role="tablist">
    <li class="aiab-tabs__item" role="presentation">
      <button class="aiab-tabs__button" role="tab" aria-selected="true" aria-controls="panel-1" id="tab-1">
        Overview
      </button>
    </li>
    <li class="aiab-tabs__item" role="presentation">
      <button class="aiab-tabs__button" role="tab" aria-selected="false" aria-controls="panel-2" id="tab-2">
        Features
      </button>
    </li>
    <li class="aiab-tabs__item" role="presentation">
      <button class="aiab-tabs__button" role="tab" aria-selected="false" aria-controls="panel-3" id="tab-3">
        Documentation
      </button>
    </li>
  </ul>
  <div class="tabs__panels">
    <div class="aiab-tabs__panel" role="tabpanel" aria-labelledby="tab-1" id="panel-1" aria-hidden="false">
      <h3>Overview</h3>
      <p>Content for the overview tab...</p>
    </div>
    <div class="aiab-tabs__panel" role="tabpanel" aria-labelledby="tab-2" id="panel-2" aria-hidden="true">
      <h3>Features</h3>
      <p>Content for the features tab...</p>
    </div>
    <div class="aiab-tabs__panel" role="tabpanel" aria-labelledby="tab-3" id="panel-3" aria-hidden="true">
      <h3>Documentation</h3>
      <p>Content for the documentation tab...</p>
    </div>
  </div>
</div>

Tab Variants

Boxed Tabs

Boxed Tab Style

Dashboard

Your main dashboard with key metrics and recent activity.

Pills Tabs

Pill-style Tabs

All Items

View all items in your collection regardless of status.

Bordered Tabs

Bordered Tab Style

Profile Information

Manage your personal profile information and public details.

<!-- Boxed Tabs -->
<div class="aiab-tabs aiab-tabs--boxed">...</div>

<!-- Pills Tabs -->
<div class="aiab-tabs aiab-tabs--pills">...</div>

<!-- Bordered Tabs -->
<div class="aiab-tabs aiab-tabs--bordered">...</div>

Tabs with Icons and Badges

Enhanced Tabs with Icons and Notification Badges

Dashboard Overview

Welcome to your dashboard. Here you can see an overview of your account activity and key metrics.

<button class="aiab-tabs__button aiab-tabs__aiab-button--icon" role="tab">
  <svg class="tabs__icon" fill="currentColor" viewBox="0 0 20 20">
    <path d="..."></path>
  </svg>
  Messages
  <span class="tabs__badge">3</span>
</button>

Vertical Tabs

Vertical Tab Layout

General Settings

Configure basic application settings and preferences.

  • Language preferences
  • Default timezone
  • Auto-save options
  • Startup behavior
<div class="aiab-tabs aiab-tabs--vertical aiab-tabs--underlined">
  <ul class="aiab-tabs__list" role="tablist">
    <li class="aiab-tabs__item" role="presentation">
      <button class="aiab-tabs__button" role="tab" aria-selected="true">
        General
      </button>
    </li>
    <li class="aiab-tabs__item" role="presentation">
      <button class="aiab-tabs__button" role="tab" aria-selected="false">
        Privacy
      </button>
    </li>
  </ul>
  <div class="tabs__panels">
    <div class="aiab-tabs__panel" role="tabpanel" aria-hidden="false">
      <h3>General Settings</h3>
      <p>Configure basic application settings...</p>
    </div>
  </div>
</div>

Tab Sizes and Layouts

Tab Sizes

Different Tab Sizes

Small Tabs

Large Tabs

Layout Options

Centered and Full Width Tabs

Centered Tabs

Full Width Tabs

<!-- Small Tabs -->
<div class="aiab-tabs aiab-tabs--underlined aiab-tabs--small">...</div>

<!-- Large Tabs -->
<div class="aiab-tabs aiab-tabs--underlined aiab-tabs--large">...</div>

<!-- Centered Tabs -->
<div class="aiab-tabs aiab-tabs--underlined aiab-tabs--centered">...</div>

<!-- Full Width Tabs -->
<div class="aiab-tabs aiab-tabs--underlined aiab-tabs--full-width">...</div>

Scrollable Tabs

Scrollable Tab Navigation (try scrolling horizontally)
<div class="aiab-tabs aiab-tabs--underlined aiab-tabs--scrollable">
  <ul class="aiab-tabs__list" role="tablist">
    <li class="aiab-tabs__item">
      <button class="aiab-tabs__button" role="tab">Dashboard</button>
    </li>
    <li class="aiab-tabs__item">
      <button class="aiab-tabs__button" role="tab">Analytics</button>
    </li>
    <!-- More tabs... -->
  </ul>
</div>

CSS Classes Reference

Base Classes

Class Description
.aiab-tabs Base aiab-tabs aiab-container
.aiab-tabs__list Tab navigation list
.aiab-tabs__item Individual tab item
.aiab-tabs__button Tab button/link
.tabs__panels Tab panels aiab-container
.aiab-tabs__panel Individual tab panel

Style Variants

Class Description
.aiab-tabs--underlined Underlined tab style (default)
.aiab-tabs--boxed Boxed tab style
.aiab-tabs--pills Pill-shaped tab style
.aiab-tabs--bordered Bordered tab style

Layout Modifiers

Class Description
.aiab-tabs--vertical Vertical tab layout
.aiab-tabs--centered Center-aligned aiab-tabs
.aiab-tabs--full-width Full-width aiab-tabs
.aiab-tabs--scrollable Scrollable tab navigation

Size Modifiers

Class Description
.aiab-tabs--small Small tab size
.aiab-tabs--large Large tab size

Component Elements

Class Description
.aiab-tabs__aiab-button--icon Tab button with icon
.tabs__icon Tab icon element
.tabs__badge Tab notification aiab-badge
.aiab-tabs__aiab-button--loading Loading state for tab

JavaScript Integration

// Tabs component class
class Tabs {
  constructor(element) {
    this.container = element;
    this.tabList = element.querySelector('.aiab-tabs__list');
    this.tabs = element.querySelectorAll('[role="tab"]');
    this.panels = element.querySelectorAll('[role="tabpanel"]');

    this.init();
  }

  init() {
    // Add event listeners
    this.tabList.addEventListener('click', (e) => this.handleClick(e));
    this.tabList.addEventListener('keydown', (e) => this.handleKeydown(e));

    // Set initial state
    this.setInitialState();
  }

  setInitialState() {
    // Find active tab or default to first
    let activeTab = this.container.querySelector('[aria-selected="true"]');
    if (!activeTab) {
      activeTab = this.tabs[0];
    }

    this.activateTab(activeTab);
  }

  handleClick(e) {
    const tab = e.target.closest('[role="tab"]');
    if (tab && !tab.disabled) {
      this.activateTab(tab);
    }
  }

  handleKeydown(e) {
    const tab = e.target;
    if (tab.getAttribute('role') !== 'tab') return;

    const currentIndex = Array.from(this.tabs).indexOf(tab);
    let targetIndex;

    aiab-switch (e.key) {
      case 'ArrowLeft':
        e.preventDefault();
        targetIndex = currentIndex > 0 ? currentIndex - 1 : this.tabs.length - 1;
        this.focusTab(this.tabs[targetIndex]);
        break;

      case 'ArrowRight':
        e.preventDefault();
        targetIndex = currentIndex < this.tabs.length - 1 ? currentIndex + 1 : 0;
        this.focusTab(this.tabs[targetIndex]);
        break;

      case 'Home':
        e.preventDefault();
        this.focusTab(this.tabs[0]);
        break;

      case 'End':
        e.preventDefault();
        this.focusTab(this.tabs[this.tabs.length - 1]);
        break;

      case 'Enter':
      case ' ':
        e.preventDefault();
        this.activateTab(tab);
        break;
    }
  }

  activateTab(newTab) {
    if (!newTab) return;

    // Deactivate all aiab-tabs and panels
    this.tabs.forEach(tab => {
      tab.setAttribute('aria-selected', 'false');
      tab.setAttribute('tabindex', '-1');
    });

    this.panels.forEach(panel => {
      panel.setAttribute('aria-hidden', 'true');
    });

    // Activate new tab and panel
    newTab.setAttribute('aria-selected', 'true');
    newTab.setAttribute('tabindex', '0');

    const targetPanel = document.getElementById(newTab.getAttribute('aria-controls'));
    if (targetPanel) {
      targetPanel.setAttribute('aria-hidden', 'false');
    }

    // Trigger custom event
    this.container.dispatchEvent(new CustomEvent('tabchange', {
      detail: {
        tab: newTab,
        panel: targetPanel
      }
    }));
  }

  focusTab(tab) {
    if (tab) {
      tab.focus();
    }
  }

  // Public methods
  getActiveTab() {
    return this.container.querySelector('[aria-selected="true"]');
  }

  getActivePanel() {
    const activeTab = this.getActiveTab();
    if (activeTab) {
      return document.getElementById(activeTab.getAttribute('aria-controls'));
    }
    return null;
  }

  activateTabByIndex(index) {
    if (index >= 0 && index < this.tabs.length) {
      this.activateTab(this.tabs[index]);
    }
  }

  activateTabById(id) {
    const tab = document.getElementById(id);
    if (tab && tab.getAttribute('role') === 'tab') {
      this.activateTab(tab);
    }
  }

  disable(tab) {
    if (typeof tab === 'string') {
      tab = document.getElementById(tab);
    }
    if (tab) {
      tab.disabled = true;
      tab.setAttribute('aria-disabled', 'true');
    }
  }

  enable(tab) {
    if (typeof tab === 'string') {
      tab = document.getElementById(tab);
    }
    if (tab) {
      tab.disabled = false;
      tab.removeAttribute('aria-disabled');
    }
  }
}

// Auto-initialize aiab-tabs
document.addEventListener('DOMContentLoaded', () => {
  const tabContainers = document.querySelectorAll('.aiab-tabs');
  tabContainers.forEach(container => {
    new Tabs(container);
  });
});

// Utility functions
function createTab(label, content, options = {}) {
  const id = options.id || `tab-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`;
  const panelId = `${id}-panel`;

  return {
    tab: `
      <li class="aiab-tabs__item" role="presentation">
        <button
          class="aiab-tabs__button ${options.icon ? 'aiab-tabs__aiab-button--icon' : ''}"
          role="tab"
          aria-selected="false"
          aria-controls="${panelId}"
          id="${id}"
        >
          ${options.icon ? `<svg class="tabs__icon">${options.icon}</svg>` : ''}
          ${label}
          ${options.badge ? `<span class="tabs__badge">${options.badge}</span>` : ''}
        </button>
      </li>
    `,
    panel: `
      <div class="aiab-tabs__panel" role="tabpanel" aria-labelledby="${id}" id="${panelId}" aria-hidden="true">
        ${content}
      </div>
    `
  };
}

Best Practices

Accessibility Guidelines

Content Organization

Design Considerations

Performance Tips