Full document, spreadsheet, slideshow, and diagram tooling
1/**
2 * Tab key support for TipTap docs editor.
3 *
4 * - In lists: Tab indents (sinks), Shift+Tab outdents (lifts)
5 * - In code blocks: Tab inserts a tab character
6 * - In normal paragraphs: Tab inserts 4 spaces
7 */
8
9import { Extension } from '@tiptap/core';
10
11export const TabSupport = Extension.create({
12 name: 'tabSupport',
13
14 addKeyboardShortcuts() {
15 return {
16 Tab: () => {
17 const { editor } = this;
18
19 // In a list? Sink the list item (increase indent)
20 if (editor.isActive('listItem') || editor.isActive('taskItem')) {
21 return editor.chain().focus().sinkListItem('listItem').run()
22 || editor.chain().focus().sinkListItem('taskItem').run();
23 }
24
25 // In a code block? Insert a tab character
26 if (editor.isActive('codeBlock')) {
27 return editor.chain().focus().command(({ tr, state }) => {
28 tr.insertText('\t', state.selection.from, state.selection.to);
29 return true;
30 }).run();
31 }
32
33 // Normal paragraph: insert 4 spaces
34 return editor.chain().focus().command(({ tr, state }) => {
35 tr.insertText(' ', state.selection.from, state.selection.to);
36 return true;
37 }).run();
38 },
39 'Shift-Tab': () => {
40 const { editor } = this;
41
42 // In a list? Lift the list item (decrease indent)
43 if (editor.isActive('listItem') || editor.isActive('taskItem')) {
44 return editor.chain().focus().liftListItem('listItem').run()
45 || editor.chain().focus().liftListItem('taskItem').run();
46 }
47
48 // In code block or normal text: do nothing special
49 return false;
50 },
51 };
52 },
53});