Components

Tiptap Editor ​

TiptapEditor provides a rich-text editing surface with a configurable toolbar and structured JSON output.

Basic Usage ​

Use a focused toolbar for the default writing experience and keep the editor controlled so value changes stay in sync with the surrounding form.

Expanded Toolbar ​

Use a broader toolbar when the editor is the primary authoring surface and needs headings, tables, links, code, and undo or redo support.

Available Toolbar Controls ​

The default toolbar contains bold and italic. Set buttons to a comma-separated list when you only need standalone controls:

html
<pk-tiptap-editor
    buttons="bold,italic,underline,small-caps,link,undo,redo"
></pk-tiptap-editor>

All built-in control IDs are listed below. IDs are case-sensitive.

IDAction
boldBold
italicItalic
underlineUnderline
strikethroughStrikethrough
subscriptSubscript
superscriptSuperscript
small-capsSmall caps using the constrained textStyle.fontVariantCaps attribute
font-familyFont family menu
font-sizeFont size menu
text-colorText and background color menus
line-heightLine height menu
unordered-listBulleted list
ordered-listNumbered list
blockquoteBlock quote
highlightHighlight
codeInline code
code-blockCode block
hrHorizontal rule
line-breakHard line break
h1–h6Heading levels 1–6
align-leftAlign left
align-centerAlign centre
align-rightAlign right
align-justifyJustify
clear-formatClear block formatting and marks
undoUndo
redoRedo
linkOpen the link editor
tableInsert a 3 × 3 table with a header row

paragraph is also available inside a custom toolbar group. It changes the current block to body text, but is not a standalone buttons ID.

Keep link as a standalone toolbar control because it opens its own menu and dialog. Keep font-family, font-size, text-color, and line-height standalone as well because each opens its own value menu. variableTag is a reserved integration ID: the base web component removes it from the rendered toolbar so consuming products can supply their variable picker through toolbar-end. Unknown IDs are ignored unless they have been registered through the TipTap extensibility API.

TextStyle Controls ​

The TextStyle controls use TipTap's official FontFamily, FontSize, Color, BackgroundColor, and LineHeight extensions. Small caps adds one constrained attribute to the same textStyle mark, so all six styles can coexist without creating additional marks. These controls are available to every editor but remain opt-in through buttons or toolbar.

Set textStyleOptions as a property—or text-style-options as JSON in HTML—to replace any default option family:

js
const editor = document.querySelector('pk-tiptap-editor');

editor.textStyleOptions = {
    fontFamilies: [
        { label: 'Default font', value: null },
        { label: 'Brand Sans', value: 'Brand Sans, sans-serif' },
        { label: 'Georgia', value: 'Georgia, serif' },
    ],
    fontSizes: [
        { label: 'Default', value: null },
        { label: 'Body', value: '16px' },
        { label: 'Large', value: '24px' },
    ],
};

Available option-family keys are fontFamilies, fontSizes, textColors, backgroundColors, and lineHeights. Each entry has a label and a CSS value; use null for the reset/default entry. Supplying one family leaves the other default families unchanged.

Grouped Toolbar ​

The toolbar attribute accepts a JSON array of buttons, separators ("|"), and group objects. Groups use a preset (or custom items) to open a dropdown cluster.

Built-in presets:

PresetMenu contents
formattingParagraph, heading levels, blockquote, and code block
headingsHeading levels only
listsUnordered and ordered list
alignLeft, center, right, and justify

formatting and headings accept optional headingLevels (e.g. [1, 2, 3, 4]). When omitted, levels default to 1–4.

Custom groups are supported through items. Items can be any built-in control ID, paragraph, a separator ("|" or "separator"), or a custom control ID that was registered before the editor mounted. Use either preset or items; when a non-empty items list is present, it defines the menu contents.

js
const editor = document.querySelector('pk-tiptap-editor');

if (editor) {
    editor.toolbar = [
        {
            type: 'group',
            label: 'Text style',
            icon: 'bold',
            items: ['paragraph', '|', 'bold', 'italic', 'underline', 'small-caps'],
        },
        '|',
        {
            type: 'group',
            label: 'Insert',
            icon: 'table',
            items: ['table', 'hr', 'code-block'],
        },
        'link',
        'undo',
        'redo',
    ];
}

A group accepts label, icon, and items, or preset with optional headingLevels. Groups can be mixed with standalone buttons and top-level separators in the same toolbar.

Inside the Craft control panel, the link menu can open Craft's element selector for entries, assets, categories, or another element type. Include link in the toolbar, pass the selector configuration as JSON through link-options, and set link-selector-storage-key-prefix to a stable value for the editor:

html
<pk-tiptap-editor
    buttons="bold,italic,link"
    link-options='{"elementSiteId":1,"linkToEntry":{"elementType":"craft\\elements\\Entry","refHandle":"entry"}}'
    link-selector-storage-key-prefix="acme.article-body"
