🎁 100 free AI Toolkit licenses – apply by August 15.Learn more

添加链接弹出框 UI 组件

Available for free

用于创建和编辑链接的弹出框。

安装

您可以通过 Tiptap CLI(适用于 Vite 或 Next.js)添加组件:

npx @tiptap/cli@latest add link-popover

手动集成

对于 Vite 或 Next.js 以外的框架,请从 开源仓库 手动添加组件。

导入样式

此组件需要您导入我们的样式,这些样式已添加到 styles/keyframe-animation.scssstyles/_variables.scss 中。

使用

<LinkPopover />

一个为 Tiptap 编辑器提供完整链接编辑界面的预制 React 组件,带有弹出框。用户友好的弹出界面支持键盘快捷键和灵活的自定义选项,可轻松添加、编辑和删除链接。

使用范例

import { EditorContent, EditorContext, useEditor } from '@tiptap/react'
import { StarterKit } from '@tiptap/starter-kit'
import { LinkPopover } from '@/components/tiptap-ui/link-popover'

import '@/components/tiptap-node/paragraph-node/paragraph-node.scss'

export default function MyEditor() {
  const editor = useEditor({
    immediatelyRender: false,
    extensions: [
      StarterKit.configure({
        link: { openOnClick: false, enableClickSelection: true },
      }),
    ],
    content: `
        <p>点击按钮打开链接弹出框。</p>
        <p><a href="https://www.tiptap.dev">Tiptap</a></p>
        `,
  })

  return (
    <EditorContext.Provider value={{ editor }}>
      <LinkPopover
        editor={editor}
        hideWhenUnavailable={true}
        autoOpenOnLinkActive={true}
        onSetLink={() => console.log('Link set!')}
        onOpenChange={(isOpen) => console.log('Popover opened:', isOpen)}
      />

      <EditorContent editor={editor} role="presentation" />
    </EditorContext.Provider>
  )
}

参数说明

名称类型默认值描述
editorEditor | nullnullTiptap 编辑器实例
hideWhenUnavailablebooleanfalse链接功能不可用时是否隐藏按钮
onSetLink() => void-成功设置链接后的回调
onOpenChange(isOpen: boolean) => void-弹出框打开状态改变时的回调
autoOpenOnLinkActivebooleantrue链接激活时是否自动打开弹出框

<LinkButton />

一个独立的链接按钮组件,用以触发链接相关功能。

使用范例

<LinkButton onClick={handleClick} aria-label="添加链接">
  自定义链接内容
</LinkButton>

<LinkContent />

一个独立组件,渲染链接编辑界面,但不包含弹出框包装。

使用范例

<LinkContent editor={editor} />

钩子

useLinkPopover()

自定义钩子,可构建自定义链接界面,全面控制渲染及行为。

使用范例

function MyLinkButton() {
  const { isVisible, canSet, isActive, url, setUrl, setLink, removeLink, label, Icon } =
    useLinkPopover({
      editor: myEditor,
      hideWhenUnavailable: true,
      onSetLink: () => console.log('Link set!'),
    })

  if (!isVisible) return null

  return (
    <div>
      <button onClick={setLink} disabled={!canSet} aria-label={label} aria-pressed={isActive}>
        <Icon />
        {label}
      </button>
      <input
        type="url"
        value={url}
        onChange={(e) => setUrl(e.target.value)}
        placeholder="请输入 URL..."
      />
      <button onClick={removeLink}>移除</button>
    </div>
  )
}

参数说明

名称类型默认值描述
editorEditor | null-Tiptap 编辑器实例
hideWhenUnavailablebooleanfalse链接不能应用时是否隐藏功能
onSetLink() => void-设置链接后的回调

返回值说明

名称类型描述
isVisibleboolean是否应渲染链接功能
canSetboolean当前上下文中是否可以设置链接
isActiveboolean链接当前是否处于激活或选中状态
urlstring链接的当前 URL 值
setUrlReact.Dispatch<React.SetStateAction<string | null>>更新 URL 状态的函数
setLink() => void在编辑器中应用链接的函数
removeLink() => void从编辑器中移除链接的函数
labelstring按钮的无障碍标签文本
IconReact.FC链接按钮的图标组件

useLinkHandler()

专注于处理链接操作的钩子,不包含 UI 状态管理。

使用范例

function MyCustomLinkInterface() {
  const { url, setUrl, setLink, removeLink } = useLinkHandler({
    editor: myEditor,
    onSetLink: () => console.log('链接已应用!'),
  })

  return (
    <div>
      <input
        value={url}
        onChange={(e) => setUrl(e.target.value)}
        onKeyDown={(e) => e.key === 'Enter' && setLink()}
      />
      <button onClick={setLink}>应用</button>
      <button onClick={removeLink}>移除</button>
    </div>
  )
}

参数说明

名称类型默认值描述
editorEditor | nullundefinedTiptap 编辑器实例
onSetLink() => voidundefined设置链接后的回调

返回值说明

名称类型描述
urlstring链接的当前 URL 值
setUrlReact.Dispatch<React.SetStateAction<string | null>>更新 URL 状态的函数
setLink() => void在编辑器中应用链接的函数
removeLink() => void从编辑器中移除链接的函数

工具函数

canSetLink(editor)

判断当前编辑器状态是否允许设置链接。

import { canSetLink } from '@/components/tiptap-ui/link-popover'

const canSet = canSetLink(editor)
if (canSet) {
  console.log('当前选区可应用链接')
}

isLinkActive(editor)

判断编辑器中是否当前处于链接激活状态。

import { isLinkActive } from '@/components/tiptap-ui/link-popover'

const isActive = isLinkActive(editor)
if (isActive) {
  console.log('当前已选中链接')
}

键盘快捷键

链接弹出框支持以下键盘操作:

  • Enter:应用当前输入框中 URL 作为链接(当焦点在 URL 输入框时)
  • Escape:关闭弹出框(标准弹出框行为)。

Requirements

Dependencies

  • @tiptap/react - Core Tiptap React integration
  • @tiptap/starter-kit - Provides the Link extension through its link option

Referenced Components

  • use-tiptap-editor (hook)
  • use-is-breakpoint (hook)
  • use-link-popover (hook)
  • button (primitive)
  • button-group (primitive)
  • popover (primitive)
  • card (primitive)
  • input (primitive)
  • separator (primitive)
  • tiptap-utils (lib)
  • corner-down-left-icon (icon)
  • external-link-icon (icon)
  • link-icon (icon)
  • trash-icon (icon)