Overview
The formatIndent inputType is triggered when the user increases indentation of selected paragraphs (typically via Tab or toolbar button). The browser increases the left margin or padding of the affected elements.
Basic Behavior
Scenario: Paragraph selected
Before (Paragraph selected)
HTML:
<p>This is a paragraph.</p>
After formatIndent
HTML:
<p style="margin-left: 40px;">This is a paragraph.</p>
Left margin increased (indented)
Browser-Specific Behavior
Chrome/Edge
- Applies
margin-leftorpadding-leftvia inline style - Increment amount varies (typically 40px)
Firefox
- Similar behavior to Chrome
- May use different increment values
Safari
- Indentation behavior may differ
- May use different CSS properties
Editor-Specific Handling
Different editor frameworks handle indentation differently. Here's how major editors implement formatIndent:
Slate.js
Indentation
Slate applies indentation as a block property:
import { Editor, Transforms, Element } from 'slate';
element.addEventListener('beforeinput', (e) => {
if (e.inputType === 'formatIndent') {
e.preventDefault();
// Get current indent level
const [match] = Editor.nodes(editor, {
match: n => Element.isElement(n) && Editor.isBlock(editor, n),
});
const currentIndent = match?.[0]?.indent || 0;
// Increase indent
Transforms.setNodes(editor, {
indent: currentIndent + 1,
}, {
match: n => Element.isElement(n) && Editor.isBlock(editor, n),
});
}
});
- Block property: Indentation is stored as a property on block elements.
- Incremental: Increases indent level by 1 each time.
ProseMirror
Indentation
ProseMirror uses block attribute:
view.dom.addEventListener('beforeinput', (e) => {
if (e.inputType === 'formatIndent') {
e.preventDefault();
const { state, dispatch } = view;
const { $from } = state.selection;
// Get current indent
const currentIndent = $from.node(-1)?.attrs.indent || 0;
// Increase indent
const tr = state.tr.setNodeMarkup($from.before(-1), null, {
...$from.node(-1).attrs,
indent: currentIndent + 1,
});
dispatch(tr);
}
});
- Block attribute: Indentation is stored as an attribute on block nodes.
Draft.js
Indentation
Draft.js uses block-level styles:
import { EditorState, RichUtils } from 'draft-js';
function handleIndent(editorState) {
// Draft.js may use block-level styles or custom block types for indentation
return RichUtils.onTab({ preventDefault: () => {} }, editorState, 4);
}
element.addEventListener('beforeinput', (e) => {
if (e.inputType === 'formatIndent') {
e.preventDefault();
const newState = handleIndent(editorState);
setEditorState(newState);
}
});
- Tab handling: Uses
RichUtils.onTab()for indentation.