Chevron left

Components

Tabs

Theme

Themes/hound/logo.svg

Hound

Framework

Tailwind CSS logo

Tailwind CSS

Quicklinks

Quickly navigate to different tab patterns below

Tabs

Simple

Some activities...
<div data-controller="tabs"
    data-tabs-active-tab="border-b border-indigo-600 inline-block bg-white text-indigo-600 dark:bg-slate-700 dark:text-white dark:border-indigo-400 rounded-t"
    >
  <div class="border-slate-200 border-b text-slate-600 dark:text-slate-100 dark:border-slate-600 font-medium text-sm">
    <nav role="navigation" class="-mb-px">
      <a href="#" data-tabs-target="tab" data-action="click->tabs#change" class="py-3 px-4 border-b border-indigo-600 inline-block bg-white whitespace-nowrap dark:bg-slate-900">Activity</a>
      <a href="#" data-tabs-target="tab" data-action="click->tabs#change" class="py-3 px-4 bg-white dark:bg-slate-900 inline-block whitespace-nowrap">Account</a>
      <a href="#" data-tabs-target="tab" data-action="click->tabs#change" class="py-3 px-4 bg-white dark:bg-slate-900 inline-block whitespace-nowrap">Billing</a>
      <a href="#" data-tabs-target="tab" data-action="click->tabs#change" class="py-3 px-4 bg-white dark:bg-slate-900 inline-block whitespace-nowrap">Team</a>
    </nav>
  </div>
   <div class="p-4" data-tabs-target="panel">
    Some activities...
  </div>

  <div class="hidden p-4" data-tabs-target="panel">
    Account information...
  </div>

  <div class="hidden p-4" data-tabs-target="panel">
    Billing information...
  </div>
  <div class="hidden p-4" data-tabs-target="panel">
    Team information...
  </div>
</div>
<div data-controller="tabs"
    data-tabs-active-tab="border-b border-indigo-600 inline-block bg-white text-indigo-600 dark:bg-slate-700 dark:text-white dark:border-indigo-400 rounded-t">
  <div class="border-slate-200 border-b text-slate-600 dark:text-slate-100 dark:border-slate-600 font-medium text-sm">
    <nav role="navigation" class="-mb-px">
      <%= link_to "Activity", "#", data: { action: "click-tabs#change", tabs_target: "tab" }, class: "py-3 px-4 border-b border-indigo-600 inline-block bg-white whitespace-nowrap dark:bg-slate-900" %>
      <%= link_to "Account", "#", data: { action: "click-tabs#change", tabs_target: "tab"}, class: "py-3 px-4 bg-white inline-block whitespace-nowrap dark:bg-slate-900" %>
      <%= link_to "Billing", "#", data: { action: "click-tabs#change", tabs_target: "tab"}, class: "py-3 px-4 bg-white inline-block whitespace-nowrap dark:bg-slate-900" %>
      <%= link_to "Team", "#", data: { action: "click-tabs#change", tabs_target: "tab" }, class: "py-3 px-4 bg-white inline-block whitespace-nowrap dark:bg-slate-900" %>
    </nav>
  </div>
   <div class="p-4" data-tabs-target="panel">
    Some activities...
  </div>

  <div class="hidden p-4" data-tabs-target="panel">
    Account information...
  </div>

  <div class="hidden p-4" data-tabs-target="panel">
    Billing information...
  </div>
  <div class="hidden p-4" data-tabs-target="panel">
    Team information...
  </div>
</div>
%div{"data-controller" => "tabs", "data-tabs-active-tab" => "border-b border-indigo-600 inline-block bg-white text-indigo-600 dark:bg-slate-700 dark:text-white dark:border-indigo-400 rounded-t"}
  .border-slate-200.border-b.text-slate-600.font-medium.text-sm.dark:text-slate-100.dark:border-slate-600
    %nav.-mb-px{role: "navigation"}
      = link_to "Activity", "#", data: { action: "click-tabs#change", tabs_target: "tab" }, class: "py-3 px-4 border-b border-indigo-600 inline-block bg-white whitespace-nowrap dark:bg-slate-900"
      = link_to "Account", "#", data: { action: "click-tabs#change", tabs_target: "tab"}, class: "py-3 px-4 bg-white inline-block whitespace-nowrap dark:bg-slate-900"
      = link_to "Billing", "#", data: { action: "click-tabs#change", tabs_target: "tab"}, class: "py-3 px-4 bg-white inline-block whitespace-nowrap dark:bg-slate-900"
      = link_to "Team", "#", data: { action: "click-tabs#change", tabs_target: "tab" }, class: "py-3 px-4 bg-white inline-block whitespace-nowrap dark:bg-slate-900"
  .p-4{"data-tabs-target" => "panel"}
    Some activities...
  .hidden.p-4{"data-tabs-target" => "panel"}
    Account information...
  .hidden.p-4{"data-tabs-target" => "panel"}
    Billing information...
  .hidden.p-4{"data-tabs-target" => "panel"}
    Team information...
