Feature Request: add option to use Link component for react-router for @tiptap/extension-link #4135
Replies: 4 comments
-
I have also been fighting this issue with the built-in link, and been trying to find a way to get it to render the React |
Beta Was this translation helpful? Give feedback.
-
Is there any work around so far? |
Beta Was this translation helpful? Give feedback.
-
If you want to handle link clicks in Tiptap (e.g. using Instead, you can use a global onClick handler directly on the <EditorContent
editor={editor}
onClick={(e) => {
const target = e.target as HTMLElement
if (target.tagName === 'A' && target instanceof HTMLAnchorElement) {
e.preventDefault()
const href = target.getAttribute('href')
// your code ...
}
}}
/> |
Beta Was this translation helpful? Give feedback.
-
With Tiptap 3 Mark views, you can now render the Link extension as a React Router or Next.js link component. Example for the Next.js Link component: // This is a client component, required by the useEditor hook.
"use client";
import React from "react";
import Link from "next/link"; // Import Next.js Link component
// Tiptap imports
import {
useEditor,
EditorContent,
ReactMarkViewRenderer,
MarkViewContent,
MarkViewRendererProps,
} from "@tiptap/react";
import StarterKit from "@tiptap/starter-kit";
import TiptapLink from "@tiptap/extension-link";
// 1. The React Component for the Link (Mark View)
// This component renders a Next.js <Link> inside the editor.
const NextJsMarkView = (props: MarkViewRendererProps) => {
const { mark, editor } = props;
const { href, target } = mark.attrs;
// Determine if the link is internal or external
const isInternal = href && href.startsWith("/");
// For internal links, use Next.js's Link component for client-side routing.
// For external links, use a standard <a> tag.
if (isInternal) {
return (
<Link
href={href}
target={target}
className={`tiptap-nextjs-link ${
editor.isEditable ? "is-editable" : ""
}`}
>
{/* MarkViewContent renders the actual text content of the link */}
<MarkViewContent />
</Link>
);
}
// External link
return (
<a
href={href}
target={target}
rel="noopener noreferrer nofollow"
className="tiptap-external-link"
>
<MarkViewContent />
</a>
);
};
// 2. The Custom Tiptap Link Extension
// This extends the default Link extension to use our React component.
const CustomLinkExtension = TiptapLink.extend({
addMarkView() {
return ReactMarkViewRenderer(NextJsMarkView);
},
});
// 3. The Tiptap Editor Component
// This component sets up the editor with our custom link extension.
const TiptapEditor = () => {
const editor = useEditor({
extensions: [
StarterKit,
// Use our custom link extension
CustomLinkExtension.configure({
// openOnClick: false,
// Autolink will create links as you type
autolink: true,
}),
],
content: `
<h2>Next.js Links in Tiptap</h2>
<p>This is a demonstration of using Next.js links within the Tiptap editor. Clicking an internal link will use the Next.js router for a smooth, client-side transition.</p>
<p>Try clicking this <a href="/dashboard">internal link to the dashboard</a>. Notice the URL changes without a page reload.</p>
<p>External links like this one to <a href="https://nextjs.org" target="_blank">the Next.js website</a> will open in a new tab as expected.</p>
<p>You can also type a URL like https://google.com and it will be autolinked.</p>
`,
// Fix SSR hydration issues
immediatelyRender: false,
});
return <EditorContent editor={editor} />;
};
// Main Page Component for Next.js
// This would be your page file, e.g., `app/page.jsx` or `pages/index.jsx`.
export default function TiptapNextJsPage() {
return (
<div className="main-container">
<h1 style={{ marginBottom: "1rem" }}>Tiptap and Next.js Integration</h1>
<div className="editor-container">
<TiptapEditor />
</div>
<div className="info-box">
<p>
<strong>💡 How it works:</strong> This demo shows Next.js Link
components working seamlessly within a Tiptap editor. Internal links
(like the dashboard link above) use client-side routing, while
external links open in new tabs. The dashboard page has been created
at `/dashboard` to test the navigation.
</p>
</div>
</div>
);
} Does this solution work for you? @coolcorexix For now, I don't know if we should create official extensions for the Link components of frontend frameworks like Next.js and React Router, as we'd have to maintain them. We'll discuss it internally. Consider creating a community extension for the Next.js or Remix Link components. |
Beta Was this translation helpful? Give feedback.
Uh oh!
There was an error while loading. Please reload this page.
-
Description
Can we add some options like this:
But I also questioning about its feasibility, because as far as I have customized, tiptap only allow native HTML tags to be in renderHTML and addHTMLAttributes. What are your thought on this?
Use Case
Inside the tiptap editor, I want to have that smooth transition and router-controlled behaviour when I clicked on a link.
Type
New extension
Beta Was this translation helpful? Give feedback.
All reactions