Vanilla UI Kit Tabs v1.0.0 · toast → datepicker →

Tabs, one file.

Zero-dependency tabs that enhance the markup you already have — full ARIA pattern, arrow-key navigation, a sliding indicator, and automatic light/dark. Every card below is live.

<script src="https://cdn.jsdelivr.net/gh/vanilla-ui-kit/components/tabs/tabs.js"></script>

Basic

Canonical markup: strip first, panels after. Arrow keys move and select.

Overview. First child is the tab strip, following siblings are the panels. That's the whole contract.

Features. Roving tabindex, wrap-around arrows, Home/End, hidden panels.

Pricing. Free — it's one file, MIT licensed.

Active: 0

new Tabs('#basic', {
  onChange: (i) => console.log(i)
})

Manual activation

Arrows only move focus; Enter or Space selects.

Editor. Use activation: 'manual' when switching panels is expensive.

Preview. Focus me with ArrowRight, then press Enter.

History. Nothing loads until you commit.

new Tabs('#manual', { activation: 'manual' })

Vertical

Rail on the left, ArrowUp/ArrowDown, indicator on the rail edge.

Profile. The tablist gets aria-orientation="vertical".

Security. The ink bar slides along the rail instead of under the tabs.

Billing. Same markup, one option.

new Tabs('#vertical', { vertical: true })

Builder mode

No markup — labels and content are text-safe by default.

new Tabs('#built', {
  tabs: [
    { label: 'One', content: 'Plain text' },
    { label: 'Two', content: '<b>html</b>',
      html: true }
  ]
})

Disabled tab

Plain disabled attribute; arrows skip it.

Inbox. Press ArrowRight — Drafts is skipped.

Never shown.

Archive. Landed here directly.

<button disabled>Drafts</button>

Declarative

Zero JS: data-vtb containers init themselves.

HTML. No script written for this card.

Attributes. data-vtb-active chose this tab; options ride along as data-vertical, data-activation, …

<div data-vtb>…canonical markup…</div>