<script setup>
import { ref } from "vue";
import { Tabs } from "@dicehub/kappa/components/tabs";
const selected = ref("overview");
</script>
<template>
<Tabs.Root v-model="selected">
<Tabs.List>
<Tabs.Trigger value="overview">Overview</Tabs.Trigger>
<Tabs.Trigger value="runs">Runs</Tabs.Trigger>
<Tabs.Trigger value="artifacts">Artifacts</Tabs.Trigger>
<Tabs.Indicator />
</Tabs.List>
<Tabs.Content value="overview">Case overview and current status.</Tabs.Content>
<Tabs.Content value="runs">Recent solver runs and timings.</Tabs.Content>
<Tabs.Content value="artifacts">Meshes, logs, and exported fields.</Tabs.Content>
</Tabs.Root>
</template>Installation
Barrel
import { Tabs } from "@dicehub/kappa";Granular
import { Tabs } from "@dicehub/kappa/components/tabs";Usage
Give each Trigger and Content the same stable value attribute. The root owns the selected value, while Ark UI supplies the tablist, panel relationships, roving focus, and activation behavior. Set visual variant and size on Tabs.List.
<script setup>
import { Tabs } from "@dicehub/kappa/components/tabs";
</script>
<template>
<Tabs.Root default-value="mesh">
<Tabs.List>
<Tabs.Trigger value="mesh">Mesh</Tabs.Trigger>
<Tabs.Trigger value="solver">Solver</Tabs.Trigger>
<Tabs.Trigger value="results">Results</Tabs.Trigger>
<Tabs.Indicator />
</Tabs.List>
<Tabs.Content value="mesh">The mesh contains 2.4 million cells.</Tabs.Content>
<Tabs.Content value="solver">PIMPLE is using six outer correctors.</Tabs.Content>
<Tabs.Content value="results">Pressure and force histories are ready.</Tabs.Content>
</Tabs.Root>
</template>Composition
Tabs.Root
├── Tabs.List
│ ├── Tabs.Trigger
│ ├── Tabs.Trigger
│ └── Tabs.Indicator (optional)
├── Tabs.Content
└── Tabs.ContentUse the compound namespace for concise templates or named exports for explicit imports. Place Indicator inside List so Ark UI can measure and move it to the selected trigger. The Context part exposes the reactive Ark UI API to a scoped slot when a custom control needs to call selectNext or inspect focus.
<script setup>
import {
TabsRoot,
TabsList,
TabsTrigger,
TabsContent,
TabsIndicator,
} from "@dicehub/kappa/components/tabs";
</script>
<template>
<TabsRoot default-value="summary">
<TabsList>
<TabsTrigger value="summary">Summary</TabsTrigger>
<TabsTrigger value="log">Log</TabsTrigger>
<TabsIndicator />
</TabsList>
<TabsContent value="summary">Run summary.</TabsContent>
<TabsContent value="log">Solver log excerpt.</TabsContent>
</TabsRoot>
</template>Examples
Basic
Use one root with a list, triggers, optional indicator, and matching content panels.
<Tabs.Root default-value="overview">
<Tabs.List>
<Tabs.Trigger value="overview">Overview</Tabs.Trigger>
<Tabs.Trigger value="runs">Runs</Tabs.Trigger>
<Tabs.Trigger value="artifacts">Artifacts</Tabs.Trigger>
<Tabs.Indicator />
</Tabs.List>
<Tabs.Content value="overview">Case overview and current status.</Tabs.Content>
<Tabs.Content value="runs">Recent solver runs and timings.</Tabs.Content>
<Tabs.Content value="artifacts">Meshes, logs, and exported fields.</Tabs.Content>
</Tabs.Root>Variants
Use the segmented rail for compact view switches or the line rail for full-width sections.
<div class="tabs-stack">
<Tabs.Root default-value="preview">
<Tabs.List variant="segmented">
<Tabs.Trigger value="preview">Preview</Tabs.Trigger>
<Tabs.Trigger value="code">Code</Tabs.Trigger>
<Tabs.Trigger value="history">History</Tabs.Trigger>
<Tabs.Indicator />
</Tabs.List>
<Tabs.Content value="preview">Preview is selected.</Tabs.Content>
<Tabs.Content value="code">Code is selected.</Tabs.Content>
<Tabs.Content value="history">History is selected.</Tabs.Content>
</Tabs.Root>
<Tabs.Root default-value="preview">
<Tabs.List variant="line">
<Tabs.Trigger value="preview">Preview</Tabs.Trigger>
<Tabs.Trigger value="code">Code</Tabs.Trigger>
<Tabs.Trigger value="history">History</Tabs.Trigger>
<Tabs.Indicator />
</Tabs.List>
<Tabs.Content value="preview">Preview is selected.</Tabs.Content>
<Tabs.Content value="code">Code is selected.</Tabs.Content>
<Tabs.Content value="history">History is selected.</Tabs.Content>
</Tabs.Root>
</div>Sizes
Use the small size in dense toolbars and the base size for standard page controls.
<div class="tabs-stack">
<Tabs.Root default-value="daily">
<Tabs.List size="base">
<Tabs.Trigger value="daily">Daily</Tabs.Trigger>
<Tabs.Trigger value="weekly">Weekly</Tabs.Trigger>
<Tabs.Trigger value="monthly">Monthly</Tabs.Trigger>
<Tabs.Indicator />
</Tabs.List>
<Tabs.Content value="daily">Daily data.</Tabs.Content>
<Tabs.Content value="weekly">Weekly data.</Tabs.Content>
<Tabs.Content value="monthly">Monthly data.</Tabs.Content>
</Tabs.Root>
<Tabs.Root default-value="daily">
<Tabs.List size="sm">
<Tabs.Trigger value="daily">Daily</Tabs.Trigger>
<Tabs.Trigger value="weekly">Weekly</Tabs.Trigger>
<Tabs.Trigger value="monthly">Monthly</Tabs.Trigger>
<Tabs.Indicator />
</Tabs.List>
<Tabs.Content value="daily">Daily data.</Tabs.Content>
<Tabs.Content value="weekly">Weekly data.</Tabs.Content>
<Tabs.Content value="monthly">Monthly data.</Tabs.Content>
</Tabs.Root>
</div>Icons
Place a decorative icon before a concise label. The text keeps the trigger name clear.
<script setup>
import { ChartLine, File, Settings } from "@lucide/vue";
import { Tabs } from "@dicehub/kappa/components/tabs";
</script>
<template>
<Tabs.Root default-value="analytics">
<Tabs.List variant="line">
<Tabs.Trigger value="analytics"><ChartLine />Analytics</Tabs.Trigger>
<Tabs.Trigger value="files"><File />Files</Tabs.Trigger>
<Tabs.Trigger value="settings"><Settings />Settings</Tabs.Trigger>
<Tabs.Indicator />
</Tabs.List>
<Tabs.Content value="analytics">Analytics are ready.</Tabs.Content>
<Tabs.Content value="files">Files are ready.</Tabs.Content>
<Tabs.Content value="settings">Settings are ready.</Tabs.Content>
</Tabs.Root>
</template>Many Tabs
Keep a long tab set on one line. A wider constrained rail supports fast scanning and horizontal scrolling.
<script setup>
import { Tabs } from "@dicehub/kappa/components/tabs";
const tabs = [
["overview", "Overview"],
["analytics", "Analytics"],
["reports", "Reports"],
["notifications", "Notifications"],
["settings", "Settings"],
["billing", "Billing"],
["security", "Security"],
["integrations", "Integrations"],
];
</script>
<template>
<Tabs.Root default-value="overview" class="many-tabs">
<Tabs.List>
<Tabs.Trigger v-for="tab in tabs" :key="tab[0]" :value="tab[0]">
{{ tab[1] }}
</Tabs.Trigger>
<Tabs.Indicator />
</Tabs.List>
<Tabs.Content v-for="tab in tabs" :key="tab[0]" :value="tab[0]">
{{ tab[1] }} view is selected.
</Tabs.Content>
</Tabs.Root>
</template>
<style scoped>
.many-tabs {
inline-size: min(100%, 29rem);
}
</style>Horizontal Overflow
Constrain the rail when space is tight. Edge controls reveal off-screen tabs without widening the page.
<script setup>
import { ChevronLeft, ChevronRight } from "@lucide/vue";
import { nextTick, onBeforeUnmount, onMounted, ref } from "vue";
import { Tabs } from "@dicehub/kappa/components/tabs";
const tabs = ["Overview", "Analytics", "Reports", "Notifications", "Settings"];
const rail = ref(null);
const canScrollBack = ref(false);
const canScrollForward = ref(false);
const getList = () => rail.value?.querySelector('[role="tablist"]');
const updateOverflow = () => {
const list = getList();
if (!list) return;
const max = list.scrollWidth - list.clientWidth;
canScrollBack.value = list.scrollLeft > 1;
canScrollForward.value = list.scrollLeft < max - 1;
};
const scrollTabs = (direction) => {
getList()?.scrollBy({ left: direction * 200, behavior: "smooth" });
};
let resizeObserver;
onMounted(async () => {
await nextTick();
const list = getList();
if (!list) return;
resizeObserver = new ResizeObserver(updateOverflow);
resizeObserver.observe(list);
updateOverflow();
});
onBeforeUnmount(() => resizeObserver?.disconnect());
</script>
<template>
<Tabs.Root default-value="Overview" class="overflow-tabs">
<div ref="rail" class="overflow-tabs__rail">
<Tabs.List class="overflow-tabs__list" @scroll.passive="updateOverflow">
<Tabs.Trigger v-for="tab in tabs" :key="tab" :value="tab">{{ tab }}</Tabs.Trigger>
<Tabs.Indicator />
</Tabs.List>
<button
v-if="canScrollBack"
type="button"
class="overflow-tabs__button overflow-tabs__button--start"
aria-label="Scroll tabs backward"
@click="scrollTabs(-1)"
>
<ChevronLeft aria-hidden="true" />
</button>
<button
v-if="canScrollForward"
type="button"
class="overflow-tabs__button overflow-tabs__button--end"
aria-label="Scroll tabs forward"
@click="scrollTabs(1)"
>
<ChevronRight aria-hidden="true" />
</button>
</div>
<Tabs.Content v-for="tab in tabs" :key="tab" :value="tab">
{{ tab }} view is selected.
</Tabs.Content>
</Tabs.Root>
</template>
<style scoped>
.overflow-tabs {
inline-size: min(100%, 17.5rem);
}
.overflow-tabs__rail {
position: relative;
}
.overflow-tabs__list {
scroll-padding-inline: 2.5rem;
}
.overflow-tabs__button {
position: absolute;
z-index: 2;
inset-block: 1px;
inline-size: 2rem;
border: 0;
}
.overflow-tabs__button--start {
inset-inline-start: 1px;
}
.overflow-tabs__button--end {
inset-inline-end: 1px;
}
</style>Right to Left
Set dir to rtl when the component must override its inherited document direction.
<Tabs.Root default-value="overview" dir="rtl">
<Tabs.List variant="line">
<Tabs.Trigger value="overview">Overview</Tabs.Trigger>
<Tabs.Trigger value="reports">Reports</Tabs.Trigger>
<Tabs.Trigger value="settings">Settings</Tabs.Trigger>
<Tabs.Indicator />
</Tabs.List>
<Tabs.Content value="overview">Direction-aware overview.</Tabs.Content>
<Tabs.Content value="reports">Direction-aware reports.</Tabs.Content>
<Tabs.Content value="settings">Direction-aware settings.</Tabs.Content>
</Tabs.Root>Manual Activation
Set activationMode to manual when arrow-key focus should not change content until Enter or Space.
<Tabs.Root default-value="setup" activation-mode="manual">
<Tabs.List variant="line">
<Tabs.Trigger value="setup">Setup</Tabs.Trigger>
<Tabs.Trigger value="review">Review</Tabs.Trigger>
<Tabs.Trigger value="submit">Submit</Tabs.Trigger>
<Tabs.Indicator />
</Tabs.List>
<Tabs.Content value="setup">Configure the case.</Tabs.Content>
<Tabs.Content value="review">Review the input values.</Tabs.Content>
<Tabs.Content value="submit">Submit a validated run.</Tabs.Content>
</Tabs.Root>Vertical
Use vertical orientation for an inspector or settings rail. Ark UI switches navigation to Up and Down.
<Tabs.Root default-value="geometry" orientation="vertical">
<Tabs.List variant="line">
<Tabs.Trigger value="geometry">Geometry</Tabs.Trigger>
<Tabs.Trigger value="mesh">Mesh</Tabs.Trigger>
<Tabs.Trigger value="boundaries">Boundaries</Tabs.Trigger>
<Tabs.Indicator />
</Tabs.List>
<Tabs.Content value="geometry">The geometry is watertight.</Tabs.Content>
<Tabs.Content value="mesh">All mesh quality checks passed.</Tabs.Content>
<Tabs.Content value="boundaries">Seven boundary patches are assigned.</Tabs.Content>
</Tabs.Root>Controlled
Bind v-model when route state, a parent workflow, or another control owns the selected value.
<script setup>
import { ref } from "vue";
import { Tabs } from "@dicehub/kappa/components/tabs";
const selected = ref("residuals");
</script>
<template>
<Tabs.Root v-model="selected">
<Tabs.List>
<Tabs.Trigger value="residuals">Residuals</Tabs.Trigger>
<Tabs.Trigger value="forces">Forces</Tabs.Trigger>
<Tabs.Indicator />
</Tabs.List>
<Tabs.Content value="residuals">All residuals are below 1e-5.</Tabs.Content>
<Tabs.Content value="forces">Mean drag coefficient is 0.31.</Tabs.Content>
</Tabs.Root>
<output aria-live="polite">Selected: {{ selected }}</output>
</template>Disabled
Disable one trigger while preserving the surrounding tab order and accessible state.
<Tabs.Root default-value="available">
<Tabs.List>
<Tabs.Trigger value="available">Available</Tabs.Trigger>
<Tabs.Trigger value="pending" disabled>Pending data</Tabs.Trigger>
<Tabs.Trigger value="history">History</Tabs.Trigger>
<Tabs.Indicator />
</Tabs.List>
<Tabs.Content value="available">Current diagnostics are ready.</Tabs.Content>
<Tabs.Content value="pending">This panel is not available yet.</Tabs.Content>
<Tabs.Content value="history">Previous diagnostics are archived.</Tabs.Content>
</Tabs.Root>Dynamic Tab Count
Change the number of tabs at runtime. Overflow controls disappear when the remaining seven tabs fit.
<script setup>
import { ChevronLeft, ChevronRight } from "@lucide/vue";
import { computed, nextTick, onBeforeUnmount, onMounted, ref, watch } from "vue";
import { Tabs } from "@dicehub/kappa/components/tabs";
const standardTabs = [
"Overview",
"Metrics",
"Releases",
"Observability",
"Domains",
"Access",
"Settings",
];
const extraTabs = ["Analytics", "Logs", "Security"];
const showExtraTabs = ref(true);
const selectedTab = ref("Settings");
const tabs = computed(() =>
showExtraTabs.value ? [...standardTabs, ...extraTabs] : standardTabs,
);
const rail = ref(null);
const canScrollBack = ref(false);
const canScrollForward = ref(false);
const getList = () => rail.value?.querySelector('[role="tablist"]');
const updateOverflow = () => {
const list = getList();
if (!list) return;
const max = list.scrollWidth - list.clientWidth;
canScrollBack.value = list.scrollLeft > 1;
canScrollForward.value = list.scrollLeft < max - 1;
};
const scrollTabs = (direction) => {
getList()?.scrollBy({ left: direction * 300, behavior: "smooth" });
};
const revealSelectedTab = async () => {
await nextTick();
const selected = getList()?.querySelector('[role="tab"][aria-selected="true"]');
selected?.scrollIntoView({ behavior: "smooth", block: "nearest", inline: "nearest" });
};
let resizeObserver;
onMounted(async () => {
await nextTick();
const list = getList();
if (!list) return;
resizeObserver = new ResizeObserver(updateOverflow);
resizeObserver.observe(list);
updateOverflow();
});
onBeforeUnmount(() => resizeObserver?.disconnect());
watch(tabs, async () => {
await nextTick();
updateOverflow();
});
watch(selectedTab, revealSelectedTab);
</script>
<template>
<div class="dynamic-tabs">
<Tabs.Root v-model="selectedTab">
<div ref="rail" class="dynamic-tabs__rail">
<Tabs.List size="sm" @scroll.passive="updateOverflow">
<Tabs.Trigger v-for="tab in tabs" :key="tab" :value="tab">
{{ tab }}
</Tabs.Trigger>
<Tabs.Indicator />
</Tabs.List>
<button
v-if="canScrollBack"
type="button"
aria-label="Scroll tabs backward"
@click="scrollTabs(-1)"
>
<ChevronLeft aria-hidden="true" />
</button>
<button
v-if="canScrollForward"
type="button"
aria-label="Scroll tabs forward"
@click="scrollTabs(1)"
>
<ChevronRight aria-hidden="true" />
</button>
</div>
<Tabs.Content v-for="tab in tabs" :key="tab" :value="tab">
{{ tab }} view is selected.
</Tabs.Content>
</Tabs.Root>
<div class="dynamic-tabs__controls">
<button type="button" @click="showExtraTabs = !showExtraTabs">Toggle extra tabs</button>
<output aria-live="polite">{{ tabs.length }} tabs</output>
</div>
</div>
</template>
<style scoped>
.dynamic-tabs {
display: grid;
inline-size: min(100%, 42rem);
gap: 0.75rem;
}
.dynamic-tabs__rail {
position: relative;
}
.dynamic-tabs__rail :deep([role="tablist"]) {
inline-size: 100%;
scroll-padding-inline: 3.25rem;
}
.dynamic-tabs__rail > button {
position: absolute;
z-index: 2;
inset-block: 1px;
inline-size: 2.5rem;
border: 0;
}
.dynamic-tabs__rail > button[aria-label="Scroll tabs backward"] {
inset-inline-start: 1px;
}
.dynamic-tabs__rail > button[aria-label="Scroll tabs forward"] {
inset-inline-end: 1px;
}
.dynamic-tabs__controls {
display: flex;
align-items: center;
gap: 0.75rem;
}
</style>Dynamic and Lazy
Combine v-if with lazyMount and unmountOnExit for panels that appear as data becomes available.
<script setup>
import { ref } from "vue";
import { Tabs } from "@dicehub/kappa/components/tabs";
const showInspect = ref(false);
</script>
<template>
<Tabs.Root lazy-mount unmount-on-exit default-value="overview">
<Tabs.List>
<Tabs.Trigger value="overview">Overview</Tabs.Trigger>
<Tabs.Trigger value="logs">Logs</Tabs.Trigger>
<Tabs.Trigger v-if="showInspect" value="inspect">Inspect</Tabs.Trigger>
<Tabs.Indicator />
</Tabs.List>
<Tabs.Content value="overview">Overview is mounted only while selected.</Tabs.Content>
<Tabs.Content value="logs">Logs mount only when selected.</Tabs.Content>
<Tabs.Content v-if="showInspect" value="inspect">Inspect is dynamic content.</Tabs.Content>
</Tabs.Root>
<button type="button" @click="showInspect = !showInspect">
{{ showInspect ? "Remove inspect" : "Add inspect" }}
</button>
</template>Content-rich
Panels accept normal Vue content, including metrics, tables, forms, and review notes.
<Tabs.Root default-value="metrics">
<Tabs.List>
<Tabs.Trigger value="metrics">Metrics</Tabs.Trigger>
<Tabs.Trigger value="boundaries">Boundaries</Tabs.Trigger>
<Tabs.Trigger value="notes">Notes</Tabs.Trigger>
<Tabs.Indicator />
</Tabs.List>
<Tabs.Content value="metrics">
<dl>
<div><dt>Cells</dt><dd>2.4M</dd></div>
<div><dt>Residual</dt><dd>8.4e-6</dd></div>
<div><dt>Courant max</dt><dd>0.82</dd></div>
</dl>
</Tabs.Content>
<Tabs.Content value="boundaries">
<table><caption>Patch summary</caption>...</table>
</Tabs.Content>
<Tabs.Content value="notes">Add review notes alongside any Vue content.</Tabs.Content>
</Tabs.Root>Accessibility
- The list uses
role="tablist"; each trigger usesrole="tab"and each panel usesrole="tabpanel". - Tab enters the selected trigger. Arrow keys move between enabled triggers; Home and End move to the first and last trigger.
- Horizontal lists use Left and Right arrows. Vertical lists use Up and Down arrows. Direction follows the root locale and
dir. - Automatic activation selects a tab on focus. Manual activation moves focus first and waits for Enter or Space to select.
- Disabled triggers are unavailable and skipped by directional keyboard navigation.
- Keep trigger labels concise and give the root an accessible name when the visible context is not enough.
- Keep focus visible. Indicator and trigger transitions honor
prefers-reduced-motion.
Kappa preserves Ark UI behavior.
API Reference
Tabs.Root
| Prop | Type | Default | Description |
|---|---|---|---|
modelValue | string | - | Controlled selected value; supports v-model. |
defaultValue | string | - | Initial selected value for uncontrolled tabs. |
activationMode | automatic | manual | automatic | Activate on focus, or wait for Enter or Space after focus. |
orientation | horizontal | vertical | horizontal | Changes layout semantics and directional keyboard navigation. |
dir | ltr | rtl | inherited | Overrides the inherited Ark UI locale direction. |
loopFocus | boolean | true | Wraps arrow-key focus from the last enabled trigger to the first. |
deselectable | boolean | false | Allows the active tab to be cleared when clicked again. |
composite | boolean | true | Uses a roving tab stop for the tablist and panel focus behavior. |
lazyMount | boolean | false | Delays each content panel until it is selected for the first time. |
unmountOnExit | boolean | false | Removes deselected content panels from the DOM. |
id | string | generated | Stable identifier for the Ark UI state machine. |
ids | TabsRootProps['ids'] | generated | Overrides generated root, list, trigger, content, and indicator IDs. |
navigate | (details) => void | - | Handles navigation when triggers are composed as links. |
translations | TabsRootProps['translations'] | - | Localized tablist labels used by Ark UI. |
asChild | boolean | false | Merges root behavior into one custom child element. |
Tabs.List
| Prop | Type | Default | Description |
|---|---|---|---|
variant | segmented | line | segmented | Uses a compact selected surface or a full-width selection line. |
size | sm | base | base | Controls the list height, trigger spacing, and type scale. |
asChild | boolean | false | Composes tablist behavior onto one custom element. |
Tabs.Trigger
| Prop | Type | Default | Description |
|---|---|---|---|
value | string | required | Unique value paired with one content panel. |
disabled | boolean | false | Prevents activation and removes the trigger from arrow-key navigation. |
asChild | boolean | false | Composes tab behavior onto one custom button or link. |
Tabs.Content
| Prop | Type | Default | Description |
|---|---|---|---|
value | string | required | Value that selects this content panel. |
asChild | boolean | false | Composes panel semantics onto one custom element. |
Parts
| Part | Element | Description |
|---|---|---|
Tabs.Root | div | Owns selected value, activation mode, orientation, locale direction, and render strategy. |
Tabs.RootProvider | div | Root variant driven by an external useTabs machine. |
Tabs.List | div[role=tablist] | Keyboard navigation container with the localized tablist semantics. |
Tabs.Trigger | button[role=tab] | Selects a value and participates in Ark UI roving focus. |
Tabs.Content | div[role=tabpanel] | Associated panel with managed visibility and labelled-by relationship. |
Tabs.Indicator | div | Optional measured surface that follows the selected trigger. |
Tabs.Context | renderless | Exposes the reactive Ark UI tabs API to a scoped slot. |
Events
| Event | Payload | Description |
|---|---|---|
update:modelValue | string | Emitted when the selected tab changes; drives v-model. |
valueChange | { value: string } | Ark UI detail emitted after the selected value changes. |
focusChange | { focusedValue: string } | Ark UI detail emitted when the focused trigger changes. |
Exports
| Export | Description |
|---|---|
Tabs | Compound API exposing Root, RootProvider, List, Trigger, Content, Indicator, and Context. |
TabsRoot | Unaugmented root with controlled and uncontrolled selected value. |
TabsRootProvider | Root backed by an external useTabs state machine. |
TabsList | Accessible tablist container. |
TabsTrigger | Keyboard-operable tab trigger. |
TabsContent | Associated tabpanel with optional lazy rendering. |
TabsIndicator | Optional moving selection surface. |
TabsContext | Scoped-slot state access. |
useTabs | Creates a Tabs state machine for RootProvider. |
useTabsContext | Reads Tabs state inside the compound component. |
tabsAnatomy | Ark UI part anatomy metadata. |
TabsProps | Public root prop contract. |
TabsEmits | Root event contract. |
TabsVariant | Segmented or line list treatment. |
TabsSize | Small or base list geometry. |
TABS_VARIANTS | Supported visual variant values. |
TABS_SIZES | Supported size values. |
TabsValueChangeDetails | Payload for valueChange. |
TabsFocusChangeDetails | Payload for focusChange. |