---
title: VerticalNavigation
description: Display a vertical navigation.
links:
  - label: GitHub
    icon: i-simple-icons-github
    to: https://github.com/nuxt/ui/blob/dev/src/runtime/components/navigation/VerticalNavigation.vue
---

## Usage

Pass an array to the `links` prop of the VerticalNavigation component. Each link can have the following properties:

- `label` - The label of the link.
- `icon` - The icon of the link.
- `iconClass` - The class of the icon of the link.
- `avatar` - The avatar of the link. You can pass all the props of the [Avatar](/elements/avatar) component.
- `badge` - A badge to display next to the label.
- `click` - The click handler of the link.

You can also pass any property from the [NuxtLink](https://nuxt.com/docs/api/components/nuxt-link#props) component such as `to`, `exact`, etc.

::component-example
#default
:vertical-navigation-example

#code
```vue
<script setup>
const links = [{
  label: 'Profile',
  avatar: {
    src: 'https://avatars.githubusercontent.com/u/739984?v=4'
  },
  badge: 100
}, {
  label: 'Installation',
  icon: 'i-heroicons-home',
  to: '/getting-started/installation'
}, {
  label: 'Vertical Navigation',
  icon: 'i-heroicons-chart-bar',
  to: '/navigation/vertical-navigation'
}, {
  label: 'Command Palette',
  icon: 'i-heroicons-command-line',
  to: '/navigation/command-palette'
}]
</script>

<template>
  <UVerticalNavigation :links="links" />
</template>
```
::

::callout{icon="i-heroicons-light-bulb"}
Learn how to build a Tailwind like vertical navigation in the [Examples](/getting-started/examples#verticalnavigation) page.
::

## Slots

You can use slots to customize links display.

### `default`

Use the `#default` slot to customize the link label. You will have access to the `link` and `isActive` properties in the slot scope.

::component-example
#default
:vertical-navigation-example-default-slot

#code
```vue
<script setup>
const links = [{
  label: 'Navigation',
  children: [{
    label: 'Vertical Navigation',
    to: '/navigation/vertical-navigation'
  }, {
    label: 'Command Palette',
    to: '/navigation/command-palette'
  }]
}, {
  label: 'Data',
  children: [{
    label: 'Table',
    to: '/data/table'
  }]
}]
</script>

<template>
  <UVerticalNavigation :links="links">
    <template #default="{ link }">
      <div class="relative text-left w-full">
        <div class="mb-2">
          {{ link.label }}
        </div>
        <UVerticalNavigation v-if="link.children" :links="link.children" />
      </div>
    </template>
  </UVerticalNavigation>
</template>
```
::

### `avatar`

Use the `#avatar` slot to customize the link avatar. You will have access to the `link` and `isActive` properties in the slot scope.

::component-example
#default
:vertical-navigation-example-avatar-slot

#code
```vue
<script setup>
const links = [{
  avatar: {
    src: 'https://avatars.githubusercontent.com/u/739984?v=4'
  },
  label: 'Benjamin Canac',
  to: 'https://github.com/benjamincanac',
  target: '_blank'
}, ...]

const { ui } = useAppConfig()
</script>

<template>
  <UVerticalNavigation :links="links">
    <template #avatar="{ link }">
      <UAvatar
        v-if="link.avatar"
        v-bind="{ size: ui.verticalNavigation.avatar.size, ...link.avatar }"
        :class="[ui.verticalNavigation.avatar.base]"
      />
      <UIcon v-else name="i-heroicons-user-circle-20-solid" class="text-lg" />
    </template>
  </UVerticalNavigation>
</template>
```
::

### `icon`

Use the `#icon` slot to customize the link icon. You will have access to the `link` and `isActive` properties in the slot scope.

::component-example
#default
:vertical-navigation-example-icon-slot

#code
```vue
<script setup>
const types = {
  bug: {
    icon: 'i-heroicons-bug-ant-20-solid',
    color: 'text-red-500'
  },
  docs: {
    icon: 'i-heroicons-document-text-20-solid',
    color: 'text-blue-500'
  },
  lock: {
    icon: 'i-heroicons-lock-closed-20-solid',
    color: 'text-gray dark:text-white'
  },
  default: {
    icon: 'i-heroicons-question-mark-circle-20-solid',
    color: 'text-green-500'
  }
}
const links = [{
  label: 'UDropdown and UPopover dropdown menu, dropdown will be obscured',
  type: 'bug'
}, {
  label: 'Uncaught (in promise) ReferenceError: ref is not defined',
  type: 'lock'
}, {
  label: 'Fully styled and customizable components for Nuxt.',
  type: 'docs'
}, {
  label: 'Can I pass a tailwind color to UNotifications with `toast.add()` ?'
}]
</script>

<template>
  <UVerticalNavigation :links="links">
    <template #icon="{ link }">
      <UIcon v-if="link.type" :name="types[link.type].icon" :class="types[link.type].color" class="text-base" />
      <UIcon v-else :name="types.default.icon" :class="types.default.color" class="text-base" />
    </template>
  </UVerticalNavigation>
</template>
```
::

### `badge`

Use the `#badge` slot to customize the link badge. You will have access to the `link` and `isActive` properties in the slot scope.

::component-example
#default
:vertical-navigation-example-badge-slot

#code
```vue
<script setup>
const links = [{
  label: '.github',
  icon: 'i-heroicons-folder-20-solid',
  badge: 'chore(github): use pnpm 8',
  time: 'last month'
}, {
  label: '.editorconfig',
  icon: 'i-heroicons-document-solid',
  badge: 'Initial commit',
  time: '2 years ago'
}, {
  label: '.package.json',
  icon: 'i-heroicons-document-solid',
  badge: 'chore(deps): bump',
  time: '16 hours ago'
}]
</script>

<template>
  <UVerticalNavigation
    :links="links"
    class="w-full"
    :ui="{
      label: 'truncate relative text-gray-900 dark:text-white flex-initial w-32 text-left'
    }"
  >
    <template #badge="{ link }">
      <div class="flex-1 flex justify-between relative truncate">
        <div>{{ link.badge }}</div>
        <div>{{ link.time }}</div>
      </div>
    </template>
  </UVerticalNavigation>
</template>
```
::

## Props

:component-props

## Preset

:component-preset
