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:
<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.
| ID | Action |
|---|---|
bold | Bold |
italic | Italic |
underline | Underline |
strikethrough | Strikethrough |
subscript | Subscript |
superscript | Superscript |
small-caps | Small caps using the constrained textStyle.fontVariantCaps attribute |
font-family | Font family menu |
font-size | Font size menu |
text-color | Text and background color menus |
line-height | Line height menu |
unordered-list | Bulleted list |
ordered-list | Numbered list |
blockquote | Block quote |
highlight | Highlight |
code | Inline code |
code-block | Code block |
hr | Horizontal rule |
line-break | Hard line break |
h1–h6 | Heading levels 1–6 |
align-left | Align left |
align-center | Align centre |
align-right | Align right |
align-justify | Justify |
clear-format | Clear block formatting and marks |
undo | Undo |
redo | Redo |
link | Open the link editor |
table | Insert 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:
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:
| Preset | Menu contents |
|---|---|
formatting | Paragraph, heading levels, blockquote, and code block |
headings | Heading levels only |
lists | Unordered and ordered list |
align | Left, 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.
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.
Craft Element Links
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:
<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:
<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
| Name | Description |
|---|---|
toolbar | Replace the entire default toolbar (opt-in via light-DOM presence). |
toolbar-end | Append controls after stock toolbar buttons (same flex gap). |
Attributes & Properties
| Name | Description |
|---|---|
buttons | Flat 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-error | Custom validation message; also settable via setCustomValidity().Type string | nullDefault null |
defaultValue value | Type string | nullDefault [] |
disabled | Disables the control and excludes it from constraint validation. Type booleanDefault false |
invalid | Type booleanDefault false |
invalidContentMessage invalid-content-message | Type string |
linkOptions link-options | JSON configuration for Craft entry, asset, category, or custom element links. Type string | nullDefault null |
linkSelectorStorageKeyPrefix link-selector-storage-key-prefix | Required storage-key prefix when Craft element link options are enabled. Type string | undefined |
name | Name submitted with form data. Type string | nullDefault null |
placeholder | Type string |
readonly | Type booleanDefault false |
required | Marks the control as required for form submission. Type booleanDefault false |
rows | Type numberDefault 4 |
textStyleOptions text-style-options | Values shown by the optional TextStyle toolbar controls. Type TiptapTextStyleToolbarConfig | nullDefault null |
toolbar | Structured toolbar config — JSON string attribute, or a node array from React. Type string | ToolbarNode[] | nullDefault null |
toolbarTooltips toolbar-tooltips | Show pk-tooltip hints on toolbar buttons (default: on).Type booleanDefault true |
value | Document JSON string. Also accepts a TipTap node array (common from React) and serializes it — arrays previously bypassed JSON.parse and mounted empty. Type string |
variableTagConfigure | Formie / 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) | nullDefault null |
variableTransformerRegistry | Transform names displayed as badges on configured variable tags. Type PkVariableTransformerRegistryDefault {} |
Methods
| Name | Description |
|---|---|
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
| Name | Description |
|---|---|
change | — |
input | — |
pk-change | — |
Custom States
| Name | Description | CSS selector |
|---|---|---|
disabled | The control is disabled. | :state(disabled) |
invalid | The control currently fails constraint validation. | :state(invalid) |
optional | The control is not required. | :state(optional) |
required | The control is required. | :state(required) |
user-invalid | Invalid after the user has interacted with the control. | :state(user-invalid) |
user-valid | Valid after the user has interacted with the control. | :state(user-valid) |
valid | The control currently passes constraint validation. | :state(valid) |
Dependencies
This component registers the following elements when it loads.
| Name | Description |
|---|---|
pk-button | — |
pk-checkbox | — |
pk-dialog | — |
pk-dropdown-item | — |
pk-dropdown-label | — |
pk-dropdown-menu | — |
pk-dropdown-separator | — |
pk-field | — |
pk-input | — |
pk-tooltip | — |