Copy Anchor Link Button

Available in Start plan

A fully accessible copy anchor link button for Tiptap editors. Generate and copy deep links to specific nodes or blocks in the editor with keyboard shortcut support and smart node ID detection.

Installation

Add the component via the Tiptap CLI:

npx @tiptap/cli@latest add copy-anchor-link-button

Components

<CopyAnchorLinkButton />

A prebuilt React component that copies anchor links to nodes in the editor.

Usage

export default function MyEditor() {
  return (
    <CopyAnchorLinkButton
      editor={editor}
      text="Copy Link"
      hideWhenUnavailable={true}
      showShortcut={true}
      onCopied={() => console.log('Link copied!')}
      onNodeIdNotFound={(found) => console.log(`Node ID found: ${found}`)}
      onExtractedNodeId={(nodeId) => console.log(`Extracted ID: ${nodeId}`)}
    />
  )
}

Props

NameTypeDefaultDescription
editorEditor | nullundefinedThe Tiptap editor instance
textstringundefinedOptional text label for the button
hideWhenUnavailablebooleanfalseHides the button when no node ID is available
onCopied() => voidundefinedCallback fired after a successful copy operation
onNodeIdNotFound(found: boolean) => voidundefinedCalled when copy operation finishes with found status
onExtractedNodeId(nodeId: string | null) => voidundefinedCalled after node ID is extracted
showShortcutbooleanfalseShows a keyboard shortcut badge

Hooks

A custom hook to build your own copy anchor link button with full control over rendering and behavior.

Usage

function MyCopyAnchorLinkButton() {
  const { isVisible, handleCopyAnchorLink, canCopyAnchorLink, label, shortcutKeys, Icon } =
    useCopyAnchorLink({
      editor: myEditor,
      hideWhenUnavailable: true,
      onCopied: () => console.log('Link copied!'),
      onNodeIdNotFound: (found) => console.log(`Node ID found: ${found}`),
      onExtractedNodeId: (nodeId) => console.log(`Extracted ID: ${nodeId}`),
    })

  if (!isVisible) return null

  return (
    <button onClick={handleCopyAnchorLink} disabled={!canCopyAnchorLink} aria-label={label}>
      <Icon />
      {label}
      {shortcutKeys && <Badge>{parseShortcutKeys({ shortcutKeys })}</Badge>}
    </button>
  )
}

Props

NameTypeDefaultDescription
editorEditor | nullundefinedThe Tiptap editor instance
hideWhenUnavailablebooleanfalseHides the button when no node ID is available
onCopied() => voidundefinedCallback fired after a successful copy operation
onNodeIdNotFound(found: boolean) => voidundefinedCalled when copy operation finishes with found status
onExtractedNodeId(nodeId: string | null) => voidundefinedCalled after node ID is extracted

Return Values

NameTypeDescription
isVisiblebooleanWhether the button should be rendered
canCopyAnchorLinkbooleanIf an anchor link can be copied for the current node
handleCopyAnchorLink() => booleanFunction to copy the anchor link for the selected node
labelstringAccessible label text for the button
shortcutKeysstringKeyboard shortcut for copying anchor links
IconReact.FCIcon component for the copy button (LinkIcon)

Utilities

canCopyAnchorLink(editor)

Checks if a node has a data-id that can be copied in the current editor state.

import { canCopyAnchorLink } from '@/components/tiptap-ui/copy-anchor-link-button'

const canCopy = canCopyAnchorLink(editor)

copyNodeId(editor, onExtractedNodeId, onNodeIdNotFound)

Programmatically extracts and copies the node ID to clipboard with full URL.

import { copyNodeId } from '@/components/tiptap-ui/copy-anchor-link-button'

const success = await copyNodeId(
  editor,
  (nodeId) => console.log(`Extracted: ${nodeId}`),
  (found) => console.log(`Found: ${found}`),
)
if (success) {
  console.log('Anchor link copied successfully!')
}

extractNodeId(node, attributeName)

Extracts the data-id from a specific node.

import { extractNodeId } from '@/components/tiptap-ui/copy-anchor-link-button'

const nodeId = extractNodeId(node, 'data-id')

shouldShowButton(props)

Utility to determine if the copy anchor link button should be visible based on editor state and configuration.

import { shouldShowButton } from '@/components/tiptap-ui/copy-anchor-link-button'

const shouldShow = shouldShowButton({
  editor,
  hideWhenUnavailable: true,
})

Keyboard Shortcuts

The copy anchor link button supports the following keyboard shortcut:

  • Cmd/Ctrl + Ctrl + L: Copy the anchor link for the current node

The shortcut is automatically registered when using either the <CopyAnchorLinkButton /> component or the useCopyAnchorLink() hook. This shortcut works with any block-level node that has a unique ID including paragraphs, headings, blockquotes, and code blocks.

How It Works

The copy anchor link functionality works by:

  1. Node ID Detection: Automatically detects nodes with unique IDs (typically using a data-id attribute)
  2. URL Generation: Creates a full URL with the current page URL plus a hash fragment pointing to the node ID
  3. Clipboard Integration: Uses the native clipboard API to copy the generated URL
  4. Source Tracking: Adds a source=copy_link query parameter for analytics

The generated URL format is: https://example.com/page?source=copy_link#node-id

Requirements

Dependencies

  • @tiptap/react - Core Tiptap React integration
  • @tiptap/pm - ProseMirror core functionality
  • react-hotkeys-hook - Keyboard shortcut management

Referenced Components

  • use-tiptap-editor (hook)
  • use-mobile (hook)
  • button (primitive)
  • badge (primitive)
  • tiptap-utils (lib)
  • tiptap-advanced-utils (lib)
  • link-icon (icon)

Extensions Required

This component works best with the UniqueID extension that automatically assigns unique identifiers to nodes. The extension can be configured with a custom attribute name (defaults to data-id).