Tabs

Usage

The default is a segmented bar. The selected tab has a white background and a border. Each tab points to its panel with aria-controls; start the other panels hidden. Tabs work as soon as they sit inside .tabs.

Account

Edit the account name and email. Save when done.

Underlined tabs

For page-level tabs under a heading. Set data-variant="line" on the tablist.

Overview

Orders, sales and returns for the selected period.

Small, for a card header

100% cotton bed sheet

Vertical tabs beside the panels

Set aria-orientation="vertical". Arrow Up / Down replace Left / Right. Below 40rem the tabs sit above the panel.

General

Store name, address and time zone.

Vertical, with underlined tabs

General

Store name, address and time zone.

With icons

Account

Name, email and profile photo.

A disabled tab cannot be selected, and the arrow keys skip it

Overview

Orders, sales and returns for the selected period.

A tab can be a dropdown: choosing an entry selects the tab

Put popovertarget on the tab, pointing to a .dropdown. Clicking the tab opens the menu; clicking an entry selects the tab (add popovertargetaction="hide" to close the menu).

Overview

All customers in the selected period.

The page selects a tab with select()

Overview

Orders, sales and returns for the selected period.

An element with data-close inside a tab closes it, and so does Delete

Closing removes the tab and its panel. If it was selected, the next (or previous) tab is selected instead.

Order #1042

2 items. Paid, awaiting shipment.

The page hears tsunami:closetab first, and keeps the tab with preventDefault()

Saved draft

This tab can be closed.

Nothing closed yet.

API

Lives in js/tabs.js. It uses event delegation, so tabs added later work too.

Function Arguments Description
tsunami.tabs.select(tab) tab: element [role="tab"] Selects the tab, shows its panel and hides the others. Does nothing on a disabled tab.
tsunami.tabs.close(tab) tab: element [role="tab"] Fires tsunami:closetab first. If not cancelled, removes the tab and panel and, if it was selected, selects the next (or previous) tab. Returns the replacement tab (or null), or false if it was kept.
Arrow Left / Right keyboard Previous / next tab, wrapping, skipping disabled tabs. Vertical tabs use Arrow Up / Down.
Home / End keyboard First / last tab
Delete keyboard On a tab with [data-close]: closes the tab and focuses its replacement
Tab keyboard Only the selected tab is in the Tab order

Events

Event Detail Description
tsunami:closetab { tab, panel } Fired on the tab before it closes. Bubbles and is cancelable: preventDefault() keeps the tab.

Attributes

Attribute / element Values Description
.tabs div Wraps the tablist and panels (data-tabs works too)
[role="tablist"] child Row of tabs. Add an aria-label.
data-variant unset (default) segmented · line underlined On the tablist: tab style
data-size unset (default) 32px · sm 28px On the tablist: size. sm for card headers.
aria-orientation horizontal (default) · vertical On the tablist: vertical puts the tabs beside the panels and uses Arrow Up / Down (the tablist must be a direct child of .tabs)
[role="tab"] button A tab. Can hold an .icon.
aria-controls panel id On a tab: the panel it shows (required)
aria-selected true · false On a tab: the selected tab. Put tabindex="-1" on the others. JS keeps them updated.
disabled / aria-disabled true On a tab: cannot be selected, skipped by the keyboard
popovertarget .dropdown id On a tab: the tab is a dropdown. Click a menu entry to select the tab.
[data-close] element in a tab Closable tab. Click this element or press Delete to close it.
[role="tabpanel"] element Content. Add aria-labelledby pointing to its tab, and hidden on all but the selected one.