Git Product home page Git Product logo

Comments (4)

lihbr avatar lihbr commented on May 16, 2024 1

Awesome!

From my understanding, Nuxt 3 already provides a <NuxtLink /> component that is just a renamed <RouterLink />: https://github.com/nuxt/framework/blob/main/packages/nuxt3/src/pages/runtime/router.ts#L19

I don't have much knowledge about prefetching Nuxt payloads as I never had the opportunity to dive into Nuxt 2 <NuxtLink /> internals. However I do have some experience building "agnostic" link components, like the one pictured in my blog post, or more recently the one created for @prismicio/vue@next targeting Vue 3: https://github.com/prismicio/prismic-vue/blob/v3/src/components/PrismicLink.ts#L133-L266

The latter might be of some help/inspiration while creating Nuxt 3 <NuxtLink /> component. In that regard, I'm happy to help, or even provide a first draft PR or spec that implements the "agnostic" part of such component that I'm familiar with!

from framework.

danielroe avatar danielroe commented on May 16, 2024 1

@lihbr That would be great! That agnostic behaviour is exactly what we'd like to include in NuxtLink 👍

from framework.

pi0 avatar pi0 commented on May 16, 2024 1

I second this. Indeed the goal is to make NuxtLink an agnostic component that optionally supports Router navigations

from framework.

lihbr avatar lihbr commented on May 16, 2024

Here's a first naive/draft specs for it, take it mainly as a bundle of ideas regarding the new <NuxtLink> component. I guess we can work from here and add the prefetching part to it. (feel free to move it to a more convenient place also)

Labels are going as follows:

  • ⚪ Status: to be discussed
  • 🟠 Status: In discussion
  • 🔴 Status: rejected
  • 🟢 Status: approved

Overview

This document presents the specifications (specs) of a <NuxtLink> component for Nuxt 3. It reimplements most Nuxt 2 <NuxtLink> component features while also allowing the new component to also act as a drop-in replacement for HTML anchor (<a>) tag, effectively making the new <NuxtLink> component agnostic regarding the type of links (external or internal) it handles.

Background Information

Nuxt 2 provides a link component for internal links that extends Vue Router's <RouterLink> component. On top of that, it also handles smart prefetching of links as they become available in the viewport, assuming user's connection is fast enough for that feature (not offline nor 2g).

As of today, Nuxt 3 link component is just a reexport of Vue Router's <RouterLink> component, with no extends of any sort on top of it.

Specifications

The following describes how Nuxt 3 <NuxtLink> component could work.

Interfaces

Props

The <NuxtLink> component accepts the following props (interface):

type NuxtLinkProps = {
	// Routing
	to?: string;
	href?: string;

	// Attributes
	blank?: boolean;
	target?: string;
	rel?: string;

	// Prefetching
	prefetch?: boolean;
	noPrefetch?: boolean;

	// Styling
	activeClass?: string;
	exactActiveClass?: string;
	prefetchedClass?: string;

	// Vue Router's `<RouterLink>` additional props
	replace?: boolean;
	ariaCurrentValue?: string;

	// Edge cases handling
	external?: boolean;
	internal?: boolean;
};

Nuxt configuration

The following props can be configured globally inside Nuxt config router object. They will be used with a lower priority than direct props by <NuxtLink> components:

import { defineNuxtConfig } from "nuxt3";

export default defineNuxtConfig({
	router: {
		prefetchLinks: false, // defaults to `true`
		linkExternalRelAttribute: "noopener", // defaults to `"noopener noreferrer"`
		linkActiveClass: "foo", // defaults to `nuxt-link-active`
		linkExactActiveClass: "bar", // defaults to `nuxt-link-exact-active`
		linkPrefetchedClass: "baz", // defaults to `nuxt-link-prefetched`
	},
});

Props

Routing

to (string)

⚪ Status: to be discussed

The to prop accepts any kind of URLs.

  • If Vue Router is available (/pages is active) and the URL is detected as internal (whatever approach we find bullet-proof-enough for it, to be discussed), then the <RouterLink> component gets rendered;
  • If Vue Router is not available, or the URL is not detected as internal, an <a> tag is rendered with a rel attribute equal to noopener noreferer (value of router.linkExternalRelAttribute).
<NuxtLink to="/foo">...</NuxtLink>
<!-- Renders as: -->
<RouterLink to="/foo">...</RouterLink>

