Skip to content

Link

The Link component renders a normalized LinkItem as a semantic <a> element. It supports variant-based styling via class-variance-authority, automatic _blank security enforcement, disabled state handling, download links, and invalid destination fallback rendering.

import { Link } from "@/rokkit200-ui/components/link/link";
<Link href="#">
Lorem Ipsum
</Link>

High-emphasis navigation action — the default variant.

Lower-emphasis navigation that maintains visual distinction.

Minimal visual weight, suited to dense layouts.

Non-interactive: href is removed, aria-disabled="true" is set, tabIndex is -1, and click events are suppressed.

Icon-only links use kind="icon" for a circular shape. An aria-label is required for accessibility.

Emits the download attribute with an optional filename for direct file download behavior.

When target="_blank" is set, rel="noopener noreferrer" is automatically enforced to prevent reverse tabnapping.

When no href is provided (representing an unresolvable destination), the component renders a non-interactive <span> preserving authored content and order.

Unresolved Link
PropTypeDefaultDescription
hrefstringundefinedDestination URL. When omitted, the component renders a non-interactive <span> fallback.
childrenReact.ReactNodeLink content — typically label text and/or icons.
variant"primary" | "secondary" | "outline""primary"Visual style variant. Shares token system with Button.
kind"default" | "icon""default"Shape/content mode. Use "icon" for icon-only links (renders rounded-full).
disabledbooleanfalsePrevents navigation and interaction. Renders aria-disabled="true" and suppresses click events.
target"_self" | "_blank" | "_parent" | "_top"undefinedWhere to open the linked document. "_blank" auto-enforces safe rel tokens.
relstringundefinedRelationship attribute. Auto-supplemented with noopener noreferrer when target="_blank".
aria-labelstringundefinedAccessible name override. Required for icon-only links where visible text is absent.
titlestringundefinedHTML title attribute (tooltip). Not an accessibility substitute.
downloadboolean | stringundefinedEmits the download attribute. Pass a string for a custom filename.
classNamestringundefinedAdditional CSS classes applied to the root element.

When target="_blank" is set, the component automatically ensures rel contains both noopener and noreferrer. Explicit rel tokens from the consumer are preserved and merged.

  • href is removed from the rendered element
  • aria-disabled="true" is set
  • tabIndex is -1
  • Click events are fully suppressed (preventDefault + stopPropagation)
  • Visual styling reflects reduced interactivity via the aria-disabled:opacity-25 utility

The HTML disabled attribute is not valid on <a> elements. This component uses aria-disabled and behavioral suppression instead.

When href is not provided, the component renders a <span> instead of <a>:

  • Non-interactive: no href, not focusable, not clickable
  • Authored label text remains visible
  • No role="link" is applied (it is not a link)
  • Element position is preserved in authored order
  • Always renders a semantic <a> element for valid destinations
  • aria-label overrides the announced accessible name when provided
  • Icon-only links (kind="icon") without aria-label emit a dev warning
  • Disabled links are non-interactive and removed from tab order
  • Invalid fallback <span> is non-interactive with no link role
  • Focus styles meet WCAG 2.1 AA requirements

The component renders standard HTML <a> elements with no router-specific behavior. For client-side navigation (Next.js <Link>, React Router), compose by wrapping this component — do not modify the core.

  • Button — shared variant system and visual language
  • Icon — used within icon-only link variants