Disclosure

Tabs

Value-keyed rather than index-keyed. `TabItem.id` is required now: v0 had it optional with a positional fallback while emitting `aria-labelledby={`tab-${index}`}` against triggers that carried no id, so the association never resolved.

data-scope="tabs"

What you get for free

  • Arrow-key navigation, Home and End
  • Roving tabindex
  • Automatic or manual activation
  • aria-controls / aria-labelledby that actually resolve

Usage

<Tabs
  type="card"
  defaultActiveKey="overview"
  onChange={key => setTab(key)}
  items={[
    { key: "overview", label: "Overview", children: <Overview /> },
    { key: "settings", label: "Settings", children: <Settings /> },
  ]}
/>
<Tabs :items="items" variant="enclosed">
  <template #overview>…</template>
  <template #settings>…</template>
</Tabs>
<Tabs {items} variant="enclosed">
  {#snippet overview()}…{/snippet}
</Tabs>
<ck-tabs [items]="items" variant="enclosed">
  <ng-template ckPanel="overview">…</ng-template>
  <ng-template ckPanel="settings">…</ng-template>
</ck-tabs>

Props

PropTypeDefaultNotes
activeKey, defaultActiveKeystringReact firstThe selected tab's key. Replaces `value` / `defaultValue`.
onChange(key: string) => voidReact firstThe key itself rather than a detail object.
type"line" | "card""line"React firstReplaces `variant`. Emits `data-type`, so v2 carries its own rules.
tabPosition"top" | "bottom" | "left" | "right""top"React firstReplaces `orientation`, and derives it — the arrow keys follow the axis the list is actually laid out on, so the two cannot disagree.
itemsTabItem[]The tabs. v1 items are `{ id, label, content }`; React's v2 items are `{ key, label, children }`, keyed the way the rest of the v2 API is.
valuestringNot in ReactSelected tab id. v0 keyed by index.
defaultValuestringNot in ReactDefaults to the first item.
onValueChange(d: { value }) => voidNot in ReactSelection callback.
variant"line" | "enclosed" | "soft-rounded" | "solid-rounded""line"Not in ReactVisual style, as data-ck-variant on the root.
orientation"horizontal" | "vertical""horizontal"Not in ReactLayout axis; also switches which arrow keys navigate.
activationMode"automatic" | "manual""automatic"Activate on focus, or require Enter/Space.

Prop names are identical in all four frameworks. Only two-way binding differs, and each framework uses its own idiom over the same underlying prop. The marked rows are the exception, and a temporary one, in both directions: React first exists in React while the other three adapters catch up, and Not in React is the prop it replaced, still live everywhere else.

Migrating from react-ui-toolkit

v0v1Notes
defaultActiveTab: numbervalue / defaultValue (a tab id)
onTabChange(index)onValueChange({ value })
TabItem.id?TabItem.id — required