Nuxt UI v3-alpha has been released!

Try it out
Components

VerticalNavigation

Display a list of vertical links.

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.
  • labelClass - The class of the link label.
  • icon - The icon of the link.
  • iconClass - The class of the link icon.
  • avatar - The avatar of the link. You can pass all the props of the Avatar component.
  • badge - A badge to display next to the label. You can pass all the props of the Badge component.
  • click - The click handler of the link.

You can also pass any property from the NuxtLink component such as to, exact, etc.

<script setup lang="ts">
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: '/components/vertical-navigation'
}, {
  label: 'Command Palette',
  icon: 'i-heroicons-command-line',
  to: '/components/command-palette'
}]
</script>

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

Sections

Group your navigation links into distinct sections, separated by a divider. You can do this by passing an array of arrays to the links prop of the VerticalNavigation component.

<script setup lang="ts">
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: '/components/vertical-navigation'
  }, {
    label: 'Command Palette',
    icon: 'i-heroicons-command-line',
    to: '/components/command-palette'
  }], [{
    label: 'Examples',
    icon: 'i-heroicons-light-bulb'
  }, {
    label: 'Help',
    icon: 'i-heroicons-question-mark-circle'
  }]
]
</script>

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

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.

<script setup lang="ts">
const links = [{
  label: 'Vertical Navigation',
  to: '/components/vertical-navigation'
}, {
  label: 'Command Palette',
  to: '/components/command-palette'
}, {
  label: 'Table',
  to: '/components/table'
}]
</script>

<template>
  <UVerticalNavigation :links="links">
    <template #default="{ link }">
      <span class="group-hover:text-primary relative">{{ link.label }}</span>
    </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.

<script setup lang="ts">
const links = [{
  avatar: {
    src: 'https://ipx.nuxt.com/s_16x16/gh_avatar/benjamincanac',
    srcset: 'https://ipx.nuxt.com/s_32x32/gh_avatar/benjamincanac 2x',
    alt: ''
  },
  label: 'benjamincanac',
  to: 'https://github.com/benjamincanac',
  target: '_blank'
}, {
  avatar: {
    src: 'https://ipx.nuxt.com/s_16x16/gh_avatar/Atinux',
    srcset: 'https://ipx.nuxt.com/s_32x32/gh_avatar/Atinux 2x',
    alt: ''
  },
  label: 'Atinux',
  to: 'https://github.com/Atinux',
  target: '_blank'
}, {
  avatar: {
    src: 'https://ipx.nuxt.com/s_16x16/gh_avatar/smarroufin',
    srcset: 'https://ipx.nuxt.com/s_32x32/gh_avatar/smarroufin 2x',
    alt: ''
  },
  label: 'smarroufin',
  to: 'https://github.com/smarroufin',
  target: '_blank'
}]
</script>

<template>
  <UVerticalNavigation :links="links">
    <template #avatar="{ link }">
      <UAvatar v-bind="link.avatar" size="2xs" loading="lazy" />
    </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.

<script setup lang="ts">
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"
    :ui="{ wrapper: 'truncate' }"
  >
    <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.

<script setup lang="ts">
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

ui
{ wrapper?: string; base?: string; ring?: string; padding?: string; width?: string; rounded?: string; font?: string; size?: string; active?: string; inactive?: string; label?: string; icon?: DeepPartial<{ base: string; active: string; inactive: string; }, any>; avatar?: DeepPartial<...>; badge?: DeepPartial<...>; di...
{}
links
VerticalNavigationLink[] | VerticalNavigationLink[][]
[]

Config

{
  wrapper: 'relative',
  base: 'group relative flex items-center gap-1.5 focus:outline-none focus-visible:outline-none dark:focus-visible:outline-none focus-visible:before:ring-inset focus-visible:before:ring-1 focus-visible:before:ring-primary-500 dark:focus-visible:before:ring-primary-400 before:absolute before:inset-px before:rounded-md disabled:cursor-not-allowed disabled:opacity-75',
  ring: 'focus-visible:ring-inset focus-visible:ring-2 focus-visible:ring-primary-500 dark:focus-visible:ring-primary-400',
  padding: 'px-2.5 py-1.5',
  width: 'w-full',
  rounded: 'rounded-md',
  font: 'font-medium',
  size: 'text-sm',
  active: 'text-gray-900 dark:text-white before:bg-gray-100 dark:before:bg-gray-800',
  inactive: 'text-gray-500 dark:text-gray-400 hover:text-gray-900 dark:hover:text-white hover:before:bg-gray-50 dark:hover:before:bg-gray-800/50',
  label: 'truncate relative',
  icon: {
    base: 'flex-shrink-0 w-5 h-5 relative',
    active: 'text-gray-700 dark:text-gray-200',
    inactive: 'text-gray-400 dark:text-gray-500 group-hover:text-gray-700 dark:group-hover:text-gray-200',
  },
  avatar: {
    base: 'flex-shrink-0',
    size: '2xs',
  },
  badge: {
    base: 'flex-shrink-0 ml-auto relative rounded',
    color: 'gray',
    variant: 'solid',
    size: 'xs',
  },
  divider: {
    wrapper: {
      base: 'p-2',
    },
  },
}

Example

Here is an example illustrating how you can customize the appearance of the VerticalNavigation component by utilizing its ui prop.

<script setup lang="ts">
const links = [{
  label: 'Introduction',
  to: '/getting-started'
}, {
  label: 'Installation',
  to: '/getting-started/installation'
}, {
  label: 'Theming',
  to: '/getting-started/theming'
}, {
  label: 'Shortcuts',
  to: '/getting-started/shortcuts'
}]
</script>

<template>
  <UVerticalNavigation
    :links="links"
    :ui="{
      wrapper: 'border-s border-gray-200 dark:border-gray-800 space-y-2',
      base: 'group block border-s -ms-px leading-6 before:hidden',
      padding: 'p-0 ps-4',
      rounded: '',
      font: '',
      ring: '',
      active: 'text-primary-500 dark:text-primary-400 border-current font-semibold',
      inactive: 'border-transparent hover:border-gray-400 dark:hover:border-gray-500 text-gray-700 hover:text-gray-900 dark:text-gray-400 dark:hover:text-gray-300'
    }"
  />
</template>