Tiptap Focus extension: outline the paragraph being edited

Use Tiptap's Focus extension to add a CSS class to focused document nodes, then style that class in the editor. Configure mode: 'deepest' when a nested paragraph should receive the cue instead of every containing node. This is the visual Focus extension; editor.commands.focus() separately moves input focus back to the editor. Focus extension · Focus command

In a long procedure containing nested bullet lists, an author may need to see which instruction paragraph currently holds the cursor. A light outline can identify that paragraph without adding a permanent highlight to the exported procedure. Readers of the finished document should receive the instructions without the author's current editing cue.

Add the extension and a scoped style

For an existing Tiptap 3 editor, add this configured extension to its current setup:

import { Focus } from '@tiptap/extensions';

const activeInstruction = Focus.configure({
  className: 'active-instruction',
  mode: 'deepest'
});

Keep the existing document and list extensions. This fragment adds a visual behavior; it does not initialize the editor or introduce list nodes. Current Tiptap 3 documentation imports Focus from @tiptap/extensions; check the version in your project before copying an older standalone-package import.

Use the actual wrapper for your procedure editor in the stylesheet:

.procedure-editor .tiptap .active-instruction {
  outline: 2px solid #466b80;
  outline-offset: 3px;
  border-radius: 3px;
}

The selector assumes .procedure-editor wraps the Tiptap editing surface. Adjust it to match your own markup. An outline avoids adding border width to the paragraph's layout. Check nearby content and clipping around the editing container, since an outward outline needs visible space.

Choose the nesting rule for the actual document

The documented modes are all, shallowest, and deepest; all is the default. A cursor inside a paragraph inside a list item gives those choices different containing nodes to work with. deepest is appropriate when the paragraph is the useful editing unit. A document with a custom node view may need a different choice and its own styling.

Open a nested list in your application, put the cursor in a child instruction, and inspect which element receives active-instruction. Change the mode deliberately if the intended unit is the entire enclosing item. Increasing selector specificity cannot change which document nodes the extension chooses.

Keep this cue distinct from a stored text highlight. Highlight marks express content the author wants to retain; a focused-node outline follows the editing location. A BubbleMenu supplies contextual controls and has a different selection and visibility policy.

Check editing and exported content separately

Move between two paragraphs using both the pointer and keyboard. Confirm the cue follows the intended node and that a nested item does not produce confusing overlapping outlines. Move focus outside the editor and check its actual blur behavior in the surrounding form.

Inspect editor.getHTML() and the saved reader document. The Focus decoration is an editor presentation cue, so the exported procedure should not acquire an active-instruction content class from this extension. Avoid saving the live editor DOM as the document. Finish by reading the procedure in its ordinary reader view, where no step should look selected merely because it held the author's cursor before saving.

Keep reading