diff --git a/demos/src/Nodes/Table/React/index.html b/demos/src/Nodes/Table/React/index.html
new file mode 100644
index 000000000..42852ed41
--- /dev/null
+++ b/demos/src/Nodes/Table/React/index.html
@@ -0,0 +1,15 @@
+
+
+
+
+
+
+
+
+
+
+
diff --git a/demos/src/Nodes/Table/React/index.jsx b/demos/src/Nodes/Table/React/index.jsx
new file mode 100644
index 000000000..321411783
--- /dev/null
+++ b/demos/src/Nodes/Table/React/index.jsx
@@ -0,0 +1,90 @@
+import React from 'react'
+import { useEditor, EditorContent } from '@tiptap/react'
+import Document from '@tiptap/extension-document'
+import Paragraph from '@tiptap/extension-paragraph'
+import Text from '@tiptap/extension-text'
+import Table from '@tiptap/extension-table'
+import TableRow from '@tiptap/extension-table-row'
+import TableCell from '@tiptap/extension-table-cell'
+import TableHeader from '@tiptap/extension-table-header'
+import Gapcursor from '@tiptap/extension-gapcursor'
+import './styles.scss'
+
+export default () => {
+ const editor = useEditor({
+ extensions: [
+ Document,
+ Paragraph,
+ Text,
+ Gapcursor,
+ Table.configure({
+ resizable: true,
+ }),
+ TableRow,
+ TableHeader,
+ TableCell,
+ ],
+ content: `
+
+
+
+ Name |
+ Description |
+
+
+ Cyndi Lauper |
+ singer |
+ songwriter |
+ actress |
+
+
+
+ `,
+ })
+
+ if (!editor) {
+ return null
+ }
+
+ return (
+ <>
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ >
+ )
+}
diff --git a/demos/src/Nodes/Table/React/index.spec.js b/demos/src/Nodes/Table/React/index.spec.js
new file mode 100644
index 000000000..8fb0e9476
--- /dev/null
+++ b/demos/src/Nodes/Table/React/index.spec.js
@@ -0,0 +1,80 @@
+context('/src/Nodes/Table/React/', () => {
+ before(() => {
+ cy.visit('/src/Nodes/Table/React/')
+ })
+
+ beforeEach(() => {
+ cy.get('.ProseMirror').then(([{ editor }]) => {
+ editor.commands.clearContent()
+ })
+ })
+
+ it('creates a table (1x1)', () => {
+ cy.get('.ProseMirror').then(([{ editor }]) => {
+ editor.commands.insertTable({ cols: 1, rows: 1, withHeaderRow: false })
+
+ cy.get('.ProseMirror').find('td').its('length').should('eq', 1)
+ cy.get('.ProseMirror').find('tr').its('length').should('eq', 1)
+ })
+ })
+
+ it('creates a table (3x1)', () => {
+ cy.get('.ProseMirror').then(([{ editor }]) => {
+ editor.commands.insertTable({ cols: 3, rows: 1, withHeaderRow: false })
+
+ cy.get('.ProseMirror').find('td').its('length').should('eq', 3)
+ cy.get('.ProseMirror').find('tr').its('length').should('eq', 1)
+ })
+ })
+
+ it('creates a table (1x3)', () => {
+ cy.get('.ProseMirror').then(([{ editor }]) => {
+ editor.commands.insertTable({ cols: 1, rows: 3, withHeaderRow: false })
+
+ cy.get('.ProseMirror').find('td').its('length').should('eq', 3)
+ cy.get('.ProseMirror').find('tr').its('length').should('eq', 3)
+ })
+ })
+
+ it('creates a table with header row (1x3)', () => {
+ cy.get('.ProseMirror').then(([{ editor }]) => {
+ editor.commands.insertTable({ cols: 1, rows: 3, withHeaderRow: true })
+
+ cy.get('.ProseMirror').find('th').its('length').should('eq', 1)
+ cy.get('.ProseMirror').find('td').its('length').should('eq', 2)
+ cy.get('.ProseMirror').find('tr').its('length').should('eq', 3)
+ })
+ })
+
+ it('creates a table with correct defaults (3x3, th)', () => {
+ cy.get('.ProseMirror').then(([{ editor }]) => {
+ editor.commands.insertTable()
+
+ cy.get('.ProseMirror').find('th').its('length').should('eq', 3)
+ cy.get('.ProseMirror').find('td').its('length').should('eq', 6)
+ cy.get('.ProseMirror').find('tr').its('length').should('eq', 3)
+ })
+ })
+
+ it('generates correct markup for a table (1x1)', () => {
+ cy.get('.ProseMirror').then(([{ editor }]) => {
+ editor.commands.insertTable({ cols: 1, rows: 1, withHeaderRow: false })
+
+ const html = editor.getHTML()
+ expect(html).to.equal(
+ '',
+ )
+ })
+ })
+
+ it('generates correct markup for a table (1x1, th)', () => {
+ cy.get('.ProseMirror').then(([{ editor }]) => {
+ editor.commands.insertTable({ cols: 1, rows: 1, withHeaderRow: true })
+
+ const html = editor.getHTML()
+ expect(html).to.equal(
+ '',
+ )
+ })
+ })
+})
diff --git a/demos/src/Nodes/Table/React/styles.scss b/demos/src/Nodes/Table/React/styles.scss
new file mode 100644
index 000000000..46bb644ea
--- /dev/null
+++ b/demos/src/Nodes/Table/React/styles.scss
@@ -0,0 +1,65 @@
+.ProseMirror {
+ table {
+ border-collapse: collapse;
+ margin: 0;
+ overflow: hidden;
+ table-layout: fixed;
+ width: 100%;
+
+ td,
+ th {
+ border: 2px solid #ced4da;
+ box-sizing: border-box;
+ min-width: 1em;
+ padding: 3px 5px;
+ position: relative;
+ vertical-align: top;
+
+ > * {
+ margin-bottom: 0;
+ }
+ }
+
+ th {
+ background-color: #f1f3f5;
+ font-weight: bold;
+ text-align: left;
+ }
+
+ .selectedCell:after {
+ background: rgba(200, 200, 255, 0.4);
+ content: "";
+ left: 0;
+ right: 0;
+ top: 0;
+ bottom: 0;
+ pointer-events: none;
+ position: absolute;
+ z-index: 2;
+ }
+
+ .column-resize-handle {
+ background-color: #adf;
+ bottom: -2px;
+ position: absolute;
+ right: -2px;
+ pointer-events: none;
+ top: 0;
+ width: 4px;
+ }
+
+ p {
+ margin: 0;
+ }
+ }
+}
+
+.tableWrapper {
+ padding: 1rem 0;
+ overflow-x: auto;
+}
+
+.resize-cursor {
+ cursor: ew-resize;
+ cursor: col-resize;
+}