Skip to content

Tabs

A set of layered sections of content—known as tab panels—that are displayed one at a time.

Make changes to your account here. Click save when you're done.

vue
vue
<script setup lang="ts">
import { TabsContent, TabsList, TabsRoot, TabsTrigger } from '@oku-ui/primitives'
</script>

<template>
  <TabsRoot
    class="flex flex-col w-full sm:w-[300px] shadow-[0_2px_10px] shadow-blackA4"
    default-value="tab1"
  >
    <TabsList
      class="relative shrink-0 flex border-b border-mauve6"
      aria-label="Manage your account"
    >
      <!-- <TabsIndicator class="absolute px-8 left-0 h-[2px] bottom-0 w-[--radix-tabs-indicator-size] translate-x-[--radix-tabs-indicator-position] rounded-full transition-[width,transform] duration-300">
        <div class="bg-grass8 w-full h-full" />
      </TabsIndicator> -->
      <TabsTrigger
        class="bg-white px-5 h-[45px] flex-1 flex items-center justify-center text-[15px] leading-none text-mauve12 select-none  rounded-tl-md  hover:text-mauve12 data-[state=active]:text-mauve12 outline-none cursor-default focus-visible:relative focus-visible:shadow-[0_0_0_2px] focus-visible:shadow-black"
        value="tab1"
      >
        Account
      </TabsTrigger>
      <TabsTrigger
        class="bg-white px-5 h-[45px] flex-1 flex items-center justify-center text-[15px] leading-none text-mauve12 select-none  rounded-tr-md hover:text-mauve12 data-[state=active]:text-mauve12 outline-none cursor-default focus-visible:relative focus-visible:shadow-[0_0_0_2px] focus-visible:shadow-black"
        value="tab2"
      >
        Password
      </TabsTrigger>
    </TabsList>
    <TabsContent
      class="grow p-5 bg-white rounded-b-md outline-none focus:shadow-[0_0_0_2px] focus:shadow-black"
      value="tab1"
    >
      <p class="mb-5 !mt-0 text-mauve12 text-[15px] !leading-normal">
        Make changes to your account here. Click save when you're done.
      </p>
      <fieldset class="mb-[15px] w-full flex flex-col justify-start">
        <label
          class="text-[13px] leading-none mb-2.5 text-indigo12 block"
          for="name"
        > Name </label>
        <input
          id="name"
          class="grow shrink-0 rounded px-2.5 text-[15px] leading-none text-mauve12 shadow-[0_0_0_1px] shadow-indigo7 h-[35px] focus:shadow-[0_0_0_2px] focus:shadow-indigo8 outline-none"
          value="Pedro Duarte"
        >
      </fieldset>
      <fieldset class="mb-[15px] w-full flex flex-col justify-start">
        <label
          class="text-[13px] leading-none mb-2.5 text-indigo12 block"
          for="username"
        > Username </label>
        <input
          id="username"
          class="grow shrink-0 rounded px-2.5 text-[15px] leading-none text-mauve12 shadow-[0_0_0_1px] shadow-indigo7 h-[35px] focus:shadow-[0_0_0_2px] focus:shadow-indigo8 outline-none"
          value="@peduarte"
        >
      </fieldset>
      <div class="flex justify-end mt-5">
        <button
          class="inline-flex items-center justify-center rounded px-[15px] text-[15px] leading-none font-medium h-[35px] bg-indigo4 text-indigo11 hover:bg-indigo5 focus:shadow-[0_0_0_2px] focus:shadow-indigo7 outline-none cursor-default"
        >
          Save changes
        </button>
      </div>
    </TabsContent>
    <TabsContent
      class="grow p-5 bg-white rounded-b-md outline-none focus:shadow-[0_0_0_2px] focus:shadow-black"
      value="tab2"
    >
      <p class="mb-5 !mt-0 text-mauve12 text-[15px] !leading-normal">
        Change your password here. After saving, you'll be logged out.
      </p>
      <fieldset class="mb-[15px] w-full flex flex-col justify-start">
        <label
          class="text-[13px] leading-none mb-2.5 text-indigo12 block"
          for="currentPassword"
        >
          Current password
        </label>
        <input
          id="currentPassword"
          class="grow shrink-0 rounded px-2.5 text-[15px] leading-none text-mauve12 shadow-[0_0_0_1px] shadow-indigo7 h-[35px] focus:shadow-[0_0_0_2px] focus:shadow-indigo8 outline-none"
          type="password"
        >
      </fieldset>
      <fieldset class="mb-[15px] w-full flex flex-col justify-start">
        <label
          class="text-[13px] leading-none mb-2.5 text-indigo12 block"
          for="newPassword"
        > New password </label>
        <input
          id="newPassword"
          class="grow shrink-0 rounded px-2.5 text-[15px] leading-none text-mauve12 shadow-[0_0_0_1px] shadow-indigo7 h-[35px] focus:shadow-[0_0_0_2px] focus:shadow-indigo8 outline-none"
          type="password"
        >
      </fieldset>
      <fieldset class="mb-[15px] w-full flex flex-col justify-start">
        <label
          class="text-[13px] leading-none mb-2.5 text-indigo12 block"
          for="confirmPassword"
        >
          Confirm password
        </label>
        <input
          id="confirmPassword"
          class="grow shrink-0 rounded px-2.5 text-[15px] leading-none text-mauve12 shadow-[0_0_0_1px] shadow-indigo7 h-[35px] focus:shadow-[0_0_0_2px] focus:shadow-indigo8 outline-none"
          type="password"
        >
      </fieldset>
      <div class="flex justify-end mt-5">
        <button
          class="inline-flex items-center justify-center rounded px-[15px] text-[15px] leading-none font-medium h-[35px] bg-indigo4 text-indigo11 hover:bg-indigo5 focus:shadow-[0_0_0_2px] focus:shadow-indigo7 outline-none cursor-default"
        >
          Change password
        </button>
      </div>
    </TabsContent>
  </TabsRoot>
