0.0.3

Tabs

A pure vanilla JS implementation of Zag JS Tabs Opens in a new window


Anatomy

The Tabs component consists of the following data-part

It can include multiple trigger and content parts.

data-value is required on all trigger and content parts

root list trigger content

Lorem ipsum dolor sit amet, consectetur adipiscing elit.

Duis a sem ut diam interdum ultricies sit amet id arcu.

Donec pretium magna cursus ante tincidunt porta.

<div class="tabs tabs-js" data-default-value="lorem">
                  <div data-part="root">
                  <div data-part="list">
                  <button data-part="trigger" data-value="lorem">Lorem</button>
                  <button data-part="trigger" data-value="duis">Duis</button>
                  <button data-part="trigger" data-value="donec">Donec</button>
                  </div>
                  <div data-part="content" data-value="lorem">
                  <p>Lorem ipsum dolor sit amet, consectetur adipiscing elit.</p>
                  </div>
                  <div data-part="content" data-value="duis">
                  <p>Duis a sem ut diam interdum ultricies sit amet id arcu.
                  </p>
                  </div>
                  <div data-part="content" data-value="donec">
                  <p>Donec pretium magna cursus ante tincidunt porta.
                  </p>
                  </div>
                  </div>
                  </div>

Data attributes

Each tabs can be set with different settings with the following data-attribute.

Lorem ipsum dolor sit amet, consectetur adipiscing elit.

Duis a sem ut diam interdum ultricies sit amet id arcu.

Donec pretium magna cursus ante tincidunt porta.

<div class="tabs tabs-js" data-default-value="duis" data-loop-focus="true" data-orientation="vertical" data-dir="ltr" data-activation-mode="manual" data-composite="true" data-deselectable="false">
                  <div data-part="root">
                  <div data-part="list">
                  <button data-part="trigger" data-value="lorem">Lorem</button>
                  <button data-part="trigger" data-value="duis">Duis</button>
                  <button data-part="trigger" data-value="donec">Donec</button>
                  </div>
                  <div data-part="content" data-value="lorem">
                  <p>Lorem ipsum dolor sit amet, consectetur adipiscing elit.</p>
                  </div>
                  <div data-part="content" data-value="duis">
                  <p>Duis a sem ut diam interdum ultricies sit amet id arcu.
                  </p>
                  </div>
                  <div data-part="content" data-value="donec">
                  <p>Donec pretium magna cursus ante tincidunt porta.
                  </p>
                  </div>
                  </div>
                  </div>
Data attribute Type / Options Description
id string The unique id of the component. Default generated if none is provided
data-default-value string The initial selected tab value
data-value string The controlled selected tab value
data-orientation horizontal | vertical The orientation of the tabs. Can be `horizontal` or `vertical` - `horizontal`: only left and right arrow key navigation will work. - `vertical`: only up and down arrow key navigation will work.
data-dir ltr | rtl The orientation of the tabs. Can be `ltr` or `rtl`
data-loop-focus boolean Whether the keyboard navigation will loop from last tab to first, and vice versa.
data-activation-mode "manual", "automatic" The activation mode of the tabs. Can be `manual` or `automatic` - `manual`: Tabs are activated when clicked or press `enter` key. - `automatic`: Tabs are activated when receiving focus

Callbacks

Each Tabs component can receive callbacks that can be used to respond to user interaction with custom behavior.

You must add a custom id for the dialog and a event listener for your event name


                      document.getElementById("my-callback-tabs")
                      ?.addEventListener("my-callback-tabs-event", (event) => {
                        console.log("Received event:", (event as CustomEvent).detail);
                      });
                  

Lorem ipsum dolor sit amet, consectetur adipiscing elit.

Duis a sem ut diam interdum ultricies sit amet id arcu.

<div id="my-callback-tabs" class="tabs tabs-js" data-default-value="lorem" data-on-value-change="my-callback-tabs-event">
                  <div data-part="root">
                  <div data-part="list">
                  <button data-part="trigger" data-value="lorem">Lorem</button>
                  <button data-part="trigger" data-value="duis">Duis</button>
                  </div>
                  <div data-part="content" data-value="lorem">
                  <p>Lorem ipsum dolor sit amet, consectetur adipiscing elit.</p>
                  </div>
                  <div data-part="content" data-value="duis">
                  <p>Duis a sem ut diam interdum ultricies sit amet id arcu.
                  </p>
                  </div>
                  </div>
                  </div>

