Web Components

By Auroratide

The tab-list Elements

The tab-list, tab-item, and tab-panel elements together represent content that is presented one panel at a time. They are built with accessibility in mind and implement the WAI-ARIA guidelines for tabs.

  • A tab-list represents a set of tabs, where only one tab's contents may be presented at a time.
  • A tab-item represents a reference of a single panel of information in a tab list.
  • A tab-panel represents a panel of information.
Apples Oranges Bananas

Apples are usually red, but sometimes they can be green.

Oranges are, well, orange!

Bananas are yellow and usually curved.

<tab-list aria-label="Learn about fruits">
    <tab-item for="example-1-tab-1" selected>Apples</tab-item>
    <tab-item for="example-1-tab-2">Oranges</tab-item>
    <tab-item for="example-1-tab-3">Bananas</tab-item>
</tab-list>
<tab-panel id="example-1-tab-1">
    <p>Apples are usually red, but sometimes they can be green.</p>
</tab-panel>
<tab-panel id="example-1-tab-2">
    <p>Oranges are, well, orange!</p>
</tab-panel>
<tab-panel id="example-1-tab-3">
    <p>Bananas are yellow and usually curved.</p>
</tab-panel>

Installation

You can import through CDN:

<script type="module" src="https://unpkg.com/@auroratide/tab-list/lib/define.js"></script>

Or, you may install through NPM and include it as part of your build process:

$ npm i @auroratide/tab-list
import '@auroratide/tab-list/lib/define.js'

Usage

tab-list, tab-item, and tab-panel are markup elements that you can use in your HTML document. To use them together, it is best to follow these guidelines:

  • tab-item elements must be contained within a tab-list. They need not be direct descendents.
  • tab-panel must define a unique id.
  • tab-item must define the for attribute, whose value is the id of its corresponding tab-panel.
<tab-list>
    <!-- tab-item must be in a tab-list, and defines `for` to be
         the corresponding tab-panel id -->
    <tab-item for="tab-panel-id">
</tab-list>
<!-- tab-panel defines an id -->
<tab-panel id="tab-panel-id">
    <p>Any content you want</p>
</tab-panel>

The following are good accessibility practices:

  • tab-list should be labelled with a name representing the collection of tabs, either with aria-label or aria-labelledby.
  • tab-panel elements can theoretically be anywhere on the page, though it's best if they are the next focusable item after the tab-list.

Automatic Activation

By default, a tab must be clicked in order for its panel to be revealed. With automatic activation, a tab only needs to acquire focus to show its tab. In general, WAI-ARIA recommends automatic activation for the best accessibility, unless animations induce lag.

You can enable automatic activation by setting the activation attribute to "automatic" on the tab list element.

Tomatoes Carrots Squashes

Tomatoes are red. People like to tell you they are fruit and not vegetables.

Carrots are orange, and also a root.

Some squashes are yellow, and they come in all shapes and sizes.

<tab-list activation="automatic" aria-label="Learn about vegetables">
    <tab-item for="example-5-tab-1" selected>Tomatoes</tab-item>
    <tab-item for="example-5-tab-2">Carrots</tab-item>
    <tab-item for="example-5-tab-3">Squashes</tab-item>
</tab-list>

Vertical Tab List

By default, tabs are listed horizontally, and they can be navigated with the left and right arrow keys.

By setting the orientation attribute to "vertical", you can make a vertical tab list. This makes it navigable with the up and down arrow keys instead.

Tomatoes Carrots Squashes

Tomatoes are red. People like to tell you they are fruit and not vegetables.

Carrots are orange, and also a root.

Some squashes are yellow, and they come in all shapes and sizes.

<tab-list orientation="vertical" aria-label="Learn about vegetables">
    <tab-item for="example-2-tab-1" selected>Tomatoes</tab-item>
    <tab-item for="example-2-tab-2">Carrots</tab-item>
    <tab-item for="example-2-tab-3">Squashes</tab-item>
</tab-list>

Setting a selected tab

You can set the selected attribute on one tab-item in a tab-list. This will mark that item as selected and show its panel.

