Components
Link
An always-underlined navigation link with default or subtle emphasis. Render an anchor directly, or use asChild to style a router adapter while preserving its link behavior.
Preview
import { Link } from "@/components/ui/link"
<Link href="#guide">Read the guide</Link>Usage
When to use
- Navigate to a page, resource or section from text.
- Place an underlined destination within a sentence.
When not to use
- An action that changes the current page without navigating. Use Button.
- A path through parent pages. Use Breadcrumb.
Variants
variant
default uses accent text; subtle uses secondary text.
import { Link } from "@/components/ui/link"
<Link href="#guide">Read the guide</Link>
<Link variant="subtle" href="#guide">Read the guide</Link>Examples
Inline navigation
import { Link } from "@/components/ui/link"
<p className="text-sm text-text-primary">
<span>Read the </span>
<Link href="#installation">installation guide</Link>
<span> before creating your first theme.</span>
</p>External destination
import { Link } from "@/components/ui/link"
<Link external href="https://example.com/guide" target="_blank" rel="help">Open the guide</Link>Composed link
A single child provides the destination. Use the same composition with an application router adapter.
import { Link } from "@/components/ui/link"
<Link asChild variant="subtle">
<a href="#project">View project</a>
</Link>Do and don't
Do
- Use meaningful destination text.
- Use asChild for router adapters with their own destination props.
- Make opening a new tab an explicit choice with target="_blank".
Don't
- Do not use Link for actions that do not navigate; use Button.
- Do not use external as a substitute for target.
- Do not nest anchors.
Props
| Name | Type | Values | Default | Description |
|---|---|---|---|---|
| variant | enum | default | subtle | default | default uses accent text; subtle uses secondary text. |
| external | boolean | - | false | Adds a decorative external-link icon. Does not change the target. |
| asChild | boolean | - | false | Styles a single child link or router adapter without a nested anchor. |
| href | string | - | - | Destination for the native anchor. A child router adapter may supply its own destination. |
| target | string | - | - | Native navigation target. _blank merges noopener and noreferrer into rel. |
| rel | string | - | - | Relationship values. Existing values are retained when safe values are added for _blank. |
Slots
| Name | Required | Description |
|---|---|---|
| children | yes | Visible destination name, or the single child link when asChild is true. |
Anatomy
| Part | Description |
|---|---|
| root | Anchor or caller-supplied link with an underline and visible keyboard focus. |
| icon | Decorative external-link icon, present only when external is true. |
Accessibility
Role: link
| Keys | Action |
|---|---|
| Tab | Focus the link. |
| Enter | Follow the focused link. |
- Both variants keep an underline so the link is distinguishable without color alone.
- The external icon is decorative and does not change the accessible name.
- external does not force a new tab. An explicit target="_blank" adds noopener noreferrer without dropping existing rel values.
- asChild preserves the child destination, native attributes, event handlers and ref.
Install
npx shadcn add https://werewolf-ui.vercel.app/r/link.jsonThis also adds styles/werewolf.css, the tokens every component uses, and any other component it needs. Import that file once in your root CSS, after @import "tailwindcss", with a path relative to that CSS file (from app/globals.css it is @import "../styles/werewolf.css").