---
layout: ~/layouts/MdxDocLayout.astro
title: "Link"
description: "A styled anchor component for inline text links with multiple variants and composition support."
sourceFile: "components/link"
---

import ComponentExample from "~/components/docs/ComponentExample.astro";
import ComponentSection from "~/components/docs/ComponentSection.astro";
import Heading from "~/components/docs/Heading.astro";
import {
  LinkBasicDemo,
  LinkInParagraphDemo,
  LinkExternalDemo,
  LinkCurrentVariantDemo,
  LinkRenderDemo,
} from "~/components/demos/LinkDemo";

{/* Hero Demo */}

<ComponentSection>
  <ComponentExample demo="LinkBasicDemo">
    <LinkBasicDemo client:visible />
  </ComponentExample>
</ComponentSection>

{/* Installation */}

<ComponentSection>
  <Heading level={2}>Installation</Heading>
  <Heading level={3}>Barrel</Heading>

```tsx
import { Link } from "@cloudflare/kumo";
```

<Heading level={3}>Granular</Heading>

```tsx
import { Link } from "@cloudflare/kumo/components/link";
```

</ComponentSection>

{/* Usage */}

<ComponentSection>
  <Heading level={2}>Usage</Heading>
  <Heading level={3}>Basic Link</Heading>
  <p>
    The default Link component renders an underlined anchor with primary color styling.
  </p>

```tsx
import { Link } from "@cloudflare/kumo";

export default function Example() {
  return (
    <p>
      Read our <Link href="/docs">documentation</Link> for more details.
    </p>
  );
}
```

<Heading level={3}>External Links</Heading>
<p>
  Use the `Link.ExternalIcon` subcomponent to indicate links that open in a new
  tab.
</p>

```tsx
import { Link } from "@cloudflare/kumo";

export default function Example() {
  return (
    <Link
      href="https://cloudflare.com"
      target="_blank"
      rel="noopener noreferrer"
    >
      Visit Cloudflare <Link.ExternalIcon />
    </Link>
  );
}
```

<Heading level={3}>Framework Integration (render prop)</Heading>
<p>
  Use the `render` prop to compose Link styles onto framework-specific routing
  components like React Router's Link or Next.js Link.
</p>

```tsx
import { Link } from "@cloudflare/kumo";
import { Link as RouterLink } from "react-router-dom";

export default function Example() {
  return (
    <Link render={<RouterLink to="/dashboard" />} variant="inline">
      Dashboard
    </Link>
  );
}
```

</ComponentSection>

{/* Examples */}

<ComponentSection>
  <Heading level={2}>Examples</Heading>

<Heading level={3}>Inline in Paragraph</Heading>
<p>Links flow naturally within paragraph text with proper underline offset.</p>
<ComponentExample demo="LinkInParagraphDemo">
  <LinkInParagraphDemo client:visible />
</ComponentExample>

<Heading level={3}>External Link with Icon</Heading>
<p>
  Use `Link.ExternalIcon` to visually indicate links that navigate away from
  your site.
</p>
<ComponentExample demo="LinkExternalDemo">
  <LinkExternalDemo client:visible />
</ComponentExample>

<Heading level={3}>Current Variant (Color Inheritance)</Heading>
<p>
  The `current` variant inherits color from its parent, useful for links within
  colored contexts like alerts.
</p>
<ComponentExample demo="LinkCurrentVariantDemo">
  <LinkCurrentVariantDemo client:visible />
</ComponentExample>

<Heading level={3}>Composition with render prop</Heading>
<p>
  The `render` prop lets you compose Link styling onto any element, enabling
  integration with framework routing components.
</p>
<ComponentExample demo="LinkRenderDemo">
  <LinkRenderDemo client:visible />
</ComponentExample>

</ComponentSection>

{/* API Reference */}

<ComponentSection>
  <Heading level={2}>API Reference</Heading>

<Heading level={3}>Link Props</Heading>
<p>Extends all native anchor element attributes.</p>
<div class="overflow-x-auto">
  <table class="w-full text-sm">
    <thead>
      <tr class="border-b border-kumo-hairline">
        <th class="px-4 py-3 text-left font-semibold">Prop</th>
        <th class="px-4 py-3 text-left font-semibold">Type</th>
        <th class="px-4 py-3 text-left font-semibold">Default</th>
        <th class="px-4 py-3 text-left font-semibold">Description</th>
      </tr>
    </thead>
    <tbody class="text-kumo-strong">
      <tr class="border-b border-kumo-hairline">
        <td class="px-4 py-3 font-mono text-xs">variant</td>
        <td class="px-4 py-3 font-mono text-xs">
          "inline" | "current" | "plain"
        </td>
        <td class="px-4 py-3 font-mono text-xs">"inline"</td>
        <td class="px-4 py-3 text-xs">Visual style variant</td>
      </tr>
      <tr class="border-b border-kumo-hairline">
        <td class="px-4 py-3 font-mono text-xs">render</td>
        <td class="px-4 py-3 font-mono text-xs">ReactElement</td>
        <td class="px-4 py-3 font-mono text-xs">-</td>
        <td class="px-4 py-3 text-xs">
          Element to render with Link props merged onto it
        </td>
      </tr>
      <tr class="border-b border-kumo-hairline">
        <td class="px-4 py-3 font-mono text-xs">href</td>
        <td class="px-4 py-3 font-mono text-xs">string</td>
        <td class="px-4 py-3 font-mono text-xs">-</td>
        <td class="px-4 py-3 text-xs">Link destination URL</td>
      </tr>
      <tr class="border-b border-kumo-hairline">
        <td class="px-4 py-3 font-mono text-xs">className</td>
        <td class="px-4 py-3 font-mono text-xs">string</td>
        <td class="px-4 py-3 font-mono text-xs">-</td>
        <td class="px-4 py-3 text-xs">Additional CSS classes</td>
      </tr>
      <tr class="border-b border-kumo-hairline">
        <td class="px-4 py-3 font-mono text-xs">children</td>
        <td class="px-4 py-3 font-mono text-xs">ReactNode</td>
        <td class="px-4 py-3 font-mono text-xs">-</td>
        <td class="px-4 py-3 text-xs">Link content</td>
      </tr>
    </tbody>
  </table>