Open your browser's console to see the events received when select a tab

Data attribute Type / Options Description
data-on-value-change string Event name to be send when the selected/active tab changes
data-on-focus-change string Event name to be send when the focused tab changes
data-navigate string Event name to be send to navigate to the selected tab when clicking on it. Useful if tab triggers are anchor elements.

Modifier

Each tab can be styled with modifiers.

You can mix as many modifiers on the same button, however you can choose only one choice per modifer

For convenience the default variant name is omited, meaning there is no need to add the default name class

Modifier Option Description
Variant underline (default), accent Used for different semantic
Color base (default), brand, alert Use any semantic colors
Size md (default), sm, lg, xl Modify the size of the button.


Variant

Set the variant of each tab

Options: neutral(default), accent

Lorem ipsum dolor sit amet, consectetur adipiscing elit.

Duis a sem ut diam interdum ultricies sit amet id arcu.

Donec pretium magna cursus ante tincidunt porta.

Lorem ipsum dolor sit amet, consectetur adipiscing elit.

Duis a sem ut diam interdum ultricies sit amet id arcu.

Donec pretium magna cursus ante tincidunt porta.

<div>
                  <div class="tabs tabs-js" data-default-value="lorem">
                  <div data-part="root">
                  <div data-part="list">
                  <button data-part="trigger" data-value="lorem">Lorem</button>
                  <button data-part="trigger" data-value="duis">Duis</button>
                  <button data-part="trigger" data-value="donec">Donec</button>
                  </div>
                  <div data-part="content" data-value="lorem">
                  <p>Lorem ipsum dolor sit amet, consectetur adipiscing elit.</p>
                  </div>
                  <div data-part="content" data-value="duis">
                  <p>Duis a sem ut diam interdum ultricies sit amet id arcu.
                  </p>
                  </div>
                  <div data-part="content" data-value="donec">
                  <p>Donec pretium magna cursus ante tincidunt porta.
                  </p>
                  </div>
                  </div>
                  </div>
                  </div>
                  <div>
                  <div class="tabs tabs-js tabs--accent" data-default-value="lorem">
                  <div data-part="root">
                  <div data-part="list">
                  <button data-part="trigger" data-value="lorem">Lorem</button>
                  <button data-part="trigger" data-value="duis">Duis</button>
                  <button data-part="trigger" data-value="donec">Donec</button>
                  </div>
                  <div data-part="content" data-value="lorem">
                  <p>Lorem ipsum dolor sit amet, consectetur adipiscing elit.</p>
                  </div>
                  <div data-part="content" data-value="duis">
                  <p>Duis a sem ut diam interdum ultricies sit amet id arcu.
                  </p>
                  </div>
                  <div data-part="content" data-value="donec">
                  <p>Donec pretium magna cursus ante tincidunt porta.
                  </p>
                  </div>
                  </div>
                  </div>
                  </div>

Color

Set the color of each tabs

Options: base(default), brand, alert

Lorem ipsum dolor sit amet, consectetur adipiscing elit.

Duis a sem ut diam interdum ultricies sit amet id arcu.

Donec pretium magna cursus ante tincidunt porta.

Lorem ipsum dolor sit amet, consectetur adipiscing elit.

Duis a sem ut diam interdum ultricies sit amet id arcu.

Donec pretium magna cursus ante tincidunt porta.

Lorem ipsum dolor sit amet, consectetur adipiscing elit.

Duis a sem ut diam interdum ultricies sit amet id arcu.

Donec pretium magna cursus ante tincidunt porta.

Lorem ipsum dolor sit amet, consectetur adipiscing elit.

Duis a sem ut diam interdum ultricies sit amet id arcu.

Donec pretium magna cursus ante tincidunt porta.

