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

export function LinkBasicDemo() {
  return (
    <div className="grid gap-x-6 gap-y-4 text-base md:grid-cols-3">
      <Link href="#">Default inline link</Link>
      <Link href="#" variant="current">
        Current color link
      </Link>
      <Link href="#" variant="plain">
        Plain inline link
      </Link>
    </div>
  );
}

安装

批量导入

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

细粒度导入

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

用法

默认的 Link 组件渲染一个带下划线、使用主题色的锚点。

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

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

用 Link.ExternalIcon 子组件标识会在新标签页中打开的链接。

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>
  );
}

框架集成(LinkProvider)

如果要在整个应用中接入路由,请在应用根部配置 LinkProvider。 你的包装组件会接收 href,并负责对接你所用路由的 API。 这样工程师可以在任何地方使用 <Link href="...">, 而不必关心路由的内部细节。

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

// 你的应用包装组件把 href 映射到路由的导航属性,
// 外部 URL 则用普通 <a> 处理
const AppLink = forwardRef(({ href, to, ...rest }, ref) => {
  const destination = href ?? to;
  const isExternal =
    destination?.startsWith("http") &&
    new URL(destination).origin !== window.location.origin;

  if (isExternal) {
    return <a ref={ref} href={destination} {...rest} />;
  }
  return <RouterLink ref={ref} to={destination} {...rest} />;
});

// 在应用根部包裹一次
export function App() {
  return (
    <LinkProvider component={AppLink}>
      {/* 所有 <Link href="..."> 调用都会经过 AppLink */}
      <YourApp />
    </LinkProvider>
  );
}

用 render 属性组合

对于需要直接控制渲染元素的特殊情况,可以使用 render 属性。 它会完全绕过 LinkProvider——其他所有属性(href、target、 className 等)都会自动合并到所提供的元素上。

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

export default function Example() {
  return (
    <>
      {/* 强制使用特定的路由链接(绕过 LinkProvider) */}
      <Link render={<RouterLink to="/dashboard" />} variant="inline">
        Dashboard
      </Link>

      {/* 强制使用普通锚点(绕过 LinkProvider) */}
      <Link render={<a />} href="https://example.com" target="_blank" rel="noopener noreferrer">
        External Site <Link.ExternalIcon />
      </Link>
    </>
  );
}

示例

段落内行内链接

链接在段落文本中自然排布,带有合适的下划线偏移。

This is a paragraph with an inline link that flows naturally with the surrounding text. Links maintain proper underline offset for readability.

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

export function LinkInParagraphDemo() {
  return (
    <p className="mx-auto max-w-md text-base leading-relaxed text-kumo-default">
      This is a paragraph with an <Link href="#">inline link</Link> that flows
      naturally with the surrounding text. Links maintain proper underline
      offset for readability.
    </p>
  );
}

用 Link.ExternalIcon 在视觉上标识会离开当前站点的链接。

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

export function LinkExternalDemo() {
  return (
    <Link
      href="https://cloudflare.com"
      target="_blank"
      rel="noopener noreferrer"
      className="text-base"
    >
      Visit Cloudflare <Link.ExternalIcon />
    </Link>
  );
}

current 变体(颜色继承)

current 变体从父元素继承颜色,适用于警报等带颜色场景中的链接。

This error message contains a link that inherits the red color from its parent.

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

export function LinkCurrentVariantDemo() {
  return (
    <p className="text-base text-kumo-danger">
      This error message contains a{" "}
      <Link href="#" variant="current">
        link
      </Link>{" "}
      that inherits the red color from its parent.
    </p>
  );
}

用 render 属性组合

render 属性让你可以把 Link 的样式组合到任意元素上, 从而与框架的路由组件集成。

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

export function LinkRenderDemo() {
  return (
    <div className="flex flex-col gap-x-6 gap-y-4 text-base md:flex-row">
      <Link render={<CustomRouterLink href="/dashboard" />} variant="inline">
        Dashboard (via render)
      </Link>
      <Link
        render={
          <CustomRouterLink
            href="https://developers.cloudflare.com"
            target="_blank"
            rel="noopener noreferrer"
          />
        }
        variant="inline"
      >
        Cloudflare Docs <Link.ExternalIcon />
      </Link>
    </div>
  );
}

API 参考

继承原生锚点元素的全部属性。

属性类型默认值说明
variant

“inline” | “current” | “plain"

"inline”视觉样式变体
renderReactElement-

要渲染的元素,Link 的属性会合并到它上面

hrefstring-

链接目标 URL。所有链接都用它——无论内部还是外部。 配置 LinkProvider 可把 href 桥接到你的路由。

tostring-

已弃用。 请改用 href。该属性将在未来的 主要版本中移除。

classNamestring-额外的 CSS 类名
childrenReactNode-链接内容

变体

变体说明适用场景
inline主题色加下划线行内文本链接的默认选择
current

继承父级文字颜色并带下划线

带颜色场景(警报、错误提示)中的链接

plain主题色、无下划线导航链接、菜单、页脚

Link.ExternalIcon

用于标识外部链接的 SVG 图标组件。接受所有 SVG 元素属性。

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

设计指南

各变体的使用时机

  • inline:正文文本中链接的默认选择

  • current:警报、横幅或其他带颜色容器 内部的链接

  • plain:导航菜单、页脚,或下划线会 干扰阅读的地方

  • 在新标签页中打开的链接,始终使用 Link.ExternalIcon
  • 设置 target="_blank" 和 rel="noopener noreferrer" 以保证安全

  • 该图标给用户一个视觉提示:将要离开当前站点

框架集成

  • 在应用根部配置 LinkProvider,与你的客户端路由集成

  • 你的包装组件接收 href,并把它映射到路由的导航属性 (例如 React Router 的 to)

  • 包装组件对外部 URL 应渲染普通 &lt;a&gt;,而不是走路由

  • 对需要直接控制渲染元素的特殊情况,用 render 属性作为 逃生通道

  • to 属性已弃用——所有链接目标都请使用 href

无障碍

  • 链接默认可通过键盘聚焦
  • 外部图标带有 aria-hidden="true"——请为屏幕阅读器 添加描述性文本

  • 确保所有变体都有足够的颜色对比度
  • 使用有意义的链接文字(避免「点击这里」)