</div>

<Heading level={3}>Variants</Heading>
<div class="overflow-x-auto">
  <table class="w-full text-sm">
    <thead>
      <tr class="border-b border-kumo-hairline">
        <th class="px-4 py-3 text-left font-semibold">Variant</th>
        <th class="px-4 py-3 text-left font-semibold">Description</th>
        <th class="px-4 py-3 text-left font-semibold">Use Case</th>
      </tr>
    </thead>
    <tbody class="text-kumo-strong">
      <tr class="border-b border-kumo-hairline">
        <td class="px-4 py-3 font-mono text-xs">inline</td>
        <td class="px-4 py-3 text-xs">Primary color with underline</td>
        <td class="px-4 py-3 text-xs">Default for inline text links</td>
      </tr>
      <tr class="border-b border-kumo-hairline">
        <td class="px-4 py-3 font-mono text-xs">current</td>
        <td class="px-4 py-3 text-xs">
          Inherits parent text color with underline
        </td>
        <td class="px-4 py-3 text-xs">
          Links within colored contexts (alerts, errors)
        </td>
      </tr>
      <tr class="border-b border-kumo-hairline">
        <td class="px-4 py-3 font-mono text-xs">plain</td>
        <td class="px-4 py-3 text-xs">Primary color without underline</td>
        <td class="px-4 py-3 text-xs">Navigation links, menus, footers</td>
      </tr>
    </tbody>
  </table>
</div>

<Heading level={3}>Link.ExternalIcon</Heading>
<p>
  SVG icon component to indicate external links. Accepts all SVG element
  attributes.
</p>

```tsx
<Link href="https://example.com" target="_blank" rel="noopener noreferrer">
  External Site <Link.ExternalIcon />
</Link>
```

</ComponentSection>

{/* Design Guidelines */}

<ComponentSection>
  <Heading level={2}>Design Guidelines</Heading>
  <div class="space-y-4 text-sm">
    <div>
      <h3 class="mb-2 font-semibold">When to Use Each Variant</h3>
      <ul class="ml-4 list-disc space-y-1 text-kumo-strong">
        <li>
          <strong>inline</strong>: Default choice for links within body text
        </li>
        <li>
          <strong>current</strong>: Links inside alerts, banners, or other
          colored containers
        </li>
        <li>
          <strong>plain</strong>: Navigation menus, footers, or where underlines
          are distracting
        </li>
      </ul>
    </div>
    <div>
      <h3 class="mb-2 font-semibold">External Link Indicators</h3>
      <ul class="ml-4 list-disc space-y-1 text-kumo-strong">
        <li>Always use `Link.ExternalIcon` for links that open in new tabs</li>
        <li>
          Set `target="_blank"` and `rel="noopener noreferrer"` for security
        </li>
        <li>
          The icon provides a visual cue that users will leave the current site
        </li>
      </ul>
    </div>
    <div>
      <h3 class="mb-2 font-semibold">Framework Integration</h3>
      <ul class="ml-4 list-disc space-y-1 text-kumo-strong">
        <li>
          Use the `render` prop with React Router, Next.js, or other framework
          links
        </li>
        <li>Pass your framework's Link component as the render prop value</li>
        <li>
          This preserves client-side navigation while applying Kumo styling
        </li>
        <li>
          Alternatively, configure a global LinkProvider for automatic
          integration
        </li>
      </ul>
    </div>
    <div>
      <h3 class="mb-2 font-semibold">Accessibility</h3>
      <ul class="ml-4 list-disc space-y-1 text-kumo-strong">
        <li>Links are keyboard focusable by default</li>
        <li>
          The external icon has `aria-hidden="true"` - add descriptive text for
          screen readers
        </li>
        <li>Ensure sufficient color contrast for all variants</li>
        <li>Use descriptive link text (avoid "click here")</li>
      </ul>
    </div>
  </div>
</ComponentSection>
