Props
| Name | Description |
|---|---|
block Type: booleanDefaultfalse | Displays the component as full width. Full width with equal-width triggers, measured from the widest so they stay even once the strip overflows. On a vertical strip it stretches every trigger to the column width instead. It replaces the full-width class most v2 projects wrote for themselves: delete yours, or the two fight over the same declarations with nothing to say which won. See example |
compact Type: booleanDefaultfalse | Adds a CSS class that applies a compact style to the component. Drops the whole scale one notch (a 28px strip with smaller text and padding) so it lines up with compact fields. See example |
direction Type: "horizontal" | "vertical"Default"horizontal" | Direction of the tabs component. A vertical strip becomes a column beside the panels and answers Up/Down as well as Left/Right. Add |
disableAnimateX Type: booleanDefaultfalse | Disables the horizontal slide transition between tab panels (enabled by default). Inverted from v2's |
disableAnimateY Type: booleanDefaultfalse | Disables the smooth height animation when switching between tab panels (enabled by default). Inverted from v2's |
disabled Type: booleanDefaultfalse | Disables the component Disables the whole group: every trigger goes disabled and keyboard navigation is inert. For a single unreachable tab, set |
eager Type: booleanDefaultfalse | Renders every tab's panel at mount and keeps it mounted, hidden while inactive, instead of only the active one. One tab alone: its item's Mounts every panel from the first render and keeps it mounted, hidden while inactive; a lazy panel unmounts on every switch away and loses its state. Prefer the per-item form ( |
headers Type: Record<string, string> | Additional HTTP headers forwarded to Inertia when navigation is triggered. Only meaningful in an Inertia context. |
id Type: string | The root's Also the address for |
items requiredType: BbTabsItem<K>[] | Array of items that define the tabs in the component. Each entry carries its own |
manualActivation Type: booleanDefaultundefined (on when server is set on the strip or an item) | Arrow keys (and Home / End) only move focus; Enter or Space opens the tab (APG manual activation, Radix |
modelValue Type: K | null | The active tab's The raw item |
navigation Type: booleanDefaultfalse | Synchronizes the current tab with the URL query parameter.
Pair it with Makes the strip a writer of the URL query. Pair it with |
onBefore Type: (() => boolean | void) | Inertia lifecycle hook — fired just before the request is sent. Return |
onCancel Type: (() => void) | Inertia lifecycle hook — fired when the request is cancelled. |
onError Type: ((errors: Record<string, string>) => void) | Inertia lifecycle hook — fired when the server returns validation errors. |
onFinish Type: (() => void) | Inertia lifecycle hook — fired after the visit finishes (success or error). |
only Type: string[] | Limits which server-side props are refreshed during a partial Inertia reload. Only meaningful in an Inertia context. |
onProgress Type: ((progress: { percentage: number | undefined; }) => void) | Inertia lifecycle hook — fired when upload/download progress is available. |
onStart Type: (() => void) | Inertia lifecycle hook — fired when the request starts. |
onSuccess Type: (() => void) | Inertia lifecycle hook — fired when the visit completes successfully. |
preserveScroll Type: boolean | ((props: Record<string, unknown>) => boolean) | Controls whether Inertia preserves the scroll position after navigation. Only meaningful in an Inertia context. |
preserveState Type: boolean | ((props: Record<string, unknown>) => boolean) | null | Controls whether Inertia preserves the current component state after navigation. Only meaningful in an Inertia context. |
pt Type: ({ root?: PtValue | undefined; panel?: PtValue | undefined; "root:disabled"?: PtValue | undefined; "root:active"?: PtValue | undefined; "item:disabled"?: PtValue | undefined; "item:active"?: PtValue | undefined; list?: PtValue | undefined; indicator?: PtValue | undefined; "list:disabled"?: PtValue | undefined; "indicator:disabled"?: PtValue | undefined; "item:pill"?: PtValue | undefined; "item:line"?: PtValue | undefined; "panel:disabled"?: PtValue | undefined; "panel:active"?: PtValue | undefined; wrapper?: PtValue | undefined; panels?: PtValue | undefined; "list:active"?: PtValue | undefined; "indicator:active"?: PtValue | undefined; "wrapper:disabled"?: PtValue | undefined; "wrapper:active"?: PtValue | undefined; "panels:disabled"?: PtValue | undefined; "panels:active"?: PtValue | undefined; "item:none"?: PtValue | undefined; } & { item?: PtValue | PtItemFn<BbTabsItem<K>, BbTabsPtState, "none" | "pill" | "line", { readonly item: BbTabsItem<K>; }> | undefined; } & { "indicator:pill"?: PtValue | undefined; "indicator:line"?: PtValue | undefined; "item:pill"?: PtValue | undefined; "item:line"?: PtValue | undefined; "list:pill"?: PtValue | undefined; "list:line"?: PtValue | undefined; "item:none"?: PtValue | undefined; "list:none"?: PtValue | undefined; "indicator:none"?: PtValue | undefined; "wrapper:none"?: PtValue | undefined; "wrapper:pill"?: PtValue | undefined; "wrapper:line"?: PtValue | undefined; }) | Passthrough, object form: the same keys as the |
pt:<part> Type: PtValue | ((ctx: PtItemCtx<BbTabsItem<K>, BbTabsPtState, "none" | "pill" | "line">) => PtItemResult) | Passthrough, attribute form: one attribute per part, |
queryKey Type: stringDefault"tab" | Defines the query key used for URL-based navigation. Spelled |
replace Type: booleanDefaultfalse | Replaces the history entry instead of pushing one when the tab changes. Recommended with Effectively required alongside |
server Type: booleanDefaultfalse | When true and in an Inertia context, triggers a real server-side Inertia visit instead of a client-only |
variant Type: keyof TabsVariantRegistryDefault"pill" | Look of the tab strip:
|
v-model
Values kept in sync through v-model.
| Name | Description |
|---|---|
modelValue Type: K | null | See example |
Events
| Name | Description |
|---|---|
update:modelValue Type: (value: K): void | Emitted when the selected tab changes. Used by The whole event surface. It also fires once on mount when the component resolves a value the parent never set (from the URL query or the first-enabled fallback), so a binding starts aligned. See example |
Slots
The listed properties are the ones exposed to the slot scope.
| Name | Description |
|---|---|
<value> Type: BbTabsSlotProps<K> | One tab's content panel, by the tab's The panel. Its name is the value in kebab-case ( |
<value>:label Type: BbTabsSlotProps<K> | One tab trigger's label, by the tab's The value in kebab-case: |
label Type: BbTabsSlotProps<K> | Fallback slot used for all tab labels when no per-tab The fallback for every trigger; a |
wrapper:append Type: BbTabsScrollSlotProps | Content rendered after the scrollable tab label list (e.g. a right scroll arrow). The trailing counterpart of |
wrapper:prepend Type: BbTabsScrollSlotProps | Content rendered before the scrollable tab label list (e.g. a left scroll arrow). Rendered outside the scrollable list, so it stays put while the strip moves. The buttons are your markup, which means an icon-only arrow needs an |
Renamed and removed
Names from v2 and from earlier 3.0 betas that no longer work, and what to write instead.
animateXdisableAnimateXfails silentlyanimateYdisableAnimateYfails silently- slot
header:appendwrapper:appendfails silently - slot
header:prependwrapper:prependfails silently - item field
items[].keyitems[].valuefails silentlyA tab's identity: what
v-modelholds and its#<value>/#<value>:labelslots;check --fixrenames it. - slot
label:<x><x>:labelfails silently querykeyqueryKeyfails silently