<div>
                  <div class="tabs tabs-js tabs--brand" data-default-value="lorem">
                  <div data-part="root">
                  <div data-part="list">
                  <button data-part="trigger" data-value="lorem">Lorem</button>
                  <button data-part="trigger" data-value="duis">Duis</button>
                  <button data-part="trigger" data-value="donec">Donec</button>
                  </div>
                  <div data-part="content" data-value="lorem">
                  <p>Lorem ipsum dolor sit amet, consectetur adipiscing elit.</p>
                  </div>
                  <div data-part="content" data-value="duis">
                  <p>Duis a sem ut diam interdum ultricies sit amet id arcu.
                  </p>
                  </div>
                  <div data-part="content" data-value="donec">
                  <p>Donec pretium magna cursus ante tincidunt porta.
                  </p>
                  </div>
                  </div>
                  </div>
                  </div>
                  <div>
                  <div class="tabs tabs-js tabs--alert" data-default-value="lorem">
                  <div data-part="root">
                  <div data-part="list">
                  <button data-part="trigger" data-value="lorem">Lorem</button>
                  <button data-part="trigger" data-value="duis">Duis</button>
                  <button data-part="trigger" data-value="donec">Donec</button>
                  </div>
                  <div data-part="content" data-value="lorem">
                  <p>Lorem ipsum dolor sit amet, consectetur adipiscing elit.</p>
                  </div>
                  <div data-part="content" data-value="duis">
                  <p>Duis a sem ut diam interdum ultricies sit amet id arcu.
                  </p>
                  </div>
                  <div data-part="content" data-value="donec">
                  <p>Donec pretium magna cursus ante tincidunt porta.
                  </p>
                  </div>
                  </div>
                  </div>
                  </div>
                  <div>
                  <div class="tabs tabs-js tabs--accent tabs--brand" data-default-value="lorem">
                  <div data-part="root">
                  <div data-part="list">
                  <button data-part="trigger" data-value="lorem">Lorem</button>
                  <button data-part="trigger" data-value="duis">Duis</button>
                  <button data-part="trigger" data-value="donec">Donec</button>
                  </div>
                  <div data-part="content" data-value="lorem">
                  <p>Lorem ipsum dolor sit amet, consectetur adipiscing elit.</p>
                  </div>
                  <div data-part="content" data-value="duis">
                  <p>Duis a sem ut diam interdum ultricies sit amet id arcu.
                  </p>
                  </div>
                  <div data-part="content" data-value="donec">
                  <p>Donec pretium magna cursus ante tincidunt porta.
                  </p>
                  </div>
                  </div>
                  </div>
                  </div>
                  <div>
                  <div class="tabs tabs-js tabs--accent tabs--alert" data-default-value="lorem">
                  <div data-part="root">
                  <div data-part="list">
                  <button data-part="trigger" data-value="lorem">Lorem</button>
                  <button data-part="trigger" data-value="duis">Duis</button>
                  <button data-part="trigger" data-value="donec">Donec</button>
                  </div>
                  <div data-part="content" data-value="lorem">
                  <p>Lorem ipsum dolor sit amet, consectetur adipiscing elit.</p>
                  </div>
                  <div data-part="content" data-value="duis">
                  <p>Duis a sem ut diam interdum ultricies sit amet id arcu.
                  </p>
                  </div>
                  <div data-part="content" data-value="donec">
                  <p>Donec pretium magna cursus ante tincidunt porta.
                  </p>
                  </div>
                  </div>
                  </div>
                  </div>

Size

Set the size of each button

Options: md(default), sm, lg, xl

Lorem ipsum dolor sit amet, consectetur adipiscing elit.

Duis a sem ut diam interdum ultricies sit amet id arcu.

Donec pretium magna cursus ante tincidunt porta.

Lorem ipsum dolor sit amet, consectetur adipiscing elit.

Duis a sem ut diam interdum ultricies sit amet id arcu.

Donec pretium magna cursus ante tincidunt porta.

Lorem ipsum dolor sit amet, consectetur adipiscing elit.

Duis a sem ut diam interdum ultricies sit amet id arcu.

Donec pretium magna cursus ante tincidunt porta.

Lorem ipsum dolor sit amet, consectetur adipiscing elit.

Duis a sem ut diam interdum ultricies sit amet id arcu.

Donec pretium magna cursus ante tincidunt porta.