// Credits to @excid3 and crew
// https://github.com/excid3/tailwindcss-stimulus-components/graphs/contributors

import { Controller } from '@hotwired/stimulus'

export default class extends Controller {
  static targets = ['tab', 'panel']

  connect() {
    this.activeTabClasses = (this.data.get('activeTab') || 'active').split(' ')
    this.inactiveTabClasses = (this.data.get('inactiveTab') || 'inactive').split(' ')
    if (this.anchor) this.index = this.tabTargets.findIndex((tab) => tab.id === this.anchor)
    this.showTab()
  }

  change(event) {
    event.preventDefault()

    // If target specifies an index, use that
    if (event.currentTarget.dataset.index) {
      this.index = event.currentTarget.dataset.index

    // If target specifies an id, use that
    } else if (event.currentTarget.dataset.id) {
      this.index = this.tabTargets.findIndex((tab) => tab.id == event.currentTarget.dataset.id)

    // Otherwise, use the index of the current target
    } else {
      this.index = this.tabTargets.indexOf(event.currentTarget)
    }

    window.dispatchEvent(new CustomEvent('tsc:tab-change'))
  }

  showTab() {
    this.tabTargets.forEach((tab, index) => {
      const panel = this.panelTargets[index]

      if (index === this.index) {
        panel.classList.remove('hidden')
        tab.classList.remove(...this.inactiveTabClasses)
        tab.classList.add(...this.activeTabClasses)

        // Update URL with the tab ID if it has one
        // This will be automatically selected on page load
        if (tab.id) {
          location.hash = tab.id
        }
      } else {
        panel.classList.add('hidden')
        tab.classList.remove(...this.activeTabClasses)
        tab.classList.add(...this.inactiveTabClasses)
      }
    })
  }

  get index() {
    return parseInt(this.data.get('index') || 0)
  }

  set index(value) {
    this.data.set('index', (value >= 0 ? value : 0))
    this.showTab()
  }

  get anchor() {
    return (document.URL.split('#').length > 1) ? document.URL.split('#')[1] : null;
  }
}

Tabs

Pills

Some activities...
<div
  data-controller="tabs"
  data-tabs-active-tab="py-3 px-4 bg-indigo-50 inline-block rounded-full text-indigo-600 dark:bg-indigo-600 dark:text-white"
  data-tabs-inactive-tab="py-3 px-4 rounded-full inline-block dark:bg-slate-900 dark:text-slate-300">
  <div class="text-slate-600 dark:text-slate-300">
    <nav role="navigation" class="flex items-center space-x-1 font-medium text-sm">
      <a href="#" data-tabs-target="tab" data-action="click->tabs#change" class="py-3 px-4 bg-indigo-50 inline-block rounded-full text-indigo-600 dark:bg-indigo-600 dark:text-white">Activity</a>
      <a href="#" data-tabs-target="tab" data-action="click->tabs#change" class="py-3 px-4 font-medium rounded-full inline-block dark:bg-slate-900">Account</a>
      <a href="#" data-tabs-target="tab" data-action="click->tabs#change" class="py-3 px-4 font-medium rounded-full inline-block dark:bg-slate-900">Billing</a>
      <a href="#" data-tabs-target="tab" data-action="click->tabs#change" class="py-3 px-4 font-medium rounded-full inline-block dark:bg-slate-900">Team</a>
    </nav>
  </div>
   <div class="p-4" data-tabs-target="panel">
    Some activities...
  </div>

  <div class="hidden p-4" data-tabs-target="panel">
    Account information...
  </div>

  <div class="hidden p-4" data-tabs-target="panel">
    Billing information...
  </div>
  <div class="hidden p-4" data-tabs-target="panel">
    Team information...
  </div>
</div>
<div
  data-controller="tabs"
  data-tabs-active-tab="py-3 px-4 bg-indigo-50 inline-block rounded-full text-indigo-600 dark:bg-indigo-600 dark:text-white"
  data-tabs-inactive-tab="py-3 px-4 rounded-full inline-block dark:bg-slate-900 dark:text-slate-300">
  <div class="text-slate-600 dark:text-slate-300">
    <nav role="navigation" class="flex items-center space-x-1 font-medium text-sm">
      <%= link_to "Activity", "#", class: "py-3 px-4 bg-indigo-50 inline-block rounded-full text-indigo-600 dark:bg-indigo-600 dark:text-white", data: { action: "click->tabs#change", tabs_target: "tab" } %>
      <%= link_to "Account", "#", class: "py-3 px-4 font-medium rounded", data: { action: "click->tabs#change", tabs_target: "tab" } %>
      <%= link_to "Billing", "#", class: "py-3 px-4 font-medium rounded", data: { action: "click->tabs#change", tabs_target: "tab" } %>
      <%= link_to "Team", "#", class: "py-3 px-4 font-medium rounded", data: { action: "click->tabs#change", tabs_target: "tab" } %>
    </nav>
  </div>
   <div class="p-4" data-tabs-target="panel">
    Some activities...
  </div>

  <div class="hidden p-4" data-tabs-target="panel">
    Account information...
  </div>

  <div class="hidden p-4" data-tabs-target="panel">
    Billing information...
  </div>
  <div class="hidden p-4" data-tabs-target="panel">
    Team information...
  </div>
