Basic Tabs

Standard Tabs

Simple tab navigation with underline indicator.

This is the overview content. It provides a high-level summary of the main topic.

Features content goes here. List the key capabilities and benefits.

Settings panel with configuration options and preferences.

<div class="tabs" role="tablist">
  <button class="tab active" role="tab" aria-selected="true">Overview</button>
  <button class="tab" role="tab" aria-selected="false">Features</button>
  <button class="tab" role="tab" aria-selected="false">Settings</button>
</div>
<div class="tab-panels">
  <div class="tab-panel active" role="tabpanel">Content...</div>
</div>

Tab Variants

Pill Tabs

Contained style with background highlight.

<div class="tabs tabs-pill" role="tablist">
  <button class="tab active">Daily</button>
  <button class="tab">Weekly</button>
  <button class="tab">Monthly</button>
</div>

Boxed Tabs

Bordered container with elevated active state.

<div class="tabs tabs-boxed" role="tablist">
  <button class="tab active">All</button>
  <button class="tab">Active</button>
</div>

Tabs with Icons

Icon + Label

Icons provide visual context alongside text labels.

<button class="tab active">
  <svg>...</svg>
  Profile
</button>

Icon Only

Compact tabs using only icons (with aria-label for accessibility).

<div class="tabs tabs-icon-only">
  <button class="tab active" aria-label="Grid view">
    <svg>...</svg>
  </button>
</div>

Tabs with Badge

Count Badges

Show item counts or notification indicators.

<button class="tab active">
  Inbox
  <span class="tab-badge">12</span>
</button>

<!-- Dot indicator -->
<button class="tab">
  Spam
  <span class="tab-badge tab-badge-dot"></span>
</button>

CSS Implementation

/* Base Tabs */
.tabs {
  display: flex;
  gap: var(--space-1);
  border-bottom: 1px solid var(--border-subtle);
  padding-bottom: 1px;
}

.tab {
  display: inline-flex;
  align-items: center;
  gap: var(--space-2);
  padding: var(--space-3) var(--space-4);
  font-family: var(--font-body);
  font-size: var(--text-sm);
  font-weight: var(--font-weight-medium);
  color: var(--text-muted);
  background: transparent;
  border: none;
  border-bottom: 2px solid transparent;
  margin-bottom: -2px;
  cursor: pointer;
  transition: all var(--duration-fast) var(--ease-ease-out);
}

.tab:hover {
  color: var(--text-primary);
}

.tab.active {
  color: var(--accent-text);
  border-bottom-color: var(--accent-primary);
}

/* Pill Variant */
.tabs-pill {
  border-bottom: none;
  background: var(--bg-secondary);
  padding: var(--space-1);
  border-radius: var(--radius-lg);
  gap: var(--space-1);
}

.tabs-pill .tab {
  border-bottom: none;
  margin-bottom: 0;
  border-radius: var(--radius-md);
  padding: var(--space-2) var(--space-4);
}

.tabs-pill .tab.active {
  background: var(--bg-elevated);
  color: var(--text-primary);
  box-shadow: var(--shadow-sm);
}

/* Boxed Variant */
.tabs-boxed {
  border: 1px solid var(--border-subtle);
  border-radius: var(--radius-lg);
  padding: var(--space-1);
  background: var(--bg-secondary);
}

.tabs-boxed .tab {
  border-bottom: none;
  margin-bottom: 0;
  border-radius: var(--radius-md);
}

.tabs-boxed .tab.active {
  background: var(--bg-elevated);
  box-shadow: var(--shadow-sm);
}

/* Icon Only */
.tabs-icon-only .tab {
  padding: var(--space-2);
}

/* Tab Badge */
.tab-badge {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-width: 18px;
  height: 18px;
  padding: 0 var(--space-1);
  font-size: var(--text-2xs);
  font-weight: var(--font-weight-semibold);
  background: var(--bg-tertiary);
  border-radius: var(--radius-full);
}

.tab.active .tab-badge {
  background: var(--accent-subtle);
  color: var(--accent-text);
}

.tab-badge-dot {
  width: 8px;
  height: 8px;
  min-width: 8px;
  padding: 0;
  background: var(--error);
}

/* Tab Panels */
.tab-panels {
  padding: var(--space-6) 0;
}

.tab-panel {
  display: none;
}

.tab-panel.active {
  display: block;
  animation: tab-fade-in var(--duration-normal) var(--ease-ease-out);
}

@keyframes tab-fade-in {
  from { opacity: 0; transform: translateY(4px); }
  to { opacity: 1; transform: translateY(0); }
}

Accessibility

Keyboard Navigation

Arrow keys move between tabs. Home/End jump to first/last tab. Enter/Space activates.

ARIA Roles

Use role="tablist" on container, role="tab" on buttons, role="tabpanel" on content.

Selection State

aria-selected="true" on active tab, aria-selected="false" on others.

Icon-Only Labels

Always include aria-label on icon-only tabs to describe their purpose.