Link

Provides a custom <NuxtLink> component to handle any kind of links within your application.

Examples

Basic

PropDefaultTypeDescription
inactiveClass-stringThe class to apply when the link is inactive.
exactfalsebooleanTrigger the link active class only on exact matches of the path.
exactQueryfalsebooleanTrigger the link active class only on exact matches of the query.
exactHashfalsebooleanTrigger the link active class only on exact matches of the hash.
Preview
Code

Slots

NamePropsDescription
default-The content of the link.

Props

types/link.ts
import type { NuxtLinkProps } from 'nuxt/app'

export interface NLinkProps extends NuxtLinkProps {
  /**
   * Manually enable/disable the exact match
   *
   * @default false
   */
  exact?: boolean
  /**
   * Manually enable/disable the exact match for the query string
   *
   * @default false
   */
  exactQuery?: boolean
  /**
   * Manually enable/disable the exact match for the hash
   *
   * @default false
   */
  exactHash?: boolean

  /**
   * Active classes to apply when the link is inactive
   *
   * @example 'text-primary'
   */
  inactiveClass?: string

  /**
   * Useful in combination with `NavLink` to apply the active class to the parent element
   *
   */
  navLinkActive?: string

  /**
   * Useful in combination with `NavLink` to apply the inactive class to the parent element
   */
  navLinkInactive?: string
}

Presets

shortcuts/link.ts
type LinkPrefix = 'link'

export const staticLink: Record<LinkPrefix, string> = {
  // base
  link: '',
}

export const dynamicLink: [RegExp, (params: RegExpExecArray) => string][] = [
  // dynamic preset
]

export const link = [
  ...dynamicLink,
  staticLink,
]

Components

Link.vue
<script lang="ts">
import type { PropType } from 'vue'
import type { NLinkProps } from '../../types'
import { NuxtLink } from '#components'
import { isEqual } from 'ohash'
import { defineComponent } from 'vue'

export default defineComponent({
  inheritAttrs: false,
  props: {
    ...NuxtLink.props,
    // config
    exact: {
      type: Boolean as PropType<NLinkProps['exact']>,
      default: false,
    },
    exactQuery: {
      type: Boolean as PropType<NLinkProps['exactQuery']>,
      default: false,
    },
    exactHash: {
      type: Boolean as PropType<NLinkProps['exactHash']>,
      default: false,
    },

    // styling
    inactiveClass: {
      type: String as PropType<NLinkProps['inactiveClass']>,
      default: undefined,
    },

    // preset
    navLinkActive: {
      type: String as PropType<NLinkProps['navLinkActive']>,
      default: undefined,
    },
    navLinkInactive: {
      type: String as PropType<NLinkProps['navLinkInactive']>,
      default: undefined,
    },
  },
  setup(props: any) {
    function resolveLinkClass(route: any, $route: any, { isActive, isExactActive }: { isActive: boolean, isExactActive: boolean }): string | null {
      if (props.exactQuery && !isEqual(route.query, $route.query))
        return props.inactiveClass

      if (props.exactHash && !isEqual(route.hash, $route.hash))
        return props.inactiveClass

      if (props.exact && isExactActive)
        return props.exactActiveClass

      if (!props.exact && isActive)
        return props.activeClass

      return props.inactiveClass
    }

    function resolveNavLinkActive(route: any, $route: any, { isActive, isExactActive }: { isActive: boolean, isExactActive: boolean }): string | null {
      if (props.exactQuery && !isEqual(route.query, $route.query))
        return null

      if (props.exactHash && !isEqual(route.hash, $route.hash))
        return null

      if (props.exact && isExactActive)
        return props.navLinkActive

      if (!props.exact && isActive)
        return props.navLinkActive

      return null
    }

    function resolveNavLinkInactive(route: any, $route: any, { isActive, isExactActive }: { isActive: boolean, isExactActive: boolean }): string | null {
      if (props.exactQuery && !isEqual(route.query, $route.query))
        return props.navLinkInactive

      if (props.exactHash && !isEqual(route.hash, $route.hash))
        return props.navLinkInactive

      if ((!props.exact && isActive) || (props.exact && isExactActive))
        return null

      return props.navLinkInactive
    }

    return {
      resolveLinkClass,
      resolveNavLinkActive,
      resolveNavLinkInactive,
    }
  },
})
</script>

<template>
  <!-- eslint-disable vue/no-template-shadow -->
  <NuxtLink
    v-slot="{ route, href, target, rel, navigate, isActive, isExactActive, isExternal, exact }"
    v-bind="$props"
    custom
  >
    <a
      v-bind="$attrs"
      :href="href"
      :rel="rel"
      :target="target"
      :class="resolveLinkClass(route, $route, { isActive, isExactActive })"
      :nav-link-active="resolveNavLinkActive(route, $route, { isActive, isExactActive })"
      :nav-link-inactive="resolveNavLinkInactive(route, $route, { isActive, isExactActive })"
      @click="(e) => !isExternal && navigate(e)"
    >
      <slot v-bind="{ isActive: exact ? isExactActive : isActive }" />
    </a>
  </NuxtLink>
</template>