Components
Back to catalog
Component detail entry
General
@vean/ui
SLink

Link

Link belongs to the General category. Start with demos and usage, then use the API tables to finish integration and styling decisions.

Use the quick jump panel to reach overview, usage, demos, and API first, then continue through the full page.

Quick jump

Related components

If you are composing interactions in the same family, these components usually pair well together.

Link

Overview

SLink is a polymorphic link component that supports internal routing (via RouterLink) and external links (via <a> tag). It automatically detects external links and sets safe target and rel attributes, supports disabled state and polymorphic rendering (as/asChild).

Features

  • 🔗 Smart Routing: Automatically distinguishes internal routes (to) from external links (href), gracefully falls back to <a> when RouterLink is unavailable.
  • 🧩 Pluggable Link Component: Inject a framework-specific component (e.g. Nuxt NuxtLink) via SConfigProvider linkComponent.
  • 🛡️ Safe Defaults: External links automatically get target="_blank" and rel="noopener noreferrer" to prevent reverse tabnabbing.
  • 🔧 Polymorphic: Render as any element or component via as/asChild.
  • ♿ Accessible Disabled: Disabled state sets aria-disabled, role="link", tabindex="-1", and blocks click events.
  • 🎨 Styling: Override styles via class prop; linkVariants provides base utility classes.

Usage

Demos

Basic

Accessibility

  • Disabled state: Sets aria-disabled="true", role="link", tabindex="-1", and calls preventDefault() to block click navigation. Visually, the data-disabled attribute triggers cursor-not-allowed and opacity-50.
  • External link safety: Automatically adds rel="noopener noreferrer" to prevent newly opened pages from accessing window.opener.

API

Aria Layer

3

Link

21 Props
Props
PropTypeDefaultDescription
class
ClassValue
—
Additional class names applied to the root element.
to
string | import("vue-router").RouteLocationAsRelativeGeneric | import("vue-router").RouteLocationAsPathGeneric
—
Route Location the link should navigate to when clicked on.
replace
boolean
—
Calls `router.replace` instead of `router.push`.
href
string
—
The URL the link should navigate to when clicked on.
disabled
boolean
—
When `true`, the link is disabled.
activeClass
string
—
Class to apply when the link is active
exactActiveClass
string
—
Class to apply when the link is exact active
inactiveClass
string
—
The class to apply to the link when it is inactive.
prefetchedClass
string
—
A class to apply to links that have been prefetched.
external
boolean
—
Forces the link to be considered as external (true) or internal (false). This is helpful to handle edge-cases
ariaCurrentValue
'true' | 'false' | 'page' | 'date' | 'time' | 'step' | 'location'
`'page'`
Value passed to the attribute `aria-current` when the link is exact active.
viewTransition
boolean
—
Pass the returned promise of `router.push()` to `document.startViewTransition()` if supported.
target
(string & {}) | '_blank' | '_parent' | '_self' | '_top' | null
—
Where to display the linked URL, as the name for a browsing context.
rel
(string & {}) | 'noopener' | 'noreferrer' | 'nofollow' | 'sponsored' | 'ugc' | null
'noopener noreferrer'
A rel attribute value to apply on the link. Defaults to "noopener noreferrer" for external links.
noRel
boolean
—
If set to true, no rel attribute will be added to the link
prefetch
boolean
—
When enabled will prefetch middleware, layouts and payloads of links in the viewport.
prefetchOn
'visibility' | 'interaction' | Partial<{ visibility: boolean; interaction: boolean; }>
—
Allows controlling when to prefetch links. By default, prefetch is triggered only on visibility.
noPrefetch
boolean
—
Escape hatch to disable `prefetch` attribute.
trailingSlash
'append' | 'remove'
—
An option to either add or remove trailing slashes in the `href` for this specific link. Overrides the global `trailingSlash` option if provided.
asChild
boolean
—
Change the default rendered element for the one passed as a child, merging their props and behavior.
as
AsTag | Component
'div'
The element or component this component should render as. Can be overwrite by `asChild`

LinkBase

4 Props
Props
PropTypeDefaultDescription
href
string
—
The URL the link should navigate to when clicked on.
to
string | import("vue-router").RouteLocationAsRelativeGeneric | import("vue-router").RouteLocationAsPathGeneric
—
Route Location the link should navigate to when clicked on.
external
boolean
—
Forces the link to be considered as external (true) or internal (false). This is helpful to handle edge-cases
target
(string & {}) | '_blank' | '_parent' | '_self' | '_top' | null
—
Where to display the linked URL, as the name for a browsing context.

LinkExtra