<div>
                  <div class="tabs tabs-js tabs--sm" data-default-value="lorem">
                  <div data-part="root">
                  <div data-part="list">
                  <button data-part="trigger" data-value="lorem">Lorem</button>
                  <button data-part="trigger" data-value="duis">Duis</button>
                  <button data-part="trigger" data-value="donec">Donec</button>
                  </div>
                  <div data-part="content" data-value="lorem">
                  <p>Lorem ipsum dolor sit amet, consectetur adipiscing elit.</p>
                  </div>
                  <div data-part="content" data-value="duis">
                  <p>Duis a sem ut diam interdum ultricies sit amet id arcu.
                  </p>
                  </div>
                  <div data-part="content" data-value="donec">
                  <p>Donec pretium magna cursus ante tincidunt porta.
                  </p>
                  </div>
                  </div>
                  </div>
                  </div>
                  <div>
                  <div class="tabs tabs-js" data-default-value="lorem">
                  <div data-part="root">
                  <div data-part="list">
                  <button data-part="trigger" data-value="lorem">Lorem</button>
                  <button data-part="trigger" data-value="duis">Duis</button>
                  <button data-part="trigger" data-value="donec">Donec</button>
                  </div>
                  <div data-part="content" data-value="lorem">
                  <p>Lorem ipsum dolor sit amet, consectetur adipiscing elit.</p>
                  </div>
                  <div data-part="content" data-value="duis">
                  <p>Duis a sem ut diam interdum ultricies sit amet id arcu.
                  </p>
                  </div>
                  <div data-part="content" data-value="donec">
                  <p>Donec pretium magna cursus ante tincidunt porta.
                  </p>
                  </div>
                  </div>
                  </div>
                  </div>
                  <div>
                  <div class="tabs tabs-js tabs--lg" data-default-value="lorem">
                  <div data-part="root">
                  <div data-part="list">
                  <button data-part="trigger" data-value="lorem">Lorem</button>
                  <button data-part="trigger" data-value="duis">Duis</button>
                  <button data-part="trigger" data-value="donec">Donec</button>
                  </div>
                  <div data-part="content" data-value="lorem">
                  <p>Lorem ipsum dolor sit amet, consectetur adipiscing elit.</p>
                  </div>
                  <div data-part="content" data-value="duis">
                  <p>Duis a sem ut diam interdum ultricies sit amet id arcu.
                  </p>
                  </div>
                  <div data-part="content" data-value="donec">
                  <p>Donec pretium magna cursus ante tincidunt porta.
                  </p>
                  </div>
                  </div>
                  </div>
                  </div>
                  <div>
                  <div class="tabs tabs-js tabs--xl" data-default-value="lorem">
                  <div data-part="root">
                  <div data-part="list">
                  <button data-part="trigger" data-value="lorem">Lorem</button>
                  <button data-part="trigger" data-value="duis">Duis</button>
                  <button data-part="trigger" data-value="donec">Donec</button>
                  </div>
                  <div data-part="content" data-value="lorem">
                  <p>Lorem ipsum dolor sit amet, consectetur adipiscing elit.</p>
                  </div>
                  <div data-part="content" data-value="duis">
                  <p>Duis a sem ut diam interdum ultricies sit amet id arcu.
                  </p>
                  </div>
                  <div data-part="content" data-value="donec">
                  <p>Donec pretium magna cursus ante tincidunt porta.
                  </p>
                  </div>
                  </div>
                  </div>
                  </div>

RTL

RTL support for tabs

سقط وبلجيكا، أن ولم, يتم غضون الأوروبية عل, أن بين وقرى مكثّفة

ي وبدون الخاسرة الأعمال بعض, عن دول القوى القادة

حتى سعر الجري الرائع قبل بوابة المطورين.

سقط وبلجيكا، أن ولم, يتم غضون الأوروبية عل, أن بين وقرى مكثّفة

ي وبدون الخاسرة الأعمال بعض, عن دول القوى القادة

حتى سعر الجري الرائع قبل بوابة المطورين.

