Rendering and NodeViews
Customize BlockSlot and InlineSlot as ordinary Tiptap Node extensions. Pass them to Slot; it retains the commands, indexing and validation behavior.
HTML attributes
Slot.configure({
blockSlot: BlockSlot.configure({ HTMLAttributes: { class: 'block-field' } }),
inlineSlot: InlineSlot.configure({ HTMLAttributes: { class: 'inline-field' } }),
})HTMLAttributes(Record<string, string>): Outer-element attributes. Default:{}.- Required
data-slot-*attributes take precedence over custom attributes. - The package supplies no toolbar, borders or colors. Style the wrapper in your application.
Serialized attributes
| Attribute | Value | Purpose |
|---|---|---|
data-slot-kind | 'block' or 'inline' | Identifies the Node kind. |
data-slot-id | Slot ID | Preserves identity. |
data-slot-config | Escaped JSON | Preserves embedded configuration. |
Default wrappers are div for block Slots and span for inline Slots. The accessible name uses config.label, falling back to the ID.
View-only attributes
| Attribute | Value | Purpose |
|---|---|---|
data-slot-empty | 'true' or 'false' | Styles empty fields. |
data-slot-active | 'true' or 'false' | Styles the active field. |
data-slot-placeholder | Configured placeholder | Supplies text when the field is empty. |
These attributes and placeholder presentation are not persisted in JSON, serialized HTML or clipboard content.
Custom NodeViews
const CustomBlockSlot = BlockSlot.extend({
addNodeView() {
return ReactNodeViewRenderer(MySlotView)
},
})
Slot.configure({ blockSlot: CustomBlockSlot })ReactNodeViewRenderer comes from @tiptap/react. JavaScript and Vue use their standard Tiptap NodeView APIs.
Contract
- Preserve the canonical Node name,
id/configattributes, content expression and defining/isolating behavior. - Register customized instances through
Slotonly. Instances are fixed at editor construction. - Provide one editable
contentDOM, or the framework'sNodeViewContentequivalent. - Let Tiptap render document content. Do not render a second copy from
node.content. - Mark controls and labels noneditable. Make edits through commands.
- Inline wrappers and content containers must use inline-compatible elements, such as
span. - Custom views own visible labels and placeholders. Default placeholder text is not added to custom views.
- Preserve selection, nested editing, IME and caret behavior. Do not swallow required content events or mutations.
See Tiptap NodeViews for the framework APIs.
Validation and permission updates
Use subscribeSlotViewUpdates to refresh UI when attributes alone do not change.
const unsubscribe = subscribeSlotViewUpdates({ editor, onUpdate: refresh })
// When disposing the view:
unsubscribe()- Read
editor.storage.slotfor the snapshot, active field and validation state. - Use
getPos()and entry positions when imported IDs are ambiguous. - Use
editor.can()for command availability and Content Protection queries for explanations. - Render only current validation results. Apply read permissions before displaying messages or content.
- Mounting a view does not start validation.
HTML serialization
addNodeViewcontrols the editor UI;renderHTMLcontrols exported HTML.- Custom
renderHTMLmust preserve the three serialized attributes and one content hole. - Generate attributes from the current Node with proper escaping.
- Custom
parseHTMLmust preserve IDs and complete configuration. Keep the default parser as a fallback. - Malformed configuration JSON in HTML becomes
config: nulland produces a validation issue. - UI controls, placeholders and validation messages belong to the NodeView, not exported content.
Redacted content
Content Protection replaces concealed Nodes with its own redaction renderer. Their original Slot NodeViews do not remain mounted.
A readable parent may contain concealed children. Its custom controls must not display those children's text, attributes or JSON elsewhere. The complete source document remains in client memory.