></pk-tiptap-editor>

The named object form supports linkToEntry, linkToAsset, and linkToCategory. Each option requires elementType, the fully qualified Craft element class, and refHandle, the handle written into the selected element's reference fragment. You can also provide sources to limit the available element sources and criteria to apply element-query criteria. Set the top-level elementSiteId when the selector should open for a particular site.

Use the array form when you need custom menu labels or another element type. Each item uses the same fields and adds optionTitle:

html
<pk-tiptap-editor
    buttons="link"
    link-options='[{"optionTitle":"Link to a product","elementType":"craft\\elements\\Entry","refHandle":"entry","sources":["section:NEWS_SECTION_UID"],"criteria":{"status":"enabled"}}]'
    link-selector-storage-key-prefix="acme.product-description"
></pk-tiptap-editor>

link-selector-storage-key-prefix is required whenever element link options are configured. Plugin Kit appends the element type to this prefix for Craft's selector storage key; choosing an element link throws an error when the prefix is missing. The selector also requires Craft's window.Craft.createElementSelectorModal API, so element link options are intended for control-panel pages where Craft has loaded that API.

Extending TipTap ​

Plugin Kit supports application-level registration of TipTap nodes, marks, behaviour extensions, and stock-toolbar-compatible controls. Registration has schema and server-rendering implications, so it is documented separately in Extending TipTap.

Variable Tag Indicators ​

Variable tags display the applied transform as a badge and an orange corner when a default value is set. Pass variableTransformerRegistry, grouped by value type, to display transform names. Unknown transforms display their saved ID.

API ​

Slots ​

NameDescription
toolbarReplace the entire default toolbar (opt-in via light-DOM presence).
toolbar-endAppend controls after stock toolbar buttons (same flex gap).

Attributes & Properties ​

NameDescription
buttonsFlat toolbar button list. HTML uses a comma-separated attribute; React may pass a string[]. Named buttons (not buttonsAttr) so React can set the property — a getter-only buttons previously threw on assign.
Type string | string[]
Default bold,italic
customError custom-errorCustom validation message; also settable via setCustomValidity().
Type string | null
Default null
defaultValue valueType string | null
Default []
disabledDisables the control and excludes it from constraint validation.
Type boolean
Default false
invalidType boolean
Default false
invalidContentMessage invalid-content-messageType string
linkOptions link-optionsJSON configuration for Craft entry, asset, category, or custom element links.
Type string | null
Default null
linkSelectorStorageKeyPrefix link-selector-storage-key-prefixRequired storage-key prefix when Craft element link options are enabled.
Type string | undefined
nameName submitted with form data.
Type string | null
Default null
placeholderType string
readonlyType boolean
Default false
requiredMarks the control as required for form submission.
Type boolean
Default false
rowsType number
Default 4
textStyleOptions text-style-optionsValues shown by the optional TextStyle toolbar controls.
Type TiptapTextStyleToolbarConfig | null
Default null
toolbarStructured toolbar config — JSON string attribute, or a node array from React.
Type string | ToolbarNode[] | null
Default null
toolbarTooltips toolbar-tooltipsShow pk-tooltip hints on toolbar buttons (default: on).
Type boolean
Default true
valueDocument JSON string. Also accepts a TipTap node array (common from React) and serializes it — arrays previously bypassed JSON.parse and mounted empty.
Type string
variableTagConfigureFormie / React configure bridge — called when a chip is activated for editing. Prefer this over listening for pk-variable-tag-configure from React.
Type ((detail: import('./variable-tag-node-view.js').PkVariableTagConfigureDetail) => void) | null
Default null
variableTransformerRegistryTransform names displayed as badges on configured variable tags.
Type PkVariableTransformerRegistry
Default {}

Methods ​

NameDescription
checkValidity()Runs constraint validation without showing the browser UI.
reportValidity()Runs constraint validation and shows the browser UI when invalid.
resetValidity()Clears custom errors and re-syncs validity state.
setCustomValidity(message: string)Sets or clears a custom validation message.

Events ​

NameDescription
change—
input—
pk-change—

Custom States ​

NameDescriptionCSS selector
disabledThe control is disabled.:state(disabled)
invalidThe control currently fails constraint validation.:state(invalid)
optionalThe control is not required.:state(optional)
requiredThe control is required.:state(required)
user-invalidInvalid after the user has interacted with the control.:state(user-invalid)
user-validValid after the user has interacted with the control.:state(user-valid)
validThe control currently passes constraint validation.:state(valid)

Dependencies ​

This component registers the following elements when it loads.

NameDescription
pk-button—
pk-checkbox—
pk-dialog—
pk-dropdown-item—
pk-dropdown-label—
pk-dropdown-menu—
pk-dropdown-separator—
pk-field—
pk-input—
pk-tooltip—
Edit this page
Last updated: Oct 21, 2026, 10:24 AM