Tabs

Summary

Tabbed navigation between sibling content panels. Two orientations (horizontal, vertical) and a disabled modifier for read-only step indicators. Tab switching is auto-bound on DOMContentLoaded; no JS is required for static markup.

When to use

VariantUse it for
Horizontal
.neura-tabs-horizontal
Top-level page sections: Overview / Details / History on a record page.
Vertical
.neura-tabs-vertical
Settings sub-navigation: Profile / Account / Notifications. Better when the menu has 4+ items.
Disabled
.neura-tabs-disabled
Read-only step indicator (e.g. wizard breadcrumbs). Clicks are ignored.

Examples

Click any tab to switch panes. Horizontal and vertical orientations behave identically; the disabled variant ignores clicks for read-only step indicators.

Horizontal tabs

First panel. Use arrow keys on the focused tab to switch via keyboard.

Second panel.

Third panel.

Vertical tabs

Profile settings - your display name, avatar, and bio.

Account settings - email, password, and connected services.

Notification preferences - email, push, in-app.

Security - two-factor authentication, sessions, API keys.

Disabled tabs

Disabled tabs - clicks are ignored. Used when tabs are read-only or sequential.

Step 2 content (unreachable while disabled).

Step 3 content (unreachable while disabled).

HTML

Markup contract: a .neura-tabs-menu with one .neura-tabs-menu-item per tab, followed by one .neura-tabs-pane per item. Each link's href matches the pane's id. Mark the initially-active tab with .active-tab and the matching pane with .active-pane.

<div class="neura-tabs neura-tabs-horizontal">
  <ul class="neura-tabs-menu">
    <li class="neura-tabs-menu-item active-tab">
      <a href="#h-tab-1"><strong>Overview</strong></a>
    </li>
    <li class="neura-tabs-menu-item">
      <a href="#h-tab-2"><strong>Details</strong></a>
    </li>
    <li class="neura-tabs-menu-item">
      <a href="#h-tab-3"><strong>History</strong></a>
    </li>
  </ul>
  <div id="h-tab-1" class="neura-tabs-pane active-pane">
    <p>First panel. Use arrow keys on the focused tab to switch via keyboard.</p>
  </div>
  <div id="h-tab-2" class="neura-tabs-pane">
    <p>Second panel.</p>
  </div>
  <div id="h-tab-3" class="neura-tabs-pane">
    <p>Third panel.</p>
  </div>
</div>

Vertical orientation changes only the modifier class:

<div class="neura-tabs neura-tabs-vertical">
  <ul class="neura-tabs-menu">
    <li class="neura-tabs-menu-item active-tab">
      <a href="#v-tab-1"><strong>Profile</strong></a>
    </li>
    <li class="neura-tabs-menu-item">
      <a href="#v-tab-2"><strong>Account</strong></a>
    </li>
    <li class="neura-tabs-menu-item">
      <a href="#v-tab-3"><strong>Notifications</strong></a>
    </li>
    <li class="neura-tabs-menu-item">
      <a href="#v-tab-4"><strong>Security</strong></a>
    </li>
  </ul>
  <div id="v-tab-1" class="neura-tabs-pane active-pane">
    <p>Profile settings - your display name, avatar, and bio.</p>
  </div>
  <div id="v-tab-2" class="neura-tabs-pane">
    <p>Account settings - email, password, and connected services.</p>
  </div>
  <div id="v-tab-3" class="neura-tabs-pane">
    <p>Notification preferences - email, push, in-app.</p>
  </div>
  <div id="v-tab-4" class="neura-tabs-pane">
    <p>Security - two-factor authentication, sessions, API keys.</p>
  </div>
</div>

To make tabs read-only / disabled, add .neura-tabs-disabled on the root:

<div class="neura-tabs neura-tabs-horizontal neura-tabs-disabled">
  <ul class="neura-tabs-menu">
    <li class="neura-tabs-menu-item active-tab">
      <a href="#d-tab-1"><strong>Step 1</strong></a>
    </li>
    <li class="neura-tabs-menu-item">
      <a href="#d-tab-2"><strong>Step 2</strong></a>
    </li>
    <li class="neura-tabs-menu-item">
      <a href="#d-tab-3"><strong>Step 3</strong></a>
    </li>
  </ul>
  <div id="d-tab-1" class="neura-tabs-pane active-pane">
    <p>Disabled tabs - clicks are ignored. Used when tabs are read-only or sequential.</p>
  </div>
  <div id="d-tab-2" class="neura-tabs-pane">
    <p>Step 2 content (unreachable while disabled).</p>
  </div>
  <div id="d-tab-3" class="neura-tabs-pane">
    <p>Step 3 content (unreachable while disabled).</p>
  </div>
</div>

CSS classes

ClassEffect
.neura-tabsRoot. Required.
.neura-tabs-horizontalTab strip on top, pane below.
.neura-tabs-verticalTab list on left, pane on right.
.neura-tabs-disabledModifier: clicks are ignored, cursor stays default.
.neura-tabs-menuThe <ul> wrapping the tab items.
.neura-tabs-menu-itemEach <li> in the menu.
.neura-tabs-paneEach panel that the tabs reveal.
.active-tabMarks the currently-selected tab item.
.active-paneMarks the currently-visible pane.

Keyboard

The tab strip uses a roving tabindex: only the active tab is in the Tab order. On a focused tab, ArrowRight / ArrowDown move to the next tab and ArrowLeft / ArrowUp to the previous one (wrapping); Home and End jump to the first / last tab. Moving activates the tab and focuses it. Horizontal arrows follow visual direction: in RTL, ArrowLeft means next.

JavaScript

Tabs auto-init on DOMContentLoaded; for static markup you don't need to write any JS. Use the API only when you want to switch tabs imperatively or react to switches.

API

MemberDescription
Neura.tabs(rootOrSelector)Get the singleton instance for a .neura-tabs root.
.activate(tabAnchor)Switch to a tab by its anchor element (<a> inside the menu item).
.activateById(paneId)Switch to a tab by its pane's id.
.on('change', fn)Fires after a tab switch. fn receives the CustomEvent with detail: { tab, pane } (the tab anchor and the pane element). The event also bubbles from the root as neura-tabs-change.
.off('change', fn)Unsubscribe.

Switch a tab imperatively (clicking the underlying link works too):

// By pane id…
Neura.tabs('#account-tabs').activateById('tab-2');
// …or by anchor element (or just click the link)
document.querySelector('.neura-tabs a[href="#tab-2"]').click();

React to tab switches (e.g. update the URL, lazy-load content):

Neura.tabs('#account-tabs').on('change', (e) => {
  history.replaceState(null, '', '#' + e.detail.pane.id);
  // or fetch and inject content into e.detail.pane, the pane just shown
});

AUI compatibility

.aui-tabs, .aui-tabs-horizontal, .aui-tabs-vertical, .aui-tabs-disabled, and the menu / pane / active-* selectors all alias to the Neura rules. AJS.tabs.setup() and AJS.tabs.change(tabAnchor) are wired through the shim. Existing Velocity templates render unchanged.