Tabs
Accessible, unstyled tabset primitive with roving focus and SSR-stable ids.
|
|
| Package |
@vizejs/ui/tabs |
| Maturity |
stable |
| Own the source |
vize lib pull tabs |
| Requires |
collection, composite-navigation, context, controllable-state, typeahead |
| Aliases |
tablist, tab panels, segmented navigation, application sections |
| Covers |
WAI-ARIA tabs pattern, React Aria Tabs, Radix Tabs, Reka UI Tabs |
Usage
import { Tabs, TabsRoot, TabsContent, TabsList, TabsTrigger } from "@vizejs/ui/tabs";
Or copy the source into your project with vize lib pull tabs (see Source Distribution).
API
Tabs
Source: src/families/navigation/tabs/tabs-root.vue
Props
| Prop |
Type |
Default |
Description |
id |
string | null |
undefined |
Consumer-owned Tabs base id. null and undefined select a deterministic fallback. |
modelValue |
TabsValue |
undefined |
Controlled selected tab value. undefined selects uncontrolled behavior; null clears it. |
defaultValue |
TabsValue |
undefined |
Initial selected value for uncontrolled use. undefined selects the first enabled trigger. |
disabled |
boolean |
false |
Disable every trigger while preserving the current selected panel. |
activationMode |
TabsActivationMode |
"automatic" |
Whether arrow focus activates tabs immediately or waits for Enter, Space, or click. |
orientation |
TabsOrientation |
"horizontal" |
Directional layout hint used by roving arrow-key focus. |
dir |
TabsDirection |
undefined |
Reading direction used for horizontal arrow-key navigation. undefined inherits DirectionProvider/LocaleProvider, then "ltr". |
loop |
boolean |
true |
Whether arrow-key navigation wraps at the first and last enabled trigger. |
Events
| Event |
Payload |
Description |
update:modelValue |
[value: TabsValue] |
Fired when the selected value requests a new controlled value. |
change |
[value: TabsValue, previous: TabsValue, nativeEvent: Event | null] |
Fired after any distinct selected-value request. |
Slots
| Slot |
Slot props |
Description |
default |
TabsSlotState |
Compound Tabs children. Receives current selection, orientation, and availability state. |
Exposed
| Member |
Type |
Description |
activationMode |
— |
|
dir |
— |
|
disabled |
— |
|
element |
Readonly<ShallowRef<HTMLElement | null>> |
Template ref to the rendered root element. |
focus |
— |
|
id |
— |
|
listId |
— |
|
orientation |
— |
|
reset |
— |
|
setValue |
— |
|
state |
— |
|
value |
— |
|
TabsRoot
Source: src/families/navigation/tabs/tabs-root.vue
Props
| Prop |
Type |
Default |
Description |
id |
string | null |
undefined |
Consumer-owned Tabs base id. null and undefined select a deterministic fallback. |
modelValue |
TabsValue |
undefined |
Controlled selected tab value. undefined selects uncontrolled behavior; null clears it. |
defaultValue |
TabsValue |
undefined |
Initial selected value for uncontrolled use. undefined selects the first enabled trigger. |
disabled |
boolean |
false |
Disable every trigger while preserving the current selected panel. |
activationMode |
TabsActivationMode |
"automatic" |
Whether arrow focus activates tabs immediately or waits for Enter, Space, or click. |
orientation |
TabsOrientation |
"horizontal" |
Directional layout hint used by roving arrow-key focus. |
dir |
TabsDirection |
undefined |
Reading direction used for horizontal arrow-key navigation. undefined inherits DirectionProvider/LocaleProvider, then "ltr". |
loop |
boolean |
true |
Whether arrow-key navigation wraps at the first and last enabled trigger. |
Events
| Event |
Payload |
Description |
update:modelValue |
[value: TabsValue] |
Fired when the selected value requests a new controlled value. |
change |
[value: TabsValue, previous: TabsValue, nativeEvent: Event | null] |
Fired after any distinct selected-value request. |
Slots
| Slot |
Slot props |
Description |
default |
TabsSlotState |
Compound Tabs children. Receives current selection, orientation, and availability state. |
Exposed
| Member |
Type |
Description |
value |
TabsValue |
Current selected value, or null when no tab is selected. |
disabled |
boolean |
Whether the root suppresses all trigger activation and roving focus. |
activationMode |
TabsActivationMode |
Whether focus movement activates tabs automatically. |
orientation |
TabsOrientation |
Directional layout hint used by tablist keyboard navigation. |
dir |
TabsDirection |
Reading direction used for horizontal arrow navigation. |
state |
TabsState |
Stable state token for styling and tests. |
element |
HTMLDivElement | null |
Rendered root element. |
id |
string |
Root-owned base id for the Tabs family. |
listId |
string |
Id wired to TabsList. |
focus |
(options?: FocusOptions) => void |
Move focus to the selected, active, or first enabled trigger. |
setValue |
(value: TabsValue, event?: Event | null) => boolean |
Request a selected value update and report whether it differs. |
reset |
() => boolean |
Restore the default value, or the first enabled trigger when no default exists. |
TabsContent
Source: src/families/navigation/tabs/tabs-content.vue
Props
| Prop |
Type |
Default |
Description |
value (required) |
string |
required |
Content value paired with a TabsTrigger. |
ariaLabel |
string |
undefined |
Accessible name when no visible label or aria-labelledby supplies one. |
ariaLabelledby |
string | null |
undefined |
Space-separated ids that label the panel. null omits the default trigger id. |
ariaDescribedby |
string |
undefined |
Space-separated ids that describe the panel. |
Slots
| Slot |
Slot props |
Description |
default |
TabsContentSlotState |
Panel contents. Receives current visibility, orientation, and availability state. |
Exposed
| Member |
Type |
Description |
value |
string |
Content value paired with a TabsTrigger. |
selected |
boolean |
Whether this panel is currently selected and visible. |
disabled |
boolean |
Whether the Tabs root suppresses trigger activation. |
orientation |
TabsOrientation |
Directional layout hint inherited from the Tabs root. |
state |
TabsContentState |
Stable state token for styling and tests. |
element |
HTMLDivElement | null |
Rendered tabpanel element. |
id |
string |
Deterministic id wired from content to trigger. |
focusContent |
(options?: FocusOptions) => void |
Move focus to the visible content panel. |
TabsList
Source: src/families/navigation/tabs/tabs-list.vue
Props
| Prop |
Type |
Default |
Description |
ariaLabel |
string |
undefined |
Accessible name when no visible label or aria-labelledby supplies one. |
ariaLabelledby |
string |
undefined |
Space-separated ids that label the tablist. |
ariaDescribedby |
string |
undefined |
Space-separated ids that describe the tablist. |
Slots
| Slot |
Slot props |
Description |
default |
TabsListSlotState |
TabsTrigger children. Receives the current root and list state. |
Exposed
| Member |
Type |
Description |
value |
TabsValue |
Current selected value, or null when no tab is selected. |
disabled |
boolean |
Whether the root suppresses all trigger activation and roving focus. |
activationMode |
TabsActivationMode |
Whether focus movement activates tabs automatically. |
orientation |
TabsOrientation |
Directional layout hint used by tablist keyboard navigation. |
dir |
TabsDirection |
Reading direction used for horizontal arrow navigation. |
state |
TabsState |
Stable state token for styling and tests. |
listId |
string |
Deterministic id assigned to the tablist. |
element |
HTMLDivElement | null |
Rendered tablist element. |
focus |
(options?: FocusOptions) => void |
Move focus to the selected, active, or first enabled trigger. |
TabsTrigger
Source: src/families/navigation/tabs/tabs-trigger.vue
Props
| Prop |
Type |
Default |
Description |
value (required) |
string |
required |
Trigger value used by the Tabs selection model. |
type |
"button" | "reset" | "submit" |
"button" |
Native button submission behavior. |
disabled |
boolean |
false |
Disable this trigger while preserving the current selected panel. |
textValue |
string | null |
undefined |
Explicit text used by future collection search or virtualized trigger labels. |
order |
number |
undefined |
Deterministic order for virtualized, portalled, or server-only triggers. |
ariaLabel |
string |
undefined |
Accessible name when no visible label or aria-labelledby supplies one. |
ariaLabelledby |
string |
undefined |
Space-separated ids that label the trigger. |
ariaDescribedby |
string |
undefined |
Space-separated ids that describe the trigger. |
Events
| Event |
Payload |
Description |
click |
[nativeEvent: MouseEvent] |
Fired before this trigger requests selection. Call preventDefault() to keep state unchanged. |
Slots
| Slot |
Slot props |
Description |
default |
TabsTriggerSlotState |
Trigger contents. Receives current selection, orientation, and availability state. |
indicator |
TabsTriggerSlotState |
Optional indicator slot for consumer-owned active-marker rendering. |
Exposed
| Member |
Type |
Description |
value |
string |
Trigger value used by the Tabs selection model. |
selected |
boolean |
Whether this trigger controls the selected tabpanel. |
disabled |
boolean |
Whether this trigger or its root suppresses activation. |
activationMode |
TabsActivationMode |
Whether focus movement activates tabs automatically. |
orientation |
TabsOrientation |
Directional layout hint inherited from the Tabs root. |
state |
TabsTriggerState |
Stable state token for styling and tests. |
element |
HTMLButtonElement | null |
Rendered native tab button. |
id |
string |
Deterministic id wired from trigger to content. |
focus |
(options?: FocusOptions) => void |
Move focus to the trigger. |
Behavior
Normative state x input -> outcome table for tabs-root.vue, tabs-list.vue,
tabs-trigger.vue, and tabs-content.vue (@vizejs/ui/tabs). Every row in
this isolated slice is proven by the named focused tests; registry, package
exports, renderer fixtures, and size budgets are intentionally left for the
parent integration step.
| ID |
State |
Input |
Outcome |
Evidence |
| T1 |
default / selected |
render |
root, tablist, tab, and tabpanel expose deterministic ids, ARIA wiring, slots, and data |
renders accessible tab semantics with deterministic ids and slots |
| T2 |
uncontrolled automatic |
Arrow key |
roving focus skips disabled triggers and immediately selects the focused tab |
automatic activation follows roving focus and skips disabled triggers |
| T3 |
uncontrolled manual |
Arrow key, then Space |
focus moves without selection until native activation requests the focused tab |
manual activation waits for keyboard or pointer activation |
| T4 |
controlled |
click |
emits requested value while rendered selection stays controlled until parent accepts it |
controlled value wins until the parent accepts the request |
| T5 |
disabled root / trigger |
click or Tab |
disabled triggers leave activation and sequential focus while preserving content state |
disabled roots and triggers suppress activation and focus |
| T6 |
exposed instances |
focus, setValue, reset |
public refs expose element state and imperative focus/value methods |
exposes typed state and imperative focus/value controls |
| T7 |
missing provider |
setup |
compound parts fail closed with the shared context diagnostic |
compound parts require a matching root provider |
| T8 |
SSR and hydration |
isolated render/mount |
generated ids are byte-identical per request and hydrate without replacement warnings |
tabs-ssr.test.ts |
Content panels use hidden while inactive, retain stable tabpanel markup for
hydration, and default aria-labelledby to the paired trigger id. Trigger
indicator is a named slot for consumer-owned active marker rendering; no
visual styling ships with the primitive.