</div>
%div{"data-controller" => "tabs", "data-tabs-active-tab" => "py-3 px-4 bg-indigo-50 inline-block rounded-full text-indigo-600 dark:bg-indigo-600 dark:text-white", "data-tabs-inactive-tab" => "py-3 px-4 rounded-full inline-block dark:bg-slate-900 dark:text-slate-300"}
  .text-slate-600.dark:text-slate-300
    %nav.flex.items-center.space-x-1.font-medium.text-sm{role: "navigation"}
      = link_to "Activity", "#", class: "py-3 px-4 bg-indigo-50 inline-block rounded-full text-indigo-600 dark:bg-indigo-600 dark:text-white", data: { action: "click->tabs#change", tabs_target: "tab" }
      = link_to "Account", "#", class: "py-3 px-4 font-medium rounded", data: { action: "click->tabs#change", tabs_target: "tab" }
      = link_to "Billing", "#", class: "py-3 px-4 font-medium rounded", data: { action: "click->tabs#change", tabs_target: "tab" }
      = link_to "Team", "#", class: "py-3 px-4 font-medium rounded", data: { action: "click->tabs#change", tabs_target: "tab" }
  .p-4{"data-tabs-target" => "panel"}
    Some activities...
  .hidden.p-4{"data-tabs-target" => "panel"}
    Account information...
  .hidden.p-4{"data-tabs-target" => "panel"}
    Billing information...
  .hidden.p-4{"data-tabs-target" => "panel"}
    Team information...
// Credit @excid3 and crew
// https://github.com/excid3/tailwindcss-stimulus-components/graphs/contributors

import { Controller } from '@hotwired/stimulus'

export default class extends Controller {
  static targets = ['tab', 'panel']

  connect() {
    this.activeTabClasses = (this.data.get('activeTab') || 'active').split(' ')
    this.inactiveTabClasses = (this.data.get('inactiveTab') || 'inactive').split(' ')
  }

  change(event) {
    event.preventDefault()

    // If target specifies an index, use that
    if (event.currentTarget.dataset.index) {
      this.index = event.currentTarget.dataset.index

    // If target specifies an id, use that
    } else if (event.currentTarget.dataset.id) {
      this.index = this.tabTargets.findIndex((tab) => tab.id == event.currentTarget.dataset.id)

    // Otherwise, use the index of the current target
    } else {
      this.index = this.tabTargets.indexOf(event.currentTarget)
    }
  }

  showTab() {
    this.tabTargets.forEach((tab, index) => {
      const panel = this.panelTargets[index]

      if (index === this.index) {
        panel.classList.remove('hidden')
        tab.classList.remove(...this.inactiveTabClasses)
        tab.classList.add(...this.activeTabClasses)
      } else {
        panel.classList.add('hidden')
        tab.classList.remove(...this.activeTabClasses)
        tab.classList.add(...this.inactiveTabClasses)
      }
    })
  }

  get index() {
    return parseInt(this.data.get('index') || 0)
  }

  set index(value) {
    this.data.set('index', (value >= 0 ? value : 0))
    this.showTab()
  }
}

Tabs

Rounded

Some activities...
<div
  data-controller="tabs"
  data-tabs-active-tab="py-3 px-4 bg-indigo-50 inline-block rounded-md text-indigo-600 dark:bg-indigo-600 dark:text-white"
  data-tabs-inactive-tab="py-3 px-4 rounded-md inline-block dark:bg-slate-900 dark:text-slate-300">
  <div>
    <nav role="navigation" class="flex items-center text-gray-600 space-x-1 font-medium text-sm">
      <a href="#" data-tabs-target="tab" data-action="click->tabs#change" class="py-3 px-4 bg-indigo-50 inline-block rounded-md text-indigo-600 dark:bg-indigo-600 dark:text-white">Activity</a>
      <a href="#" data-tabs-target="tab" data-action="click->tabs#change" class="py-3 px-4 font-medium rounded-md inline-block dark:bg-slate-900">Account</a>
      <a href="#" data-tabs-target="tab" data-action="click->tabs#change" class="py-3 px-4 font-medium rounded-md inline-block dark:bg-slate-900">Billing</a>
      <a href="#" data-tabs-target="tab" data-action="click->tabs#change" class="py-3 px-4 font-medium rounded-md inline-block dark:bg-slate-900">Team</a>
    </nav>
  </div>
   <div class="p-4" data-tabs-target="panel">
    Some activities...
  </div>

  <div class="hidden p-4" data-tabs-target="panel">
    Account information...
  </div>

  <div class="hidden p-4" data-tabs-target="panel">
    Billing information...
  </div>
  <div class="hidden p-4" data-tabs-target="panel">
    Team information...
  </div>
