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
Essential components for building rich text editors including the main wrapper, content area, toolbar, and control grouping components.
Main wrapper component that provides context and styling for all child components. Uses the compound component pattern with 30+ static sub-components.
/**
* Main rich text editor wrapper component
* @param props - RichTextEditor configuration and children
* @returns JSX.Element with context provider and styling
*/
function RichTextEditor(props: RichTextEditorProps): JSX.Element;
interface RichTextEditorProps extends BoxProps, StylesApiProps<RichTextEditorFactory>, ElementProps<'div'> {
/** Tiptap editor instance (required) */
editor: Editor | null;
/** Determines whether code highlight styles should be added @default true */
withCodeHighlightStyles?: boolean;
/** Determines whether typography styles should be added @default true */
withTypographyStyles?: boolean;
/** Called if RichTextEditor.SourceCode clicked */
onSourceCodeTextSwitch?: (isSourceCodeModeActive: boolean) => void;
/** Labels that are used in controls for accessibility and i18n */
labels?: Partial<RichTextEditorLabels>;
/** Child editor components (required) */
children: React.ReactNode;
}
type RichTextEditorVariant = 'default' | 'subtle';
type RichTextEditorStylesNames =
| 'linkEditorSave'
| 'linkEditorDropdown'
| 'root'
| 'content'
| 'Typography'
| 'control'
| 'controlIcon'
| 'controlsGroup'
| 'toolbar'
| 'linkEditor'
| 'linkEditorInput'
| 'linkEditorExternalControl';Usage Example:
import { useEditor } from "@tiptap/react";
import StarterKit from "@tiptap/starter-kit";
import { RichTextEditor } from "@mantine/tiptap";
function MyEditor() {
const editor = useEditor({
extensions: [StarterKit],
content: "<p>Hello world!</p>",
});
return (
<RichTextEditor
editor={editor}
withCodeHighlightStyles={true}
withTypographyStyles={true}
labels={{ boldControlLabel: "Make text bold" }}
>
<RichTextEditor.Toolbar>
<RichTextEditor.Bold />
</RichTextEditor.Toolbar>
<RichTextEditor.Content />
</RichTextEditor>
);
}Renders the actual editor content area where users type and edit text. Automatically integrates with Tiptap's EditorContent.
/**
* Editor content area component
* @param props - Content area styling and configuration
* @returns JSX.Element with Tiptap EditorContent integration
*/
RichTextEditor.Content: React.ComponentType<RichTextEditorContentProps>;
interface RichTextEditorContentProps extends BoxProps, CompoundStylesApiProps<RichTextEditorContentFactory>, ElementProps<'div'> {}
type RichTextEditorContentStylesNames = 'root';Usage Example:
<RichTextEditor editor={editor}>
<RichTextEditor.Toolbar>
{/* toolbar controls */}
</RichTextEditor.Toolbar>
{/* Content area where users type */}
<RichTextEditor.Content />
</RichTextEditor>Container component for organizing editor controls with optional sticky positioning and visual styling.
/**
* Toolbar container for organizing editor controls
* @param props - Toolbar configuration including sticky positioning
* @returns JSX.Element toolbar container
*/
RichTextEditor.Toolbar: React.ComponentType<RichTextEditorToolbarProps>;
interface RichTextEditorToolbarProps extends BoxProps, CompoundStylesApiProps<RichTextEditorToolbarFactory>, ElementProps<'div'> {
/** Determines whether position: sticky styles should be added @default false */
sticky?: boolean;
/** Sets top style to offset elements with fixed position @default 0 */
stickyOffset?: React.CSSProperties['top'];
}
type RichTextEditorToolbarStylesNames = 'toolbar';Usage Example:
<RichTextEditor editor={editor}>
{/* Sticky toolbar that stays at top when scrolling */}
<RichTextEditor.Toolbar sticky stickyOffset={60}>
<RichTextEditor.ControlsGroup>
<RichTextEditor.Bold />
<RichTextEditor.Italic />
</RichTextEditor.ControlsGroup>
</RichTextEditor.Toolbar>
<RichTextEditor.Content />
</RichTextEditor>Groups related controls together with visual separation, typically used within toolbars to organize functionality.
/**
* Groups related controls with visual separation
* @param props - Control group styling configuration
* @returns JSX.Element container for grouped controls
*/
RichTextEditor.ControlsGroup: React.ComponentType<RichTextEditorControlsGroupProps>;
interface RichTextEditorControlsGroupProps extends BoxProps, CompoundStylesApiProps<RichTextEditorControlsGroupFactory>, ElementProps<'div'> {}
type RichTextEditorControlsGroupStylesNames = 'controlsGroup';Usage Example:
<RichTextEditor.Toolbar>
{/* Group text formatting controls */}
<RichTextEditor.ControlsGroup>
<RichTextEditor.Bold />
<RichTextEditor.Italic />
<RichTextEditor.Underline />
</RichTextEditor.ControlsGroup>
{/* Group heading controls */}
<RichTextEditor.ControlsGroup>
<RichTextEditor.H1 />
<RichTextEditor.H2 />
<RichTextEditor.H3 />
</RichTextEditor.ControlsGroup>
</RichTextEditor.Toolbar>Base component for creating custom editor controls. Provides consistent styling and behavior patterns.
/**
* Base component for creating custom editor controls
* @param props - Control configuration including active state and interactions
* @returns JSX.Element button component for editor controls
*/
RichTextEditor.Control: React.ComponentType<RichTextEditorControlProps>;
interface RichTextEditorControlProps extends BoxProps, CompoundStylesApiProps<RichTextEditorControlFactory>, ElementProps<'button'> {
/** Determines whether the control should have active state @default false */
active?: boolean;
/** Determines whether the control can be interacted with @default true */
interactive?: boolean;
}
type RichTextEditorControlStylesNames = 'control';Usage Example:
import { useRichTextEditorContext } from "@mantine/tiptap";
import { IconCustom } from "@tabler/icons-react";
function CustomControl() {
const { editor } = useRichTextEditorContext();
return (
<RichTextEditor.Control
active={editor?.isActive('customMark')}
onClick={() => editor?.chain().focus().toggleCustomMark().run()}
aria-label="Apply custom formatting"
>
<IconCustom size={16} />
</RichTextEditor.Control>
);
}The typical component hierarchy for a rich text editor:
<RichTextEditor editor={editor}>
<RichTextEditor.Toolbar sticky>
<RichTextEditor.ControlsGroup>
<RichTextEditor.Bold />
<RichTextEditor.Italic />
{/* More controls... */}
</RichTextEditor.ControlsGroup>
<RichTextEditor.ControlsGroup>
<RichTextEditor.H1 />
<RichTextEditor.H2 />
{/* More controls... */}
</RichTextEditor.ControlsGroup>
</RichTextEditor.Toolbar>
<RichTextEditor.Content />
</RichTextEditor>All core components integrate with Mantine's styling system:
styles prop to override specific style slotsclassNames prop to add custom CSS classesunstyled prop