<NuxtLink to="https://example.com">...</NuxtLink>
<!-- Renders as: -->
<a href="https://example.com" rel="noopener noreferrer">...</a>

Errors & warnings

  • If the to prop is not provided, so is the href prop, an error is thrown by the component;
  • If the to prop is used in conjunction with the href prop, a warning is emitted and the to prop takes the priority over the href prop (however could go the other way around, depending on how we want to present the component).

href (string)

⚪ Status: to be discussed

The href prop is an alias to the to prop.

  • It behaves exactly the same way as the to prop;
  • It allows the <NuxtLink> component to be presented as a "drop-in replacement for the native <a> tag", in the same fashion as @nuxt/image <NuxtImg> and <NuxtPicture> components.
<NuxtLink href="/foo">...</NuxtLink>
<!-- Renders as: -->
<RouterLink to="/foo">...</RouterLink>

<NuxtLink href="https://example.com">...</NuxtLink>
<!-- Renders as: -->
<a href="https://example.com" rel="noopener noreferrer">...</a>

Errors & warnings

  • If the href prop is used in conjunction with the to prop, a warning is emitted and the to prop takes the priority over the href prop (however could go the other way around, depending on how we want to present the component);
  • If the href prop is not provided, so is the to prop, an error is thrown by the component.

Attributes

blank (boolean)

⚪ Status: to be discussed

The blank prop is a sugar for making any kind of link open in a new tab.

  • When blank is used, the link is treated as an external link and rendered with an <a> tag;
  • The target and rel attributes are set respectively to _blank and noopener noreferer (value of router.linkExternalRelAttribute).
<NuxtLink to="/foo" blank>...</NuxtLink>
<!-- Renders as: -->
<a href="/foo" target="_blank" rel="noopener noreferrer">...</a>

<NuxtLink to="https://example.com">...</NuxtLink>
<!-- Renders as: -->
<a href="https://example.com" target="_blank" rel="noopener noreferrer">...</a>

target (string)

⚪ Status: to be discussed

The target prop allows users to set the target attribute of the rendered link.

  • When target is used, an <a> tag is systematically rendered regardless if the link represents an internal link;
  • The target prop takes priority over the blank prop target attribute value when used together.
<NuxtLink to="/foo" target="_blank">...</NuxtLink>
<!-- Renders as: -->
<a href="/foo" target="_blank" rel="noopener noreferrer">...</a>

<NuxtLink to="https://example.com" target="_blank">...</NuxtLink>
<!-- Renders as: -->
<a href="https://example.com" target="_blank" rel="noopener noreferrer">...</a>

<NuxtLink to="https://example.com" blank target="bar">...</NuxtLink>
<!-- Renders as: -->
<a href="https://example.com" target="bar" rel="noopener noreferrer">...</a>

Setting target prop to _blank performs effectively the same action as using the blank prop alone.

rel (string)

⚪ Status: to be discussed

The rel prop allows users to set the rel attribute of the rendered link.

  • The rel prop takes priority over the rel that could have been computed by the component.
<NuxtLink to="/foo" rel="noopener">...</NuxtLink>
<!-- Renders as: -->
<a href="/foo" rel="noopener">...</a>

<NuxtLink to="https://example.com" rel="noopener">...</NuxtLink>
<!-- Renders as: -->
<a href="https://example.com" rel="noopener">...</a>

<NuxtLink to="https://example.com" blank rel="bar">...</NuxtLink>
<!-- Renders as: -->
<a href="https://example.com" target="_blank" rel="bar">...</a>

Prefetching

prefetch (boolean)

⚪ Status: to be discussed

The prefetch prop explicitely enables link prefetching.

  • When prefetch is used, it takes priority over the value set in Nuxt config router.prefetchLinks;
  • When prefetch is used with an external link, it is simply ignored.
<!-- Will prefetch -->
<NuxtLink to="/foo" prefetch>...</NuxtLink>

<!-- No effect -->
<NuxtLink to="https://example.com">...</NuxtLink>

Errors & warnings

  • If the prefetch prop is used in conjunction with the no-prefetch prop, a warning is emitted and the prefetch prop takes the priority over the no-prefetch prop (however could go the other way around, depending on how we want to present the component, or we could just throw an error).

no-prefetch (boolean)

⚪ Status: to be discussed

The no-prefetch prop explicitely disables link prefetching.

  • When no-prefetch is used, it takes priority over the value set in Nuxt config router.prefetchLinks;
  • When no-prefetch is used with an external link, it is simply ignored.