16 Props
Props
PropTypeDefaultDescription
replace
boolean
—
Calls `router.replace` instead of `router.push`.
disabled
boolean
—
When `true`, the link is disabled.
asChild
boolean
—
Change the default rendered element for the one passed as a child, merging their props and behavior.
as
AsTag | Component
'div'
The element or component this component should render as. Can be overwrite by `asChild`
activeClass
string
—
Class to apply when the link is active
exactActiveClass
string
—
Class to apply when the link is exact active
inactiveClass
string
—
The class to apply to the link when it is inactive.
prefetchedClass
string
—
A class to apply to links that have been prefetched.
ariaCurrentValue
'true' | 'false' | 'page' | 'date' | 'time' | 'step' | 'location'
`'page'`
Value passed to the attribute `aria-current` when the link is exact active.
viewTransition
boolean
—
Pass the returned promise of `router.push()` to `document.startViewTransition()` if supported.
rel
(string & {}) | 'noopener' | 'noreferrer' | 'nofollow' | 'sponsored' | 'ugc' | null
'noopener noreferrer'
A rel attribute value to apply on the link. Defaults to "noopener noreferrer" for external links.
noRel
boolean
—
If set to true, no rel attribute will be added to the link
prefetch
boolean
—
When enabled will prefetch middleware, layouts and payloads of links in the viewport.
prefetchOn
'visibility' | 'interaction' | Partial<{ visibility: boolean; interaction: boolean; }>
—
Allows controlling when to prefetch links. By default, prefetch is triggered only on visibility.
noPrefetch
boolean
—
Escape hatch to disable `prefetch` attribute.
trailingSlash
'append' | 'remove'
—
An option to either add or remove trailing slashes in the `href` for this specific link. Overrides the global `trailingSlash` option if provided.

Notes

Architecture and benchmark differences

VeanUI splits the link into an Aria layer (route detection, disabled handling, RouterLink integration) and a styled layer (linkVariants styling). This differs from single-package solutions like Nuxt Link, React Router Link, and Next.js Link.

AspectVeanUINuxt Link / React Router Link / Next.js Link
ArchitectureAria + styled splitsingle package
Route detectionauto-detect http prefix, external prop, RouterLink availabilityexplicit <NuxtLink> / <Link>
External linksauto target="_blank" + rel="noopener noreferrer"manual setup required
Disabled statearia-disabled + tabindex="-1" + preventDefaultmanual handling required
Polymorphismas/asChild via Primitiveas / passHref
StylingUnoCSS utility classes + linkVariantsCSS Modules / styled / none

FAQ

When to use to vs href? Use to for internal route navigation (requires RouterLink) and href for external links. When to is a string starting with http, the component automatically treats it as an external link and renders an <a> tag.

Can I use it without vue-router installed? Yes. The component uses resolveComponent('RouterLink') to check if RouterLink is available. When unavailable, it automatically falls back to rendering an <a> tag.

Can I plug in a framework-specific link component (Nuxt NuxtLink, a locale-prefixing Link)? Yes. Set linkComponent on SConfigProvider (same injection mechanism as iconRender); Link then renders internal links with that component instead of the global RouterLink. Framework-specific props that LinkProps does not declare (e.g. locale) fall through as attrs to the injected component, and you can type them via module augmentation of LinkProps. External links still render a native <a>.

How do I disable a link? Set disabled: true. The component sets aria-disabled="true", tabindex="-1", role="link", and calls preventDefault() to block click navigation. The data-disabled attribute is added to trigger cursor-not-allowed and opacity-50 visually.

What’s the difference between as and asChild?as specifies the root element tag (e.g., as="button" renders a <button>). asChild makes the component not render its own root element, instead forwarding attributes and events to its child (similar to Radix UI’s asChild pattern).

What are the default values for target and rel? External links default to target="_blank", rel="noopener noreferrer"; internal routes default to target="_self". Both can be overridden via props.

Changelog

Version history is grouped by release so you can quickly see what changed for this component across published versions.

v0.40.0

2026-09-14

Compare release

Feature

add linkComponent injection via ConfigProvider

Scope: linkAuthors: soybeanfeView commit3fd7f

Feature

add linkComponent injection via ConfigProvider

Scope: linkAuthors: soybeanfeView commit3fd7f

v0.28.0

2026-05-28

Compare release

Refactor

simplify link component logic and remove unused Nuxt integration

Scope: linkAuthors: soybeanfeView commit68630

v0.27.2

2026-05-28

Compare release

Fix

refactor LinkComponent to use shallowRef and improve NuxtLink handling

