Rich text editor React component library based on Tiptap with extensive formatting controls and Mantine integration
—
Pending
Does it follow best practices?
Impact
Pending
No eval scenarios have been run
Pending
The risk profile of this skill
Tiptap extensions with enhanced functionality for links and task lists. These extensions provide additional features beyond the standard Tiptap extensions, including custom keyboard shortcuts and styling integration.
Enhanced Tiptap Link extension with custom keyboard shortcuts and optimized behavior for rich text editing.
/**
* Enhanced Link extension with keyboard shortcuts
* Extends @tiptap/extension-link with additional functionality
* Keyboard shortcut: Ctrl/Cmd + K opens link editor
*/
const Link: Extension;Features:
Usage Example:
import { useEditor } from "@tiptap/react";
import StarterKit from "@tiptap/starter-kit";
import { RichTextEditor, Link } from "@mantine/tiptap";
function EditorWithLinks() {
const editor = useEditor({
extensions: [
StarterKit,
Link, // Enhanced Link extension
],
content: '<p>Visit <a href="https://mantine.dev">Mantine</a> for more info!</p>',
});
return (
<RichTextEditor editor={editor}>
<RichTextEditor.Toolbar>
<RichTextEditor.ControlsGroup>
<RichTextEditor.Link />
<RichTextEditor.Unlink />
</RichTextEditor.ControlsGroup>
</RichTextEditor.Toolbar>
<RichTextEditor.Content />
</RichTextEditor>
);
}Factory function that enhances any Tiptap TaskList extension with custom keyboard shortcuts and Mantine-specific styling.
/**
* Factory function to enhance TaskList extensions
* Adds keyboard shortcuts and custom styling to any TaskList extension
* @param TipTapTaskList - The TaskList extension to enhance
* @returns Enhanced TaskList extension with additional functionality
*/
function getTaskListExtension<T>(TipTapTaskList: T): T;Features:
Cmd/Ctrl + [: Decrease task indentation (lift)Cmd/Ctrl + ]: Increase task indentation (sink)Usage Example:
import { useEditor } from "@tiptap/react";
import StarterKit from "@tiptap/starter-kit";
import TaskList from "@tiptap/extension-task-list";
import TaskItem from "@tiptap/extension-task-item";
import { RichTextEditor, getTaskListExtension } from "@mantine/tiptap";
function EditorWithTasks() {
const editor = useEditor({
extensions: [
StarterKit,
// Enhanced TaskList with keyboard shortcuts and styling
getTaskListExtension(TaskList),
TaskItem.configure({
nested: true,
}),
],
content: `
<ul data-type="taskList">
<li data-type="taskItem" data-checked="false">Uncompleted task</li>
<li data-type="taskItem" data-checked="true">Completed task</li>
<li data-type="taskItem" data-checked="false">
Parent task
<ul data-type="taskList">
<li data-type="taskItem" data-checked="false">Nested task</li>
</ul>
</li>
</ul>
`,
});
return (
<RichTextEditor editor={editor}>
<RichTextEditor.Toolbar>
<RichTextEditor.ControlsGroup>
<RichTextEditor.TaskList />
<RichTextEditor.TaskListSink />
<RichTextEditor.TaskListLift />
</RichTextEditor.ControlsGroup>
</RichTextEditor.Toolbar>
<RichTextEditor.Content />
</RichTextEditor>
);
}The Link extension is built on top of @tiptap/extension-link with the following enhancements:
// Internal implementation (for reference)
import TipTapLink from '@tiptap/extension-link';
const Link = TipTapLink.extend({
addKeyboardShortcuts: () => ({
'Mod-k': () => {
// Dispatches custom event for UI integration
window.dispatchEvent(new Event('edit-link'));
return true;
},
}),
}).configure({
openOnClick: false // Prevents links from opening when clicked
});Configuration Options:
@tiptap/extension-link options are supportedopenOnClick: false is set by default for better editing experienceThe factory function enhances TaskList extensions with:
// Internal implementation (for reference)
const getTaskListExtension = <T>(TipTapTaskList: T): T =>
(TipTapTaskList as any)
.extend({
addKeyboardShortcuts: () => ({
'Mod-[': ({ editor }: any) => {
editor.chain().focus().liftListItem('taskItem').run();
return true;
},
'Mod-]': ({ editor }: any) => {
editor.chain().focus().sinkListItem('taskItem').run();
return true;
},
}),
})
.configure({
HTMLAttributes: {
class: `mantine-RichTextEditor-taskList`,
},
});Enhancement Features:
import { useEditor } from "@tiptap/react";
import StarterKit from "@tiptap/starter-kit";
import TaskList from "@tiptap/extension-task-list";
import TaskItem from "@tiptap/extension-task-item";
import { RichTextEditor, Link, getTaskListExtension } from "@mantine/tiptap";
function FullFeaturedEditor() {
const editor = useEditor({
extensions: [
StarterKit,
// Enhanced Link extension
Link,
// Enhanced TaskList extension
getTaskListExtension(TaskList),
TaskItem.configure({
nested: true,
HTMLAttributes: {
class: 'my-task-item',
},
}),
],
content: `
<h2>Rich Text Editor with Extensions</h2>
<p>This editor supports <a href="https://mantine.dev">enhanced links</a>
with keyboard shortcuts (Cmd/Ctrl+K).</p>
<p>Task management with enhanced shortcuts:</p>
<ul data-type="taskList">
<li data-type="taskItem" data-checked="false">
Press Cmd/Ctrl+] to indent this task
</li>
<li data-type="taskItem" data-checked="true">
Press Cmd/Ctrl+[ to outdent this task
</li>
<li data-type="taskItem" data-checked="false">
Parent task
<ul data-type="taskList">
<li data-type="taskItem" data-checked="false">Nested subtask</li>
</ul>
</li>
</ul>
`,
});
return (
<RichTextEditor editor={editor}>
<RichTextEditor.Toolbar sticky stickyOffset={60}>
{/* Link controls */}
<RichTextEditor.ControlsGroup>
<RichTextEditor.Link />
<RichTextEditor.Unlink />
</RichTextEditor.ControlsGroup>
{/* Task controls */}
<RichTextEditor.ControlsGroup>
<RichTextEditor.TaskList />
<RichTextEditor.TaskListSink />
<RichTextEditor.TaskListLift />
</RichTextEditor.ControlsGroup>
</RichTextEditor.Toolbar>
<RichTextEditor.Content />
</RichTextEditor>
);
}The Link extension dispatches custom events that can be handled by your application:
useEffect(() => {
const handleEditLink = () => {
console.log('Link editing triggered');
// Custom link editing logic
};
window.addEventListener('edit-link', handleEditLink);
return () => {
window.removeEventListener('edit-link', handleEditLink);
};
}, []);Extensions automatically integrate with Mantine's styling system:
// TaskList extension applies these classes automatically
.mantine-RichTextEditor-taskList {
/* Mantine task list styling */
}
// You can override with custom styles
<RichTextEditor
styles={{
taskList: {
marginLeft: '1rem',
'& li': {
marginBottom: '0.5rem',
},
},
}}
>
{/* editor content */}
</RichTextEditor>You can create your own enhanced extensions using similar patterns:
import { Extension } from '@tiptap/core';
const MyCustomExtension = Extension.create({
name: 'myCustom',
addKeyboardShortcuts() {
return {
'Mod-Shift-x': () => {
// Custom functionality
return true;
},
};
},
addOptions() {
return {
HTMLAttributes: {
class: 'mantine-RichTextEditor-custom',
},
};
},
});
// Use with RichTextEditor
const editor = useEditor({
extensions: [StarterKit, MyCustomExtension],
});Extensions require specific Tiptap packages:
Link Extension:
@tiptap/extension-link (peer dependency)Link from @mantine/tiptapTaskList Extension Factory:
@tiptap/extension-task-list@tiptap/extension-task-itemgetTaskListExtension()const editor = useEditor({
extensions: [
StarterKit, // Base extensions first
Link, // Enhanced Link extension
getTaskListExtension(TaskList), // Enhanced TaskList
TaskItem, // TaskItem after TaskList
// Other extensions...
],
});// Configure enhanced extensions
const editor = useEditor({
extensions: [
StarterKit,
Link, // Uses default configuration
getTaskListExtension(
TaskList.configure({
itemTypeName: 'taskItem',
HTMLAttributes: {
class: 'custom-task-list',
},
})
),
],
});import type { Extension } from '@tiptap/core';
import { Link, getTaskListExtension } from '@mantine/tiptap';
// Extensions have proper TypeScript support
const linkExtension: Extension = Link;
const taskListExtension: Extension = getTaskListExtension(TaskList);