</div>
<div
  data-controller="tabs"
  data-tabs-active-tab="py-3 px-4 bg-indigo-50 inline-block rounded-md text-indigo-600 dark:bg-indigo-600 dark:text-white"
  data-tabs-inactive-tab="py-3 px-4 rounded-md inline-block dark:bg-slate-900 dark:text-slate-300">
  <div>
    <nav role="navigation" class="flex items-center text-gray-600 space-x-1 font-medium text-sm">
      <%= link_to "Activity", "#", class: "py-3 px-4 bg-indigo-50 inline-block rounded-md text-indigo-600 dark:bg-indigo-600 dark:text-white", data: { action: "click->tabs#change", tabs_target: "tab" } %>
      <%= link_to "Account", "#", class: "py-3 px-4 font-medium rounded-md inline-block dark:bg-slate-900", data: { action: "click->tabs#change", tabs_target: "tab" } %>
      <%= link_to "Billing", "#", class: "py-3 px-4 font-medium rounded-md inline-block dark:bg-slate-900", data: { action: "click->tabs#change", tabs_target: "tab" } %>
      <%= link_to "Team", "#", class: "py-3 px-4 font-medium rounded-md inline-block dark:bg-slate-900", data: { action: "click->tabs#change", tabs_target: "tab" } %>
    </nav>
  </div>
   <div class="p-4" data-tabs-target="panel">
    Some activities...
  </div>

  <div class="hidden p-4" data-tabs-target="panel">
    Account information...
  </div>

  <div class="hidden p-4" data-tabs-target="panel">
    Billing information...
  </div>
  <div class="hidden p-4" data-tabs-target="panel">
    Team information...
  </div>
</div>
%div{"data-controller" => "tabs", "data-tabs-active-tab" => "py-3 px-4 bg-indigo-50 inline-block rounded-md text-indigo-600 dark:bg-indigo-600 dark:text-white", "data-tabs-inactive-tab" => "py-3 px-4 rounded-md inline-block dark:bg-slate-900 dark:text-slate-300"}
  %div
    %nav.flex.items-center.text-gray-600.space-x-1.font-medium.text-sm{role: "navigation"}
      = link_to "Activity", "#", class: "py-3 px-4 bg-indigo-50 inline-block rounded-md text-indigo-600 dark:bg-indigo-600 dark:text-white", data: { action: "click->tabs#change", tabs_target: "tab" }
      = link_to "Account", "#", class: "py-3 px-4 font-medium rounded-md inline-block dark:bg-slate-900", data: { action: "click->tabs#change", tabs_target: "tab" }
      = link_to "Billing", "#", class: "py-3 px-4 font-medium rounded-md inline-block dark:bg-slate-900", data: { action: "click->tabs#change", tabs_target: "tab" }
      = link_to "Team", "#", class: "py-3 px-4 font-medium rounded-md inline-block dark:bg-slate-900", data: { action: "click->tabs#change", tabs_target: "tab" }
  .p-4{"data-tabs-target" => "panel"}
    Some activities...
  .hidden.p-4{"data-tabs-target" => "panel"}
    Account information...
  .hidden.p-4{"data-tabs-target" => "panel"}
    Billing information...
  .hidden.p-4{"data-tabs-target" => "panel"}
    Team information...
// Credit @excid3 and crew
// https://github.com/excid3/tailwindcss-stimulus-components/graphs/contributors

import { Controller } from '@hotwired/stimulus'

export default class extends Controller {
  static targets = ['tab', 'panel']

  connect() {
    this.activeTabClasses = (this.data.get('activeTab') || 'active').split(' ')
    this.inactiveTabClasses = (this.data.get('inactiveTab') || 'inactive').split(' ')
  }

  change(event) {
    event.preventDefault()

    // If target specifies an index, use that
    if (event.currentTarget.dataset.index) {
      this.index = event.currentTarget.dataset.index

    // If target specifies an id, use that
    } else if (event.currentTarget.dataset.id) {
      this.index = this.tabTargets.findIndex((tab) => tab.id == event.currentTarget.dataset.id)

    // Otherwise, use the index of the current target
    } else {
      this.index = this.tabTargets.indexOf(event.currentTarget)
    }
  }

