Skip to content

Tabs ​

Switches between a few panels of content in place, chosen from a row of tabs.

vue
<script setup lang="ts">
import { FsTabs } from '@fivespark/ui'

const items = [
  { value: 'details', label: 'Details' },
  { value: 'regels', label: 'Regels' },
  { value: 'historie', label: 'Historie' },
]
</script>

<template>
  <FsTabs :items label="Onderdelen van de offerte" class="w-full">
    <template #details><p class="type-body pt-4">Klant, referentie en leverdatum.</p></template>
    <template #regels><p class="type-body pt-4">Twaalf regels, samen € 4.250,00.</p></template>
    <template #historie><p class="type-body pt-4">Aangemaakt op 3 november 2026.</p></template>
  </FsTabs>
</template>

Usage ​

vue
<script setup lang="ts">
import { FsTabs } from '@fivespark/ui'

const items = [
  { value: 'details', label: 'Details' },
  { value: 'regels', label: 'Regels' },
]
</script>

<template>
  <FsTabs :items label="Onderdelen van de offerte">
    <template #details>Klant en referentie.</template>
    <template #regels>De regels.</template>
  </FsTabs>
</template>

Each item's value is also the name of the slot holding its panel. Every panel is rendered; the inactive ones are hidden. Tabs are for panels on one page. To go to another page, use Navigation menu or Link. Use at least two tabs, and keep nothing interactive inside a tab itself.

Examples ​

Controlled with v-model ​

Bind v-model to the selected tab's value. Without it, the first tab is selected.

vue
<script setup lang="ts">
import { FsTabs } from '@fivespark/ui'
import { ref } from 'vue'

const items = [
  { value: 'open', label: 'Open' },
  { value: 'verstuurd', label: 'Verstuurd' },
  { value: 'akkoord', label: 'Akkoord' },
]
const tab = ref('verstuurd')
</script>

<template>
  <div class="w-full">
    <FsTabs v-model="tab" :items label="Status van offertes">
      <template #open><p class="type-body pt-4">Vijf offertes wachten op verzending.</p></template>
      <template #verstuurd><p class="type-body pt-4">Acht offertes wachten op een reactie.</p></template>
      <template #akkoord><p class="type-body pt-4">Twee offertes zijn goedgekeurd.</p></template>
    </FsTabs>
    <p class="type-meta mt-4">Gekozen: {{ tab }}</p>
  </div>
</template>

With counts ​

count is a whole number shown after the label and read as part of the tab's name.

vue
<script setup lang="ts">
import { FsTabs } from '@fivespark/ui'

const items = [
  { value: 'regels', label: 'Regels', count: 12 },
  { value: 'documenten', label: 'Documenten', count: 3 },
  { value: 'opmerkingen', label: 'Opmerkingen', count: 0 },
]
</script>

<template>
  <FsTabs :items label="Onderdelen van de order" class="w-full">
    <template #regels><p class="type-body pt-4">Twaalf orderregels.</p></template>
    <template #documenten><p class="type-body pt-4">Drie bijlagen.</p></template>
    <template #opmerkingen><p class="type-body pt-4">Nog geen opmerkingen.</p></template>
  </FsTabs>
</template>

Dense ​

size="dense" makes the tabs 32px high instead of 36px.

vue
<script setup lang="ts">
import { FsTabs } from '@fivespark/ui'

const items = [
  { value: 'week', label: 'Week' },
  { value: 'maand', label: 'Maand' },
]
</script>

<template>
  <FsTabs :items size="dense" label="Periode van de planning" class="w-full">
    <template #week><p class="type-body pt-4">Planning van deze week.</p></template>
    <template #maand><p class="type-body pt-4">Planning van deze maand.</p></template>
  </FsTabs>
</template>

Keyboard ​

KeyDoes
TabMoves focus into the row of tabs, to the selected tab; from the tab it moves on to the panel
→, ←Selects and focuses the next or the previous tab; past either end it wraps. In right-to-left text the arrows swap
Home, EndSelects and focuses the first or the last tab

API Reference ​

FsTabs ​

PropTypeDefaultDescription
items{ value: string; label: string; count?: number | undefined; }[]requiredThe tabs, in order. `value` names the panel's slot and is the model's value; `count`, a whole number, is shown after the label and read as part of the tab's name.
labelstringNames the row for assistive technology: for a page with two sets of tabs, or tabs under no heading.
size"default" | "dense""default"`default` is 36px high; `dense` is 32px.
modelValuestringThe selected tab's value. Without `v-model`, the first tab is selected.
EventPayloadDescription
update:modelValue[value: string | undefined]Sent with the new `modelValue`, for `v-model`.