# Link Text

A polymorphic text link with tone, underline, size, and external-link controls.

## Installation

```bash
npx shadcn@latest add https://reactdocs.canceydejean.dev/r/link-text.json
```

[Registry JSON](https://reactdocs.canceydejean.dev/r/link-text.json)

## Preview

```tsx
import { LinkText } from "@/components/ui/link-text/link-text";
import { LINK_TONES } from "@/components/ui/link-text/link-text.variants";

export function Preview() {
  return (
    <div className="flex flex-col gap-3">
      {LINK_TONES.map((tone) => (
        <LinkText key={tone} href="#" tone={tone}>
          Tone: {tone}
        </LinkText>
      ))}
    </div>
  );
}
```


## Source

### link-text.tsx

```tsx
import type * as React from "react";

import { cn } from "cn";

import type { LinkProps } from "./link-text.types";
import { linkTextVariants } from "./link-text.variants";

export function LinkText<T extends React.ElementType = "a">({
  as,
  tone,
  underline,
  size,
  external,
  className,
  ...props
}: LinkProps<T>) {
  const Component = (as || "a") as React.ComponentType<Record<string, unknown>>;

  return (
    <Component
      data-slot="link-text"
      className={cn(linkTextVariants({ tone, underline, size }), className)}
      {...(external && {
        target: "_blank",
        rel: "noopener noreferrer",
      })}
      {...props}
    />
  );
}
```


### link-text.types.ts

```ts
import type { VariantProps } from "class-variance-authority";

import type { linkTextVariants } from "./link-text.variants";

type LinkTextVariants = VariantProps<typeof linkTextVariants>;

export type LinkProps<T extends React.ElementType> = {
  as?: T;
  external?: boolean;
  className?: string;
} & LinkTextVariants &
  Omit<React.ComponentPropsWithoutRef<T>, keyof LinkTextVariants>;
```


### link-text.variants.ts

```ts
import { cva } from "class-variance-authority";

import { cn } from "cn"

const linkTextBase = cn(
  "inline-flex items-center gap-1 leading-none! font-medium transition-colors focus-visible:ring-2 focus-visible:ring-blue-500 focus-visible:ring-offset-2 focus-visible:outline-none",
);

const linkTextConfig = {
  variants: {
    tone: {
      default: "text-primary hover:text-primary/80",
      muted: "text-muted-foreground hover:text-foreground",
      subtle: "text-neutral-500 hover:text-neutral-700",
      danger: "text-destructive hover:text-destructive/80",
    },
    underline: {
      none: "no-underline",
      hover: "no-underline hover:underline",
      always: "underline",
    },
    size: {
      sm: "[font-size:var(--text-14)]",
      md: "[font-size:var(--text-16)]",
      lg: "[font-size:var(--text-24)]",
    },
  },
  compoundVariants: [],
  defaultVariants: {
    tone: "default",
    underline: "hover",
    size: "md",
  },
} as const;

export const linkTextCva = cva(linkTextBase, {
  ...linkTextConfig,
  compoundVariants: [...linkTextConfig.compoundVariants],
});

// Export the size variants
export const LINK_SIZES = Object.keys(
  linkTextConfig.variants.size,
) as (keyof typeof linkTextConfig.variants.size)[];

//  Export the tone variants
export const LINK_TONES = Object.keys(
  linkTextConfig.variants.tone,
) as (keyof typeof linkTextConfig.variants.tone)[];

// Export the underline variants
export const LINK_UNDERLINES = Object.keys(
  linkTextConfig.variants.underline,
) as (keyof typeof linkTextConfig.variants.underline)[];

export const linkTextVariants = linkTextCva;
```



## Usage

Use Link Text for inline actions, navigation labels, and linked UI copy. It supports visual
variants and can render as any element through the `as` prop.

```tsx
import { LinkText } from "@/components/link-text/link-text";

export function Example() {
  return (
    <LinkText href="/docs" tone="default" underline="hover">
      Read the docs
    </LinkText>
  );
}
```

