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
npx shadcn@latest add @ritla/text-linkDependencies 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.
| Prop | Type | Default | Description |
|---|---|---|---|
children | ReactNode | Figma's Label. | |
href | string | Where 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. |
underline | boolean | true | Figma's Show underline. |
iconLeading | IconComponent | Figma's Icon leading and its swap. Directional icons mirror in RTL. | |
iconTrailing | IconComponent | Figma's Icon trailing and its swap. | |
external | boolean | false | A new tab, the external arrow and a screen reader note. |
disabled | boolean | false | Figma's State = Disabled: no href, out of the Tab order. |
render | ReactElement | A 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.
| Key | Action |
|---|---|
| Tab | Moves focus to the link, with the focus ring around it (the error ring on danger). |
| Enter | Follows 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 nohref, 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
numeralslike any other text. - Arabic typography
- Standalone links use the
labelstyles 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>.