diff --git a/demos/src/Nodes/ListItem/React/index.html b/demos/src/Nodes/ListItem/React/index.html
new file mode 100644
index 00000000..0eb904ab
--- /dev/null
+++ b/demos/src/Nodes/ListItem/React/index.html
@@ -0,0 +1,15 @@
+
+
+
+
+
+
+
+
+
+
+
diff --git a/demos/src/Nodes/ListItem/React/index.jsx b/demos/src/Nodes/ListItem/React/index.jsx
new file mode 100644
index 00000000..3742b824
--- /dev/null
+++ b/demos/src/Nodes/ListItem/React/index.jsx
@@ -0,0 +1,77 @@
+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 BulletList from '@tiptap/extension-bullet-list'
+import OrderedList from '@tiptap/extension-ordered-list'
+import ListItem from '@tiptap/extension-list-item'
+import './styles.scss'
+
+export default () => {
+ const editor = useEditor({
+ extensions: [Document, Paragraph, Text, BulletList, OrderedList, ListItem],
+ content: `
+
+ I like lists. Let’s add one:
+
+
+ - This is a bullet list.
+ - And it has three list items.
+ - Here is the third one.
+
+
+ Do you want to see one more? I bet! Here is another one:
+
+
+ - That’s a different list, actually it’s an ordered list.
+ - It also has three list items.
+ - And all of them are numbered.
+
+
+ Lists would be nothing without list items.
+
+ `,
+ })
+
+ if (!editor) {
+ return null
+ }
+
+ return (
+ <>
+
+
+
+
+
+
+
+ >
+ )
+}
diff --git a/demos/src/Nodes/ListItem/React/index.spec.js b/demos/src/Nodes/ListItem/React/index.spec.js
new file mode 100644
index 00000000..95695e2c
--- /dev/null
+++ b/demos/src/Nodes/ListItem/React/index.spec.js
@@ -0,0 +1,38 @@
+context('/src/Nodes/ListItem/React/', () => {
+ before(() => {
+ cy.visit('/src/Nodes/ListItem/React/')
+ })
+
+ beforeEach(() => {
+ cy.get('.ProseMirror').then(([{ editor }]) => {
+ editor.commands.setContent('')
+ })
+ })
+
+ it('should add a new list item on Enter', () => {
+ cy.get('.ProseMirror').type('{enter}2nd Item')
+
+ cy.get('.ProseMirror').find('li:nth-child(1)').should('contain', 'Example Text')
+
+ cy.get('.ProseMirror').find('li:nth-child(2)').should('contain', '2nd Item')
+ })
+
+ it('should sink the list item on Tab', () => {
+ cy.get('.ProseMirror').type('{enter}').trigger('keydown', { key: 'Tab' })
+
+ cy.get('.ProseMirror').type('2nd Level')
+
+ cy.get('.ProseMirror').find('li:nth-child(1) li').should('contain', '2nd Level')
+ })
+
+ it('should lift the list item on Shift+Tab', () => {
+ cy.get('.ProseMirror')
+ .type('{enter}')
+ .trigger('keydown', { key: 'Tab' })
+ .trigger('keydown', { shiftKey: true, key: 'Tab' })
+
+ cy.get('.ProseMirror').type('1st Level')
+
+ cy.get('.ProseMirror').find('li:nth-child(2)').should('contain', '1st Level')
+ })
+})
diff --git a/demos/src/Nodes/ListItem/React/styles.scss b/demos/src/Nodes/ListItem/React/styles.scss
new file mode 100644
index 00000000..d7d0f5ad
--- /dev/null
+++ b/demos/src/Nodes/ListItem/React/styles.scss
@@ -0,0 +1,11 @@
+/* Basic editor styles */
+.ProseMirror {
+ > * + * {
+ margin-top: 0.75em;
+ }
+
+ ul,
+ ol {
+ padding: 0 1rem;
+ }
+}