Link
A text hyperlink: the anchor primitive, in three emphasis variants with an automatic external-link affordance.
Live demo
Link is the styled <a> primitive: inline text that navigates, drawn in the link color with an offset underline and a token-colored focus ring. Three variants tune emphasis: default is the full-strength link, muted recedes into body text (underline only on hover) for in-prose and secondary nav, and quiet is the lowest-key treatment for dense footers and utility nav.
When target="_blank", Link automatically appends an external-link glyph, adds a screen-reader-only "(opens in a new tab)" hint, and sets rel="noopener noreferrer", handling security and accessibility without ceremony. Given no href, it degrades to inert text rather than rendering a broken anchor.
When to use
How this component composes with the rest of the set.
Props
5 props, straight from the manifest.
| Prop | Type | Default | Bindings | Description |
|---|---|---|---|---|
Appearance
Variants
default
The full-strength link: link color with a persistent offset underline.
muted
Recedes into body text: body-secondary color, underline only on hover, brightening to the link color.
quiet
The lowest-key treatment for dense or utility nav: body-tertiary color, no underline until hover.
Sizes
md
Links inherit their surrounding text size.
States
hover
Pointer over the link: color shifts toward the link/hover color and the underline appears or strengthens.
focus-visible
Keyboard focus: a token-colored ring, plus a transparent outline that becomes real in forced-colors mode.
external
An external link (target="_blank"): appends the icon and the SR-only new-tab hint, and sets rel.
Anatomy
The named parts that make up the component, with their selectors.
link
The anchor element (or inert span when hrefless) carrying the variant class and link styling.
external-icon
The inline SVG glyph appended after the label when the link opens in a new tab.
sr-hint
The visually-hidden "(opens in a new tab)" text announced to screen readers for external links.
Tokens & coverage
What the component consumes, checked live against what the algorithm produces.
Live coverage check against the xoji-default register
(derive(xojiDefault, { anchors }) →
coverComponent(manifest, register)). Every token this component
consumes must be a key the algorithm produces.
--border-normal
--border-thin
--duration-fast
--ease-standard
--fg-2
--fg-3
--font-sans
--link
--link-hover
--radius-sm
--ring
--space-1
Slots
The link text.
Accessibility
Code
Variants and external links
Three emphasis variants, plus the automatic external-link affordance on target="_blank".
<xoji-link href="/docs">Read the docs</xoji-link>
<xoji-link href="https://example.com" target="_blank">External site</xoji-link>
<nav>
<xoji-link variant="muted" href="/about">About</xoji-link>
<xoji-link variant="quiet" href="/legal">Legal</xoji-link>
</nav>
<script lang="ts">
import { Link } from "@xoji/svelte";
</script>
<Link href="/docs">Read the docs</Link>
<Link href="https://example.com" target="_blank">External site</Link>
<nav>
<Link variant="muted" href="/about">About</Link>
<Link variant="quiet" href="/legal">Legal</Link>
</nav>
---
import { Link } from "@xoji/astro";
---
<Link href="/docs">Read the docs</Link>
<Link href="https://example.com" target="_blank">External site</Link>
<nav>
<Link variant="muted" href="/about">About</Link>
<Link variant="quiet" href="/legal">Legal</Link>
</nav>