Apples Oranges Bananas

Apples are usually red, but sometimes they can be green.

Oranges are, well, orange!

Bananas are yellow and usually curved.

<tab-item selected for="example-3-tab-3">Bananas</tab-item>

Note: Only one tab-item can be selected at a time! If you attempt to set multiple as selected, only the first selected tabl's panel will be shown.

All Attributes

For tab-list:

Attribute Description
orientation Either "horizontal" or "vertical". Represents whether the tab list should be presented horizontally or vertically, and affects whether they are navigated with the left/right or up/down keys respectively. "horizontal" by default.
activation Either "manual" or "automatic". Represents whether a click (manual) or focus (automatic) is required to show a tab's panel. "manual" by default.

For tab-item:

Attribute Description
for Required. Should be the same as the id of the tab's respective panel.
selected Either present or not. Represents whether this tab's panel should be shown.

CSS Customization

Since these are native custom elements, they can be styled the same way as regular HTML elements.

Of note:

  • tab-item[selected] will style the currently selected tab.
  • tab-list[orientation="vertical"] can style vertical tab lists.
  • tab-panel[hidden] styles hidden tabs, in case you want transitions.

Here's an example of a fully customized tab list:

Apples Oranges Bananas

Ingredients for making apple pie:

  • 8 Granny Smith apples
  • ½ cup butter
  • 3 tablespoons flour
  • ½ cup white sugar
  • ½ cup brown sugar
  • ¼ water
  • A double-crust pie pastry

Ingredients for making orange sorbet:

  • 2 cups orange juice pulp
  • 1½ cup almond milk
  • 1 tablespoon orange zest
  • 1 tablespoon lemon juice
  • ¼ teaspoon salt
  • 1 teaspoon vanilla extract
  • ½ teaspoon sweetener

Ingredients for making banana pudding:

  • 14 bananas
  • 5 ounce packet instant vanilla pudding
  • 2 cups milk
  • 14 ounce can condensed milk
  • 1 tablespoon vanilla extract
  • 12 ounces frozen whipped topping
  • 16 ounces vanilla wafers
div.tab-container {
	box-shadow: 0 0.125em 0.25em oklch(0% 0 0 / 0.25);
}

tab-list {
	background: oklch(55% 0.119 250);
	gap: 0;
}

tab-item {
	border: none;
	border-radius: 0;
	background: oklch(55% 0.119 250);
	color: oklch(97.5% 0.005 255);
	padding: 0.625em 1.125em;
	border-right: 0.125em solid oklch(38% 0.125 250);
}

tab-item:hover:not([selected]),
tab-item:focus:not([selected]) {
	background: oklch(38% 0.125 250);
}

tab-item[selected] {
	background: oklch(22% 0.021 255);
	border-color: transparent;
	color: oklch(80% 0.005 255);
}

div.tab-panels-container { display: grid; }
tab-panel {
	grid-area: 1 / 1;
	border: none;
	padding: 0.625em 1.125em 1.125em;
	opacity: 1;
	transition: opacity 0.2s ease-in-out;
}

tab-panel[hidden] {
	display: block;
	opacity: 0;
}

Events

The tab-list element dispatches the following events:

Name When Triggered
tab-list:change Whenever the currently selected tab changes

The tab-list:change event contains references to the previously selected tab and the newly selected tab:

tabList.addEventListener('tab-list:change', e => {
    console.log(e.detail.from)
    console.log(e.detail.to)
})

Accessibility

This custom element is built with accessibility in mind! It follows the WAI-ARIA guidelines for tabs (the tablist, tab, and tabpanel roles).

  • When focus enters the tab list, the currently active tab item is focused.
  • Left and Right can be used to navigate the tabs.
  • Enter or Space select the currently focused tab.
  • Home goes to the first tab, and End goes to the last tab.

Not (yet) Implemented

The following features are desired of tab lists, but are not yet implemented:

  • Auto-opening a panel when its corresponding tab receives focus.
  • Native support for removable tabs.
  • Tabs that open popup menus.