<!-- Will not prefetch -->
<NuxtLink to="/foo" no-prefetch>...</NuxtLink>

<!-- No effect -->
<NuxtLink to="https://example.com">...</NuxtLink>

Errors & warnings

  • If the no-prefetch prop is used in conjunction with the prefetch prop, a warning is emitted and the prefetch prop takes the priority over the no-prefetch prop (however could go the other way around, depending on how we want to present the component, or we could just throw an error).

Styling

active-class (string)

⚪ Status: to be discussed

The active-class prop is simply forwarded to the <RouterLink> component when one is rendered.

  • When no active-class prop is provided, the one from the Nuxt config is used;
  • When active-class is used with an external link, it is simply ignored.
<NuxtLink to="/foo" active-class="baz">...</NuxtLink>
<!-- Renders as on `/foo/bar`: -->
<RouterLink to="/foo" class="baz">...</RouterLink>

<NuxtLink to="https://example.com" active-class="baz">...</NuxtLink>
<!-- Renders as: -->
<a href="https://example.com" rel="noopener noreferrer">...</a>

See Vue Router's <RouterLink> props for more details.

exact-active-class (string)

⚪ Status: to be discussed

The exact-active-class prop is simply forwarded to the <RouterLink> component when one is rendered.

  • When no exact-active-class prop is provided, the one from the Nuxt config is used;
  • When exact-active-class is used with an external link, it is simply ignored.
<NuxtLink to="/foo/bar" exact-active-class="baz">...</NuxtLink>
<!-- Renders as on `/foo/bar`: -->
<RouterLink to="/foo" class="nuxt-link-active baz">...</RouterLink>

<NuxtLink to="https://example.com" exact-active-class="baz">...</NuxtLink>
<!-- Renders as: -->
<a href="https://example.com" rel="noopener noreferrer">...</a>

See Vue Router's <RouterLink> props for more details.

prefetched-class (string)

⚪ Status: to be discussed

The prefetched-class prop is appended to rendered classes once the internal link has been prefetched.

  • When no prefetched-class prop is provided, the one from the Nuxt config is used;
  • When prefetched-class is used with an external link, or when prefetching is disabled, it is simply ignored.
<NuxtLink to="/foo" prefetched-class="bar">...</NuxtLink>
<!-- Renders as, once prefetched: -->
<RouterLink to="/foo" class="bar">...</RouterLink>

<NuxtLink to="https://example.com" prefetched-class="bar">...</NuxtLink>
<!-- Renders as: -->
<a href="https://example.com" rel="noopener noreferrer">...</a>

Vue Router's <RouterLink> additional props

replace (boolean)

⚪ Status: to be discussed

The replace prop is simply forwarded to the <RouterLink> component when one is rendered.

  • When replace is used with an external link, it is simply ignored.

See Vue Router's <RouterLink> props for more details.

aria-current-value (string)

⚪ Status: to be discussed

The aria-current-value prop is simply forwarded to the <RouterLink> component when one is rendered.

  • When aria-current-value is used with an external link, it is simply ignored.

See Vue Router's <RouterLink> props for more details.

Edge cases handling

external (boolean)

⚪ Status: to be discussed

The external prop forces the link to be rendered as an external link.

<NuxtLink to="/foo" external>...</NuxtLink>
<!-- Renders as: -->
<a href="/foo" rel="noopener noreferrer">...</a>

<a to="https://example.com" external>...</a>
<!-- Renders as: -->
<a href="https://example.com" rel="noopener noreferrer">...</a>

Errors & warnings

  • If the external prop is used in conjunction with the internal prop, a warning is emitted and the external prop takes the priority over the internal prop (however could go the other way around, depending on how we want to present the component, or we could just throw an error).

internal prop (boolean)

⚪ Status: to be discussed

The internal prop forces the link to be rendered as an internal link.

<NuxtLink to="/foo" internal>...</NuxtLink>
<!-- Renders as: -->
<NuxtLink to="/foo">...</NuxtLink>

<a to="https://example.com" internal>...</a>
<!-- Renders as: -->
<NuxtLink to="https://example.com">...</NuxtLink>

Errors & warnings

  • If the internal prop is used in conjunction with the external prop, a warning is emitted and the external prop takes the priority over the internal prop (however could go the other way around, depending on how we want to present the component, or we could just throw an error).

from framework.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.