<script lang="ts" setup>
import { ATabsContent, ATabsIndicator, ATabsList, ATabsRoot, ATabsTrigger } from 'akar';
const items = [
{
label: 'Tab1',
content: 'This is the content shown for Tab1',
},
{
label: 'Tab2',
content: 'And, this is the content for Tab2',
},
{
label: 'Tab3',
content: 'Finally, this is the content for Tab3',
},
];
</script>
<template>
<ATabsRoot
class="flex flex-col gap-2 w-80 items-center"
default-value="Tab1"
>
<ATabsList
class="group p-1 rounded-lg bg-background-elevated flex w-full relative"
>
<ATabsIndicator class="rounded-md bg-primary w-$akar-tabs-indicator-size shadow-xs translate-x-$akar-tabs-indicator-position transition-[transform,width]-200 inset-y-1 left-0 absolute" />
<ATabsTrigger
v-for="tabItem in items"
:key="tabItem.label"
class="group text-sm font-medium px-3 py-1.5 rounded-md inline-flex grow gap-1.5 min-w-0 transition-colors-280 items-center justify-center relative data-[state=active]:color-text-inverted data-[state=inactive]:color-text-muted focus-visible:(outline-2 outline-primary outline-offset-2) disabled:(opacity-75 cursor-not-allowed) hover:data-[state=inactive]:not-disabled:color-text"
:value="tabItem.label"
>
{{ tabItem.label }}
</ATabsTrigger>
</ATabsList>
<ATabsContent
v-for="tabItem in items"
:key="tabItem.label"
class="w-full focus:outline-none"
:value="tabItem.label"
>
{{ tabItem.content }}
</ATabsContent>
</ATabsRoot>
</template>
Import all parts and piece them together.
<script setup>
import { ATabsContent, ATabsIndicator, ATabsList, ATabsRoot, ATabsTrigger } from 'akar';
</script>
<template>
<ATabsRoot>
<ATabsList>
<ATabsIndicator />
<ATabsTrigger />
</ATabsList>
<ATabsContent />
</ATabsRoot>
</template>
One benefit of using Akar is its flexibility and low-level control over the components. However, this also means that you may need to manually construct more complex UI elements by combining multiple Akar components together.
If you feel there's a lot of elements that needs to be constructed manually using Akar, consider using Pohon UI instead. It provides a higher-level abstraction over Akar components with pre-defined styles and behaviors that can help you build UIs faster.
Contains all the tabs component parts.
| Prop | Default | Type |
|---|---|---|
as | 'div' | APrimitiveAsTag | ComponentThe element or component this component should render as. Can be overwritten by |
activationMode | 'automatic' | 'automatic' | 'manual'Whether a tab is activated automatically (on focus) or manually (on click). |
asChild | booleanChange the default rendered element for the one passed as a child, merging their props and behavior. Read our Composition guide for more details. | |
defaultValue | string | numberThe value of the tab that should be active when initially rendered. Use when you do not need to control the state of the tabs | |
dir | 'ltr' | 'rtl'The reading direction of the combobox when applicable. | |
modelValue | string | number | |
orientation | 'horizontal' | 'horizontal' | 'vertical'The orientation the tabs are laid out. Mainly so arrow navigation is done accordingly (left & right vs. up & down) |
unmountOnHide | true | booleanWhen |
| Event | Type |
|---|---|
update:modelValue | [payload: StringOrNumber]Event handler called when the value changes |
| Slot | Type |
|---|---|
modelValue | string | numberThe controlled value of the tab to activate. Can be bind as |
| Attribute | Value |
|---|---|
[data-orientation] | 'vertical' | 'horizontal' |
Contains the triggers that are aligned along the edge of the active content.
| Prop | Default | Type |
|---|---|---|
as | 'div' | APrimitiveAsTag | ComponentThe element or component this component should render as. Can be overwritten by |
asChild | booleanChange the default rendered element for the one passed as a child, merging their props and behavior. Read our Composition guide for more details. | |
loop | true | booleanWhen |
| Attribute | Value |
|---|---|
[data-orientation] | 'vertical' | 'horizontal' |
The button that activates its associated content.
| Prop | Default | Type |
|---|---|---|
as | 'button' | APrimitiveAsTag | ComponentThe element or component this component should render as. Can be overwritten by |
asChild | booleanChange the default rendered element for the one passed as a child, merging their props and behavior. Read our Composition guide for more details. | |
disabled | false | booleanWhen |
value* | string | numberA unique value that associates the trigger with a content. |
| Attribute | Value |
|---|---|
[data-state] | 'active' | 'inactive' |
[data-disabled] | Present when disabled |
[data-orientation] | 'vertical' | 'horizontal' |
The indicator that highlights the current active tab.
| Prop | Default | Type |
|---|---|---|
as | 'div' | APrimitiveAsTag | ComponentThe element or component this component should render as. Can be overwritten by |
asChild | booleanChange the default rendered element for the one passed as a child, merging their props and behavior. Read our Composition guide for more details. |
| Variable | Description |
|---|---|
--akar-tabs-indicator-size | The size of the indicator |
--akar-tabs-indicator-position | The position of the indicator |
Contains the content associated with each trigger.
| Prop | Default | Type |
|---|---|---|
as | 'div' | APrimitiveAsTag | ComponentThe element or component this component should render as. Can be overwritten by |
asChild | booleanChange the default rendered element for the one passed as a child, merging their props and behavior. Read our Composition guide for more details. | |
forceMount | booleanUsed to force mounting when more control is needed. Useful when controlling animation with Vue animation libraries. | |
value* | string | numberA unique value that associates the trigger with a content. |
| Attribute | Value |
|---|---|
[data-state] | 'active' | 'inactive' |
[data-orientation] | 'vertical' | 'horizontal' |
You can create vertical tabs by using the orientation prop.
<script setup>
import { ATabsContent, ATabsList, ATabsRoot, ATabsTrigger } from 'akar';
</script>
<template>
<ATabsRoot
default-value="tab1"
orientation="vertical"
>
<ATabsList aria-label="tabs example">
<ATabsTrigger value="tab1">
One
</ATabsTrigger>
<ATabsTrigger value="tab2">
Two
</ATabsTrigger>
<ATabsTrigger value="tab3">
Three
</ATabsTrigger>
</ATabsList>
<ATabsContent value="tab1">
Tab one content
</ATabsContent>
<ATabsContent value="tab2">
Tab two content
</ATabsContent>
<ATabsContent value="tab3">
Tab three content
</ATabsContent>
</ATabsRoot>
</template>
Adheres to the ATabs WAI-ARIA design pattern.
| Key | Description |
|---|---|
Tab | When focus moves onto the tabs, focuses the active trigger. When a trigger is focused, moves focus to the active content. |
ArrowDown | Moves focus to the next trigger depending on |
ArrowRight | Moves focus to the next trigger depending on |
ArrowUp | Moves focus to the previous trigger depending on |
ArrowLeft | Moves focus to the previous trigger depending on |
Home | Moves focus to the first trigger and activates its associated content. |
End | Moves focus to the last trigger and activates its associated content. |