<div dir="rtl">
                  <div class="tabs tabs-js" data-dir="rtl" data-default-value="lorem">
                  <div data-part="root">
                  <div data-part="list">
                  <button data-part="trigger" data-value="lorem">سقط</button>
                  <button data-part="trigger" data-value="duis">بين</button>
                  <button data-part="trigger" data-value="donec">دونيك</button>
                  </div>
                  <div data-part="content" data-value="lorem">
                  <p>سقط وبلجيكا، أن ولم, يتم غضون الأوروبية عل, أن بين وقرى مكثّفة</p>
                  </div>
                  <div data-part="content" data-value="duis">
                  <p>ي وبدون الخاسرة الأعمال بعض, عن دول القوى القادة</p>
                  <p></p>
                  </div>
                  <div data-part="content" data-value="donec">
                  <p>حتى سعر الجري الرائع قبل بوابة المطورين.
                  </p>
                  </div>
                  </div>
                  </div>
                  </div>
                  <div dir="rtl">
                  <div class="tabs tabs-js" data-dir="rtl" data-orientation="vertical" data-default-value="lorem">
                  <div data-part="root">
                  <div data-part="list">
                  <button data-part="trigger" data-value="lorem">سقط</button>
                  <button data-part="trigger" data-value="duis">بين</button>
                  <button data-part="trigger" data-value="donec">دونيك</button>
                  </div>
                  <div data-part="content" data-value="lorem">
                  <p>سقط وبلجيكا، أن ولم, يتم غضون الأوروبية عل, أن بين وقرى مكثّفة</p>
                  </div>
                  <div data-part="content" data-value="duis">
                  <p>ي وبدون الخاسرة الأعمال بعض, عن دول القوى القادة</p>
                  <p></p>
                  </div>
                  <div data-part="content" data-value="donec">
                  <p>حتى سعر الجري الرائع قبل بوابة المطورين.
                  </p>
                  </div>
                  </div>
                  </div>
                  </div>

Mix

Mix as many modifiers for each tab

Lorem ipsum dolor sit amet, consectetur adipiscing elit.

Duis a sem ut diam interdum ultricies sit amet id arcu.

Donec pretium magna cursus ante tincidunt porta.

<div>
                  <div class="tabs tabs-js tabs--accent tabs--brand tabs--sm" data-default-value="lorem">
                  <div data-part="root">
                  <div data-part="list">
                  <button data-part="trigger" data-value="lorem">Lorem</button>
                  <button data-part="trigger" data-value="duis">Duis</button>
                  <button data-part="trigger" data-value="donec">Donec</button>
                  </div>
                  <div data-part="content" data-value="lorem">
                  <p>Lorem ipsum dolor sit amet, consectetur adipiscing elit.</p>
                  </div>
                  <div data-part="content" data-value="duis">
                  <p>Duis a sem ut diam interdum ultricies sit amet id arcu.
                  </p>
                  </div>
                  <div data-part="content" data-value="donec">
                  <p>Donec pretium magna cursus ante tincidunt porta.
                  </p>
                  </div>
                  </div>
                  </div>
                  </div>

Custom (Tailwind)

If you are using Tailwind styling, you can customize each tabs and its parts with Tailwind utilities

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation.

Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident.

Ipsum suspendisse ultrices gravida dictum fusce ut. Mauris commodo quis imperdiet massa tincidunt nunc pulvinar sapien et.

<div class="tabs tabs-js" data-default-value="tab1">
                  <div data-part="root">
                  <div data-part="list" data-scope="tabs">
                  <button data-part="trigger" data-value="tab1" class="border-ui-brand px-4 py-2 font-medium" data-scope="tabs" data-selected="">Lorem</button>
                  <button data-part="trigger" data-value="tab2" class="border-2 border-indigo-500 px-4 py-2 font-medium rounded-t-lg text-contrast-1 hover:text-contrast-2" data-scope="tabs">Duis</button>
                  <button data-part="trigger" data-value="tab3" class="border-2 border-indigo-500 px-4 py-2 font-medium rounded-t-lg text-contrast-alert-1 hover:text-contrast-brand-2" data-scope="tabs">Ipsum</button>
                  </div>
                  <div data-part="content" data-value="tab1" class="p-4 rounded-md shadow-sm" data-scope="tabs">
                  <p class="text-gray-800">Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed do
                  eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam,
                  quis nostrud exercitation.</p>
                  </div>
                  <div data-part="content" data-value="tab2" class=" p-4 bg-white rounded-md shadow-sm" data-scope="tabs">
                  <p class="text-gray-800">Duis aute irure dolor in reprehenderit in voluptate velit esse
                  cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident.
                  </p>
                  </div>
                  <div data-part="content" data-value="tab3" class=" p-4 bg-white rounded-md shadow-sm" data-scope="tabs">
                  <p class="text-gray-800">Ipsum suspendisse ultrices gravida dictum fusce ut. Mauris commodo
                  quis imperdiet massa tincidunt nunc pulvinar sapien et.</p>
                  </div>
                  </div>
                  </div>

Templates

Tabs components is available in the followng templates

Switcher Timer