  showTab() {
    this.tabTargets.forEach((tab, index) => {
      const panel = this.panelTargets[index]

      if (index === this.index) {
        panel.classList.remove('hidden')
        tab.classList.remove(...this.inactiveTabClasses)
        tab.classList.add(...this.activeTabClasses)
      } else {
        panel.classList.add('hidden')
        tab.classList.remove(...this.activeTabClasses)
        tab.classList.add(...this.inactiveTabClasses)
      }
    })
  }

  get index() {
    return parseInt(this.data.get('index') || 0)
  }

  set index(value) {
    this.data.set('index', (value >= 0 ? value : 0))
    this.showTab()
  }
}

Tabs

With icons

Some activities...
<div
  data-controller="tabs"
  data-tabs-active-tab="py-3 px-4 border-b border-indigo-600 flex items-center space-x-3 bg-white whitespace-nowrap text-indigo-600 dark:bg-indigo-600/70 dark:text-white dark:border-indigo-600 rounded-t"
  data-tabs-inactive-tab="py-3 px-4 flex items-center space-x-3 whitespace-nowrap border-b bg-white dark:bg-slate-900 dark:border-slate-600">

  <div class="border-slate-200 border-b text-slate-600 dark:text-slate-200 dark:border-slate-600 text-sm font-medium">
    <nav role="navigation" class="-mb-px flex items-center flex-wrap">
      <a href="#"
      data-tabs-target="tab" data-action="click->tabs#change"
      class="py-3 px-4 border-b border-indigo-500 flex items-center space-x-3 bg-white whitespace-nowrap text-indigo-600 dark:bg-indigo-600/70 dark:text-white dark:border-indigo-600 rounded-t">
        <%= icon "chat-bubble-oval-left-ellipsis", classes: "w-5 h-5" %>
        <span>Activity</span>
      </a>
      <a href="#" data-tabs-target="tab" data-action="click->tabs#change" class="py-3 px-4 flex items-center space-x-3 whitespace-nowrap border-b bg-white dark:bg-slate-900 dark:border-slate-600">
        <%= icon "user-circle", classes: "w-5 h-5" %>
        <span>Account</span>
      </a>
      <a href="#" data-tabs-target="tab" data-action="click->tabs#change" class="py-3 px-4 flex items-center space-x-3 whitespace-nowrap border-b bg-white dark:bg-slate-900 dark:border-slate-600">
        <%= icon "credit-card", classes: "w-5 h-5" %>
        <span>Billing</span>
      </a>
      <a href="#" data-tabs-target="tab" data-action="click->tabs#change" class="py-3 px-4 flex items-center space-x-3 whitespace-nowrap border-b bg-white dark:bg-slate-900 dark:border-slate-600">
        <%= icon "users", classes: "w-5 h-5" %>
        <span>Team</span>
      </a>
    </nav>
  </div>
   <div class="p-4" data-tabs-target="panel">
    Some activities...
  </div>

  <div class="hidden p-4" data-tabs-target="panel">
    Account information...
  </div>

  <div class="hidden p-4" data-tabs-target="panel">
    Billing information...
  </div>
  <div class="hidden p-4" data-tabs-target="panel">
    Team information...
  </div>
</div>
<div
  data-controller="tabs"
  data-tabs-active-tab="py-3 px-4 border-b border-indigo-600 flex items-center space-x-3 bg-white whitespace-nowrap text-indigo-600 dark:bg-indigo-600/70 dark:text-white dark:border-indigo-600 rounded-t"
  data-tabs-inactive-tab="py-3 px-4 flex items-center space-x-3 whitespace-nowrap border-b bg-white dark:bg-slate-900 dark:border-slate-600">

  <div class="border-slate-200 border-b text-slate-600 dark:text-slate-200 dark:border-slate-600 text-sm font-medium">
    <nav role="navigation" class="-mb-px flex items-center flex-wrap">
      <%= link_to "#", class: "py-3 px-4 border-b border-indigo-500 flex items-center space-x-3 bg-white whitespace-nowrap text-indigo-600 dark:bg-indigo-600/70 dark:text-white dark:border-indigo-600 rounded-t", data: { tabs_target: "tab", action: "click->tabs#change" } do %>
        <%= icon "chat-bubble-oval-left-ellipsis", classes: "w-5 h-5" %>
        <span>Activity</span>
      <% end %>
      <%= link_to "#", class: "py-3 px-4 flex items-center space-x-3 whitespace-nowrap border-b bg-white dark:bg-slate-900 dark:border-slate-600", data: {tabs_target: "tab", action: "click->tabs#change" } do %>
        <%= icon "user-circle", classes: "w-5 h-5" %>
        <span>Account</span>
      <% end %>
      <%= link_to "#", class: "py-3 px-4 flex items-center space-x-3 whitespace-nowrap border-b bg-white dark:bg-slate-900 dark:border-slate-600", data: {tabs_target: "tab", action: "click->tabs#change" } do %>
        <%= icon "credit-card", classes: "w-5 h-5" %>
        <span>Billing</span>
      <% end %>
      <%= link_to "#", class: "py-3 px-4 flex items-center space-x-3 whitespace-nowrap border-b bg-white dark:bg-slate-900 dark:border-slate-600", data: {tabs_target: "tab", action: "click->tabs#change" } do %>
        <%= icon "users", classes: "w-5 h-5" %>
        <span>Team</span>
      <% end %>
    </nav>
  </div>
   <div class="p-4" data-tabs-target="panel">
    Some activities...
  </div>

  <div class="hidden p-4" data-tabs-target="panel">
    Account information...
  </div>

  <div class="hidden p-4" data-tabs-target="panel">
    Billing information...
  </div>
  <div class="hidden p-4" data-tabs-target="panel">
    Team information...
  </div>
