How to Configure Table Features (Merge Cells & Resize Columns) in reactjs-tiptap-editor
Enable resizable: true in the Table extension options to activate column resizing, and invoke editor.chain().focus().mergeCells().run() via the RichTextBubbleTable component to merge selected cells.
The reactjs-tiptap-editor repository extends TipTap's @tiptap/extension-table with custom React wrappers to provide a comprehensive table editing experience. Configuring table features requires modifying the extension configuration in src/extensions/Table/Table.ts for resizing capabilities, and leveraging the bubble menu component in src/components/Bubble/RichTextBubbleTable.tsx for cell merging operations.
Enabling Column Resizing
Extension Configuration
Column resizing is controlled through the custom Table extension located at src/extensions/Table/Table.ts. The extension overrides the default addOptions() method to enable resizing behaviors by default.
// src/extensions/Table/Table.ts
addOptions() {
return {
...this.parent?.(),
resizable: true, // Enables draggable column borders
lastColumnResizable: true // Allows resizing the right-most column
};
}
When resizable is set to true, TipTap injects mouse-draggable handles on each column border. Dragging these handles updates the column widths in the document model immediately.
Runtime Configuration
You can override these defaults when initializing the editor instance to disable resizing for specific use cases, such as read-only views.
import { Table } from '@/extensions/Table/Table';
const editor = new Editor({
extensions: [
Table.configure({
resizable: false,
lastColumnResizable: false
}),
// ...other extensions
],
});
Implementing Cell Merging
RichTextBubbleTable Integration
The merge functionality is exposed through the RichTextBubbleTable component in src/components/Bubble/RichTextBubbleTable.tsx. This bubble menu appears when the cursor is inside a table and provides the merge action.
The component calls onMergeCell (lines 51-53) which executes the merge command:
// src/components/Bubble/RichTextBubbleTable.tsx
function onMergeCell() {
editor.chain().focus().mergeCells().run();
}
The button is conditionally enabled only when editor?.can()?.mergeCells?.() returns true, ensuring the action only appears for valid rectangular cell selections.
Programmatic Usage
You can trigger cell merging from any custom UI component using the same chain command:
const mergeSelectedCells = () => {
editor.chain().focus().mergeCells().run();
};
// Example action button with disabled state
<ActionButton
action={mergeSelectedCells}
disabled={!editor?.can()?.mergeCells?.()}
icon='TableCellsMerge'
tooltip='Merge selected cells'
/>
Complete Implementation Example
Below is a minimal implementation that demonstrates inserting a resizable table and accessing the merge functionality:
import React from 'react';
import { ActionButton } from '@/components';
import { Table } from '@/extensions/Table/Table';
import { RichTextBubbleTable } from '@/components/Bubble/RichTextBubbleTable';
import { useEditorInstance } from '@/store/editor';
export const TableEditor = () => {
const editor = useEditorInstance();
const insertTable = () => {
editor
.chain()
.focus()
.insertTable({ rows: 3, cols: 3, withHeaderRow: false })
.run();
};
return (
<>
<ActionButton
action={insertTable}
icon='Table'
tooltip='Insert 3×3 resizable table'
/>
{/* Bubble menu provides merge, split, add/delete row/column actions */}
<RichTextBubbleTable />
</>
);
};
This configuration creates tables with draggable column borders (via the resizable option) and exposes the merge cells button through the bubble menu when multiple cells are selected.
Summary
- Configure
resizable: trueinsrc/extensions/Table/Table.tsto enable draggable column resize handles on all tables. - Set
lastColumnResizable: trueto ensure users can resize the right-most column border. - Invoke
editor.chain().focus().mergeCells().run()to programmatically merge selected cells into a single cell. - Use
editor.can().mergeCells()to conditionally render merge buttons only when a valid rectangular selection exists. - The
RichTextBubbleTablecomponent atsrc/components/Bubble/RichTextBubbleTable.tsxprovides the standard UI for table manipulation actions.
Frequently Asked Questions
How do I disable column resizing in reactjs-tiptap-editor?
Configure the Table extension with resizable: false when initializing the editor. This removes the draggable handles from all column borders.
Can I trigger cell merging from a custom toolbar instead of the bubble menu?
Yes. Import useEditorInstance from your editor store and call editor.chain().focus().mergeCells().run() directly from any button or keyboard shortcut handler. Ensure you check editor.can().mergeCells() to validate the selection first.
What determines if the merge cells button is available?
The button availability depends on editor.can().mergeCells(), which validates that the current selection forms a proper rectangular range of adjacent table cells. If you select cells that are not contiguous or overlap existing merged cells, the command returns false and the button disables automatically.
How do I prevent users from resizing only the last column?
Set lastColumnResizable: false in the Table extension options. This keeps resizing enabled for all other columns while removing the resize handle from the right-most column border.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →