Build · New

Links

Links that take people to another page, section or site, inside text or on their own. For actions that change data, use a Button.

Preview

Mirrored is the same English content laid out right to left: it separates a mirroring bug from a translation one.

Installation

SoonInstalling from the registry opens at launch. Until then the command below is what it will be.
npx shadcn@latest add @ritla/text-link

Dependencies it brings: @phosphor-icons/react

Usage

import { TextLink } from "@/components/ui/text-link";
<p>
  By continuing you agree to our <TextLink href="/terms" size="inline">Terms of service</TextLink>.
</p>
<TextLink href="/transactions" size="md">View all transactions</TextLink>

Examples

Styles

blue for most links, gray where links are quiet (footers, secondary navigation), danger for a link into a destructive flow, never for plain navigation.

Sizes

For standalone links: sm 20px, md 24px and lg 28px tall, with 16, 20 and 24px icons.

States

Hover and focus come from the pointer and keyboard. disabled drops the href, so the link leaves the Tab order but stays visible. Remove the underline only where the context already reads as links.

Inline

size="inline" wraps with the sentence and takes its size and weight, at any text style. Keep the underline in running text: color alone doesn't mark a link.

External

external opens a new tab with rel="noopener noreferrer", adds the external arrow and tells screen readers it opens in a new tab, in the page language.

With your router

Pass Next's <Link> (or your router's) as render: it keeps client-side navigation and prefetching, and TextLink adds the look.

API reference

TextLink

Also takes every <a> prop. Named TextLink so it doesn't clash with your router's Link.

PropTypeDefaultDescription
childrenReactNodeFigma's Label.
hrefstringWhere the link goes.
variant"blue" | "gray" | "danger""blue"Figma's Style.
size"sm" | "md" | "lg" | "inline""lg"Figma's Size, or inline inside running text.
underlinebooleantrueFigma's Show underline.
iconLeadingIconComponentFigma's Icon leading and its swap. Directional icons mirror in RTL.
iconTrailingIconComponentFigma's Icon trailing and its swap.
externalbooleanfalseA new tab, the external arrow and a screen reader note.
disabledbooleanfalseFigma's State = Disabled: no href, out of the Tab order.
renderReactElementA router link (<Link href>) rendered with the TextLink look.

Accessibility

Keyboard

Keys are written for left-to-right. In right-to-left the arrow keys swap: the one pointing toward the reading direction moves forward.

KeyAction
TabMoves focus to the link, with the focus ring around it (the error ring on danger).
EnterFollows the link.

ARIA

  • A real <a href>, so it's announced as a link and opening in a new tab or copying works.
  • An external link adds “(opens in a new tab)” for screen readers, in Arabic on Arabic pages.
  • A disabled link has aria-disabled="true" and no href, so Tab skips it.
  • Icons are decorative and hidden from screen readers; the text names the link.

Arabic and RTL notes

Mirrors

  • Directional icons mirror: the “View all transactions” arrow points left, and the external arrow up and to the left.
  • The leading icon sits at the inline start (the right), the trailing one at the end.

Does not mirror

  • Non-directional icons (home, help) stay as they are, as does the underline.
Numerals
Numbers in a link's text follow numerals like any other text.
Arabic typography
Standalone links use the label styles in Medium, with taller Arabic line heights; heights are minimums, so text never clips. The underline sits 4px below the baseline, clear of most Arabic dots.
Mixed-direction text
Inside a sentence the link follows the paragraph direction. Wrap a Latin brand name inside an Arabic link in <bdi>.

All components ›