Tabs

Organize content with style.

zweiundeins <sb-tabs> tablist segmented switcher Since 2026-09-210Open in playground Edit on GitHub

Playground

A segmented tab bar with keyboard support. Labels come from a JSON attribute. Each panel is a slotted element whose slot is the label in kebab-case.

Examples

With panels

A light, fast shuttle built for orbital hops.

Payload 4t · Δv 9.4 km/s · 2 engines

Commander, pilot and one very good dog.

<sb-tabs labels='["Overview","Specs","Crew"]' style="inline-size: 100%">
  <p slot="overview">A light, fast shuttle built for orbital hops.</p>
  <p slot="specs">Payload 4t · Δv 9.4 km/s · 2 engines</p>
  <p slot="crew">Commander, pilot and one very good dog.</p>
</sb-tabs>

Follow the selection

<div data-signals:_tab="'Home'">
  <sb-tabs labels='["Home","Docs","API"]' data-on:sb-tab-change="$_tab = evt.detail.label"></sb-tabs>
  <p data-text="'Current: ' + $_tab"></p>
</div>

Accessibility

It follows the WAI-ARIA tabs pattern: role="tablist", tab and tabpanel, a roving tabindex, and arrow keys, Home and End for navigation.

Installation

Add Datastar with Rocket and the Starbase autoloader once per page, then use the tag. The autoloader imports each component the first time its tag appears, including tags added later by a Datastar morph.

<!-- Once per page: Datastar with Rocket, and the Starbase autoloader.
     It loads every <sb-…> component the first time its tag appears. -->
<script type="importmap">
  { "imports": { "datastar": "https://cdn.jsdelivr.net/gh/starfederation/datastar@v1.0.4/bundles/datastar-rocket.js" } }
</script>
<script type="module" src="https://rocket.libretto.ch/c/autoloader.js"></script>
<!-- Optional, no flash of undefined elements: class="sb-cloak" on <html>, and -->
<style>.sb-cloak :not(:defined) { visibility: hidden }</style>

<sb-tabs labels='["Home","Docs","API"]'></sb-tabs>

<!-- Or skip the autoloader and load just this component: -->
<!-- <script type="module" src="https://rocket.libretto.ch/c/tabs/tabs.js"></script> -->

API reference

Props

AttributeTypeDefaultDescription
labelsarray[ "Home", "Docs", "API" ]Tab labels, as a JSON array.
selectednumber0Index of the initially selected tab.

Slots

NameDescription
<label-slug>Panel content per tab, e.g. slot="docs" for a tab labelled "Docs".

Events

NameDescription
sb-tab-changedetail: { index, label }.