</div>
%div{"data-controller" => "tabs", "data-tabs-active-tab" => "py-3 px-4 border-b border-indigo-600 flex items-center space-x-3 bg-white whitespace-nowrap text-indigo-600 dark:bg-indigo-600/70 dark:text-white dark:border-indigo-600 rounded-t", "data-tabs-inactive-tab" => "py-3 px-4 flex items-center space-x-3 whitespace-nowrap border-b bg-white dark:bg-slate-900 dark:border-slate-600"}
  .border-slate-200.border-b.text-slate-600.dark:text-slate-200.dark:border-slate-600.text-sm.font-medium
    %nav.-mb-px.flex.items-center.flex-wrap{role: "navigation"}
      = link_to "#", class: "py-3 px-4 border-b border-indigo-500 flex items-center space-x-3 bg-white whitespace-nowrap text-indigo-600 dark:bg-indigo-600/70 dark:text-white dark:border-indigo-600 rounded-t", data: { tabs_target: "tab", action: "click->tabs#change" } do
        = icon "chat-bubble-oval-left-ellipsis", classes: "w-5 h-5"
        %span Activity
      = link_to "#", class: "py-3 px-4 flex items-center space-x-3 whitespace-nowrap border-b bg-white dark:bg-slate-900 dark:border-slate-600", data: {tabs_target: "tab", action: "click->tabs#change" } do
        = icon "user-circle", classes: "w-5 h-5"
        %span Account
      = link_to "#", class: "py-3 px-4 flex items-center space-x-3 whitespace-nowrap border-b bg-white dark:bg-slate-900 dark:border-slate-600", data: {tabs_target: "tab", action: "click->tabs#change" } do
        = icon "credit-card", classes: "w-5 h-5"
        %span Billing
      = link_to "#", class: "py-3 px-4 flex items-center space-x-3 whitespace-nowrap border-b bg-white dark:bg-slate-900 dark:border-slate-600", data: {tabs_target: "tab", action: "click->tabs#change" } do
        = icon "users", classes: "w-5 h-5"
        %span Team
  .p-4{"data-tabs-target" => "panel"}
    Some activities...
  .hidden.p-4{"data-tabs-target" => "panel"}
    Account information...
  .hidden.p-4{"data-tabs-target" => "panel"}
    Billing information...
  .hidden.p-4{"data-tabs-target" => "panel"}
    Team information...
// Credits to @excid3 and crew
// https://github.com/excid3/tailwindcss-stimulus-components/graphs/contributors

import { Controller } from '@hotwired/stimulus'

export default class extends Controller {
  static targets = ['tab', 'panel']

  connect() {
    this.activeTabClasses = (this.data.get('activeTab') || 'active').split(' ')
    this.inactiveTabClasses = (this.data.get('inactiveTab') || 'inactive').split(' ')
    if (this.anchor) this.index = this.tabTargets.findIndex((tab) => tab.id === this.anchor)
    this.showTab()
  }

  change(event) {
    event.preventDefault()

    // If target specifies an index, use that
    if (event.currentTarget.dataset.index) {
      this.index = event.currentTarget.dataset.index

    // If target specifies an id, use that
    } else if (event.currentTarget.dataset.id) {
      this.index = this.tabTargets.findIndex((tab) => tab.id == event.currentTarget.dataset.id)

    // Otherwise, use the index of the current target
    } else {
      this.index = this.tabTargets.indexOf(event.currentTarget)
    }

    window.dispatchEvent(new CustomEvent('tsc:tab-change'))
  }

