Text Link
An anchor for a sentence or a line of UI copy. It takes its size and weight from the text around it and carries an underline that never leaves; a link navigates and a button acts.
If it acts, it is a button
A link navigates: to another page, another site, or a place on the same page. A button acts: it sends, saves, opens, or retries. TextLink always renders an anchor with an href, or your router's link through asChild. There is no href-less text link: an anchor that navigates nowhere is an action, and an action is a button. An action inside a sentence — "Didn't get the code? Resend" — is the primary button placed inline, and the registry ships no text-looking button variant.
Navigation items are not text links either. Breadcrumb's levels, sidebar's items, menu items, and pagination's page numbers read as links by their position, so they keep their own classes and draw no underline. Card and table stretched links stay as they are: the surface is the hit target, and an underline inside it would compete with the title.
Inside a paragraph
The link is display: inline, so it breaks across lines with the sentence it sits in and never forces a line of its own. Font size, weight, and line height are inherited — there is no size prop and no variant. The text is --foreground in every state; the underline sits at underline-offset-4 and is 1px --muted-foreground at rest, 1.5px --foreground on hover and press. It thickens downward from the offset, so the line box never moves. Tab to the link below and the focus ring closes around each line fragment separately, which is what box-decoration-clone is for.
Every itinerary starts from a template, and the one we reach for most is the three days in Kyoto walking route that begins at Fushimi Inari, which fits temples, tea, and a river walk into a weekend.
Every itinerary starts from a template, and the one we reach for most is the three days in Kyoto walking route that begins at Fushimi Inari, which fits temples, tea, and a river walk into a weekend.
Inside muted text
In an alert description, a field description, or any muted block, the link keeps --foreground while its surroundings stay --muted-foreground, so it reads one step stronger than the copy around it. That is why there is no muted variant and no currentColor inheritance: the contrast with the surrounding text is the point.
External links
There is no external prop. Whether a link opens a new tab is your app's policy, so you pass target and rel yourself, and you place the icon as a child. An svg child sits inline at text scale, so it grows and shrinks with the sentence instead of holding a fixed pixel size.
Japan's rail passes are explained on japan.travel, which lists every regional option.
Japan's rail passes are explained on japan.travel, which lists every regional option.
Router links
asChild hands the class names and the props to the element you pass, so your router renders the anchor and client-side navigation keeps working. This is the same slotting BreadcrumbLink and DropdownMenuItem use. The component is named TextLink rather than Link precisely because this case nests the two.
Everything on this page is built from the registry components.
Everything on this page is built from the registry components.
On another surface
The focus ring stands 2px off the text, and that gap paints --background. On a card, or any surface that is not the page, pass focus-visible:ring-offset-card through className so the gap matches what the link sits on — the same override alert's close button makes.
States, motion, and accessibility
Rest, hover, press, and focus are the whole set. There is no visited state — browsers restrict :visited to colour, and "visited" means nothing for a router link — and no disabled state, because an anchor that cannot navigate is plain text. The only thing that moves is the underline: its colour and its thickness together, at --motion-fast. Thickness carries the change where colour alone reads faint — a 1px dark stroke on a light ground loses to antialiasing in a way a light stroke on a dark ground does not. The underline never draws in, because it is never absent.
Tab reaches the link and Enter activates it, the native anchor behaviour. Text runs --foreground on --background, the body-text pair; the resting underline is --muted-foreground at 4.73:1 light and 7.63:1 dark, and the hover underline is --foreground at 1.5px. WCAG 1.4.1 does not apply here: the underline never leaves, so the link is never told apart by colour alone.