Copy Anchor Link Button
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
Name | Type | Default | Description |
---|---|---|---|
editor | Editor | null | undefined | The Tiptap editor instance |
text | string | undefined | Optional text label for the button |
hideWhenUnavailable | boolean | false | Hides the button when no node ID is available |
onCopied | () => void | undefined | Callback fired after a successful copy operation |
onNodeIdNotFound | (found: boolean) => void | undefined | Called when copy operation finishes with found status |
onExtractedNodeId | (nodeId: string | null) => void | undefined | Called after node ID is extracted |
showShortcut | boolean | false | Shows a keyboard shortcut badge |
Hooks
useCopyAnchorLink()
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
Name | Type | Default | Description |
---|---|---|---|
editor | Editor | null | undefined | The Tiptap editor instance |
hideWhenUnavailable | boolean | false | Hides the button when no node ID is available |
onCopied | () => void | undefined | Callback fired after a successful copy operation |
onNodeIdNotFound | (found: boolean) => void | undefined | Called when copy operation finishes with found status |
onExtractedNodeId | (nodeId: string | null) => void | undefined | Called after node ID is extracted |
Return Values
Name | Type | Description |
---|---|---|
isVisible | boolean | Whether the button should be rendered |
canCopyAnchorLink | boolean | If an anchor link can be copied for the current node |
handleCopyAnchorLink | () => boolean | Function to copy the anchor link for the selected node |
label | string | Accessible label text for the button |
shortcutKeys | string | Keyboard shortcut for copying anchor links |
Icon | React.FC | Icon 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:
- Node ID Detection: Automatically detects nodes with unique IDs (typically using a
data-id
attribute) - URL Generation: Creates a full URL with the current page URL plus a hash fragment pointing to the node ID
- Clipboard Integration: Uses the native clipboard API to copy the generated URL
- 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 functionalityreact-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
).