</template>

Features

  • Can be controlled or uncontrolled.
  • Supports horizontal/vertical orientation.
  • Supports automatic/manual activation.
  • Full keyboard navigation.

Installation

Install the component from your command line.

sh
sh
$ npm add @oku-ui/primitives

Anatomy

Import all parts and piece them together.

vue
vue
<script setup>
import { TabsContent, TabsIndicator, TabsList, TabsRoot, TabsTrigger } from '@oku-ui/primitives'
</script>

<template>
  <TabsRoot>
    <TabsList>
      <TabsIndicator />
      <TabsTrigger />
    </TabsList>
    <TabsContent />
  </TabsRoot>
</template>

API Reference

Root

Contains all the tabs component parts.

PropDefaultType
activationMode
'automatic' | 'manual'

Whether a tab is activated automatically or manually.

defaultValue
string

The value of the tab to select by default, if uncontrolled

dir
'ltr' | 'rtl'

The direction of navigation between toolbar items.

orientation
'horizontal' | 'vertical'

The orientation the tabs are layed out. Mainly so arrow navigation is done accordingly (left & right vs. up & down)

value
string

The value for the selected tab, if controlled

EmitPayload
update:value
[value: string]
Data AttributeValue
[data-orientation]"vertical" | "horizontal"

List

Contains the triggers that are aligned along the edge of the active content.

PropDefaultType
loop
boolean
Data AttributeValue
[data-orientation]"vertical" | "horizontal"

Trigger

The button that activates its associated content.

PropDefaultType
as
'div'
object | AsTag
disabled
boolean
value*
string
Data AttributeValue
[data-state]"active" | "inactive"
[data-disabled]Present when disabled
[data-orientation]"vertical" | "horizontal"

Indicator

The indicator that highlights the current active tab.

CSS VariableDescription
--radix-tabs-indicator-size
The size of the indicator.
--radix-tabs-indicator-position
The position of the indicator

Content

Contains the content associated with each trigger.

PropDefaultType
forceMount
boolean

Used to force mounting when more control is needed. Useful when controlling animation with React animation libraries.

value*
string
Data AttributeValue
[data-state]"active" | "inactive"
[data-orientation]"vertical" | "horizontal"

Examples

Vertical

You can create vertical tabs by using the orientation prop.

vue
vue
<script setup>
import { TabsContent, TabsList, TabsRoot, TabsTrigger } from '@oku-ui/primitives'
</script>

<template>
  <TabsRoot
    default-value="tab1"
    orientation="vertical"
  >
    <TabsList aria-label="tabs example">
      <TabsTrigger value="tab1">
        One
      </TabsTrigger>
      <TabsTrigger value="tab2">
        Two
      </TabsTrigger>
      <TabsTrigger value="tab3">
        Three
      </TabsTrigger>
    </TabsList>
    <TabsContent value="tab1">
      Tab one content
    </TabsContent>
    <TabsContent value="tab2">
      Tab two content
    </TabsContent>
    <TabsContent value="tab3">
      Tab three content
    </TabsContent>
  </TabsRoot>
</template>

Accessibility

Adheres to the Tabs WAI-ARIA design pattern.

Keyboard Interactions

KeyDescription
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 orientation and activates its associated content.
ArrowRight
Moves focus to the next trigger depending on orientation and activates its associated content.
ArrowUp
Moves focus to the previous trigger depending on orientation and activates its associated content.
ArrowLeft
Moves focus to the previous trigger depending on orientation and activates its associated content.
Home
Moves focus to the first trigger and activates its associated content.
End
Moves focus to the last trigger and activates its associated content.