Scope: linkAuthors: soybeanfeView commit90090

v0.25.1

2026-05-23

Compare release

Fix

get config provider can be null

Scope: linkAuthors: soybeanjsView commit866e4

v0.2.3

2026-01-28

Compare release

Fix

update href prop description and type

Scope: linkAuthors: soybeanjsView commit3d935

v0.1.5

2026-01-27

Compare release

Optimization

remove unused custom prop and simplify href handling

Scope: linkAuthors: soybeanjsView commit98386

v0.1.0

2026-01-22

Compare release

Feature

enhance slot binding for Link component and update styles

Scope: linkAuthors: soybeanjsView commitd41b3

v0.0.20

2026-01-21

Compare release

Feature

enhance slot functionality and improve forwarded props handling

Scope: linkAuthors: soybeanjsView commit384df

v0.0.9

2026-01-02

Compare release

Feature

extend LinkProps to include LinkBaseProps and LinkExtraProps, and set default rel attribute

Scope: linkAuthors: soybeanjsView commit7b3f1

v0.0.6

2025-12-09

Compare release

Feature

enhance slot functionality in link components to pass isHref prop for better context handling

Scope: linkAuthors: soybeanjsView commitd5c7a

Feature

enhance slot functionality in link components to pass isHref prop for better context handling

Scope: linkAuthors: soybeanjsView commitd5c7a

v0.0.2

2025-11-18

Compare release

Feature

introduce Link component for enhanced navigation and update app examples to utilize it

Scope: linkAuthors: soybeanjsView commit3f7f3

Feature

add Link component and examples for improved navigation in the playground

Scope: linkAuthors: soybeanjsView commitb3a24

Feature

enhance Link component with disabled state handling

Scope: linkAuthors: soybeanjsView commit42d18

Feature

rename Link component file and implement new link.vue with props and computed class handling

Scope: linkAuthors: soybeanjsView commit2eebf

Feature

add target prop and refactor isExternal to isHref for improved link handling

Scope: linkAuthors: soybeanjsView commitbd126

Fix

update href handling to conditionally set based on Nuxt context for improved link behavior

Scope: linkAuthors: soybeanjsView commit6c99e

Fix

remove unnecessary width utility from linkVariants base styles for cleaner implementation

Scope: linkAuthors: soybeanjsView commitcd211

Fix

update target behavior to default to '_blank' for external links

Scope: linkAuthors: soybeanjsView commit374d7

Refactor

consolidate Nuxt and Router link components into a single Link component with dynamic resolution

Scope: linkAuthors: soybeanjsView commit5812f

Refactor

simplify forwarded props handling and update types for improved clarity and functionality

Scope: linkAuthors: soybeanjsView commitb856a

Refactor

rename Link component to SLink for consistency with naming conventions

Scope: linkAuthors: soybeanjsView commit20057

Refactor

change LinkProps to use HTMLAttributes directly and update ButtonLinkProps to use type alias for clarity

Scope: linkAuthors: soybeanjsView commit82304

Fix

update target behavior to default to '_blank' for external links

Scope: linkAuthors: soybeanjsView commit374d7

Feature

introduce Link component for enhanced navigation and update app examples to utilize it

Scope: linkAuthors: soybeanjsView commit3f7f3

Feature

add Link component and examples for improved navigation in the playground

Scope: linkAuthors: soybeanjsView commitb3a24

Feature

enhance Link component with disabled state handling

Scope: linkAuthors: soybeanjsView commit42d18

Feature

rename Link component file and implement new link.vue with props and computed class handling

Scope: linkAuthors: soybeanjsView commit2eebf

Feature

add target prop and refactor isExternal to isHref for improved link handling

Scope: linkAuthors: soybeanjsView commitbd126

Fix

update href handling to conditionally set based on Nuxt context for improved link behavior

Scope: linkAuthors: soybeanjsView commit6c99e

Fix

remove unnecessary width utility from linkVariants base styles for cleaner implementation

Scope: linkAuthors: soybeanjsView commitcd211

Refactor

consolidate Nuxt and Router link components into a single Link component with dynamic resolution

Scope: linkAuthors: soybeanjsView commit5812f

Refactor

simplify forwarded props handling and update types for improved clarity and functionality

Scope: linkAuthors: soybeanjsView commitb856a

Refactor

rename Link component to SLink for consistency with naming conventions

Scope: linkAuthors: soybeanjsView commit20057

Refactor

change LinkProps to use HTMLAttributes directly and update ButtonLinkProps to use type alias for clarity

Scope: linkAuthors: soybeanjsView commit82304