  showTab() {
    this.tabTargets.forEach((tab, index) => {
      const panel = this.panelTargets[index]

      if (index === this.index) {
        panel.classList.remove('hidden')
        tab.classList.remove(...this.inactiveTabClasses)
        tab.classList.add(...this.activeTabClasses)

        // Update URL with the tab ID if it has one
        // This will be automatically selected on page load
        if (tab.id) {
          location.hash = tab.id
        }
      } else {
        panel.classList.add('hidden')
        tab.classList.remove(...this.activeTabClasses)
        tab.classList.add(...this.inactiveTabClasses)
      }
    })
  }

  get index() {
    return parseInt(this.data.get('index') || 0)
  }

  set index(value) {
    this.data.set('index', (value >= 0 ? value : 0))
    this.showTab()
  }

  get anchor() {
    return (document.URL.split('#').length > 1) ? document.URL.split('#')[1] : null;
  }
}

Tabs

Dark

Some activities...
<div data-controller="tabs"
    data-tabs-active-tab="py-3 px-4 border-b border-indigo-300 flex items-center space-x-3 whitespace-nowrap text-indigo-300"
    data-tabs-inactive-tab="py-3 px-4 bg-slate-800 flex items-center space-x-3 whitespace-nowrap border-b border-slate-700 dark:bg-transparent"
    >

  <div class="border-slate-200 border-b text-slate-300 font-medium text-sm">
    <nav role="navigation" class="-mb-px flex items-center flex-wrap">
      <a href="#" data-tabs-target="tab" data-action="click->tabs#change" class="py-3 px-4 border-b border-indigo-600 flex items-center space-x-3 bg-white whitespace-nowrap text-indigo-600">
        <%= icon "chat-bubble-oval-left-ellipsis", classes: "w-5 h-5" %>
        <span>Activity</span>
      </a>
      <a href="#" data-tabs-target="tab" data-action="click->tabs#change" class="py-3 px-4 bg-white flex items-center space-x-3 whitespace-nowrap border-b dark:bg-transparent">
        <%= icon "user-circle", classes: "w-5 h-5" %>
        <span>Account</span>
      </a>
      <a href="#" data-tabs-target="tab" data-action="click->tabs#change" class="py-3 px-4 bg-white flex items-center space-x-3 whitespace-nowrap border-b dark:bg-transparent">
        <%= icon "credit-card", classes: "w-5 h-5" %>
        <span>Billing</span>
      </a>
      <a href="#" data-tabs-target="tab" data-action="click->tabs#change" class="py-3 px-4 bg-white flex items-center space-x-3 whitespace-nowrap border-b dark:bg-transparent">
        <%= icon "users", classes: "w-5 h-5" %>
        <span>Team</span>
      </a>
    </nav>
  </div>
   <div class="p-4 text-slate-600" data-tabs-target="panel">
    Some activities...
  </div>

  <div class="hidden p-4 text-slate-600" data-tabs-target="panel">
    Account information...
  </div>

  <div class="hidden p-4 text-slate-600" data-tabs-target="panel">
    Billing information...
  </div>
  <div class="hidden p-4 text-slate-600" data-tabs-target="panel">
    Team information...
  </div>
</div>
<div data-controller="tabs"
    data-tabs-active-tab="py-3 px-4 border-b border-indigo-300 flex items-center space-x-3 whitespace-nowrap text-indigo-300"
    data-tabs-inactive-tab="py-3 px-4 bg-slate-800 flex items-center space-x-3 whitespace-nowrap border-b border-slate-700 dark:bg-transparent"
    >

  <div class="border-slate-200 border-b text-slate-300 font-medium text-sm">
    <nav role="navigation" class="-mb-px flex items-center flex-wrap">
      <%= link_to "#", class: "py-3 px-4 border-b border-indigo-600 flex items-center space-x-3 bg-white whitespace-nowrap text-indigo-600", data: { action: "click->tabs#change", tabs_target: "tab" } do %>
        <%= icon "chat-bubble-oval-left-ellipsis", classes: "w-5 h-5" %>
        <span>Activity</span>
      <% end %>
      <%= link_to "#", class: "py-3 px-4 bg-white flex items-center space-x-3 whitespace-nowrap border-b dark:bg-transparent", data: { action: "click->tabs#change", tabs_target: "tab" } %>
        <%= icon "user-circle", classes: "w-5 h-5" %>
        <span>Account</span>
      <% end %>
       <%= link_to "#", class: "py-3 px-4 bg-white flex items-center space-x-3 whitespace-nowrap border-b dark:bg-transparent", data: { action: "click->tabs#change", tabs_target: "tab" } %>
        <%= icon "credit-card", classes: "w-5 h-5" %>
        <span>Billing</span>
      <% end %>
       <%= link_to "#", class: "py-3 px-4 bg-white flex items-center space-x-3 whitespace-nowrap border-b dark:bg-transparent", data: { action: "click->tabs#change", tabs_target: "tab" } %>
        <%= icon "users", classes: "w-5 h-5" %>
        <span>Team</span>
      <% end %>
    </nav>
  </div>
   <div class="p-4" data-tabs-target="panel">
    Some activities...
  </div>

  <div class="hidden p-4" data-tabs-target="panel">
    Account information...
  </div>

  <div class="hidden p-4" data-tabs-target="panel">
    Billing information...
  </div>
  <div class="hidden p-4" data-tabs-target="panel">
    Team information...
  </div>
</div>
%div{"data-controller" => "tabs", "data-tabs-active-tab" => "py-3 px-4 border-b border-indigo-300 flex items-center space-x-3 whitespace-nowrap text-indigo-300", "data-tabs-inactive-tab" => "py-3 px-4 bg-slate-800 flex items-center space-x-3 whitespace-nowrap border-b border-slate-700 dark:bg-transparent"}
  .border-slate-200.border-b.text-slate-300.font-medium.text-sm
    %nav.-mb-px.flex.items-center.flex-wrap{role: "navigation"}
      = link_to "#", class: "py-3 px-4 border-b border-indigo-600 flex items-center space-x-3 bg-white whitespace-nowrap text-indigo-600", data: { action: "click->tabs#change", tabs_target: "tab" }
        = icon "chat-bubble-oval-left-ellipsis", classes: "w-5 h-5"
      %span Activity

      = link_to "#", class: "py-3 px-4 bg-white flex items-center space-x-3 whitespace-nowrap border-b dark:bg-transparent", data: { action: "click->tabs#change", tabs_target: "tab" }
        = icon "user-circle", classes: "w-5 h-5"
      %span Account

      = link_to "#", class: "py-3 px-4 bg-white flex items-center space-x-3 whitespace-nowrap border-b dark:bg-transparent", data: { action: "click->tabs#change", tabs_target: "tab" }
        = icon "credit-card", classes: "w-5 h-5"
      %span Billing

      = link_to "#", class: "py-3 px-4 bg-white flex items-center space-x-3 whitespace-nowrap border-b dark:bg-transparent", data: { action: "click->tabs#change", tabs_target: "tab" }
        = icon "users", classes: "w-5 h-5"
      %span Team

  .p-4{"data-tabs-target" => "panel"}
    Some activities...
  .hidden.p-4{"data-tabs-target" => "panel"}
    Account information...
  .hidden.p-4{"data-tabs-target" => "panel"}
    Billing information...
  .hidden.p-4{"data-tabs-target" => "panel"}
    Team information...
// Credits to @excid3 and crew
// https://github.com/excid3/tailwindcss-stimulus-components/graphs/contributors

import { Controller } from '@hotwired/stimulus'

export default class extends Controller {
  static targets = ['tab', 'panel']

  connect() {
    this.activeTabClasses = (this.data.get('activeTab') || 'active').split(' ')
    this.inactiveTabClasses = (this.data.get('inactiveTab') || 'inactive').split(' ')
    if (this.anchor) this.index = this.tabTargets.findIndex((tab) => tab.id === this.anchor)
    this.showTab()
  }

  change(event) {
    event.preventDefault()

    // If target specifies an index, use that
    if (event.currentTarget.dataset.index) {
      this.index = event.currentTarget.dataset.index

    // If target specifies an id, use that
    } else if (event.currentTarget.dataset.id) {
      this.index = this.tabTargets.findIndex((tab) => tab.id == event.currentTarget.dataset.id)

    // Otherwise, use the index of the current target
    } else {
      this.index = this.tabTargets.indexOf(event.currentTarget)
    }

    window.dispatchEvent(new CustomEvent('tsc:tab-change'))
  }

  showTab() {
    this.tabTargets.forEach((tab, index) => {
      const panel = this.panelTargets[index]

      if (index === this.index) {
        panel.classList.remove('hidden')
        tab.classList.remove(...this.inactiveTabClasses)
        tab.classList.add(...this.activeTabClasses)

        // Update URL with the tab ID if it has one
        // This will be automatically selected on page load
        if (tab.id) {
          location.hash = tab.id
        }
      } else {
        panel.classList.add('hidden')
        tab.classList.remove(...this.activeTabClasses)
        tab.classList.add(...this.inactiveTabClasses)
      }
    })
  }

  get index() {
    return parseInt(this.data.get('index') || 0)
  }

  set index(value) {
    this.data.set('index', (value >= 0 ? value : 0))
    this.showTab()
  }

  get anchor() {
    return (document.URL.split('#').length > 1) ? document.URL.split('#')[1] : null;
  }
}