Getting Started

Load the script, drop a container element in your HTML, then call TiptapEditor.createEditor().

HTML
<script src="https://artworx-tiptap-editor.pages.dev/editor.js"></script>

<div id="editor"></div>
JavaScript
const editor = TiptapEditor.createEditor(
  document.getElementById('editor'),
  {
    content:     '<p>Hello world!</p>',
    placeholder: 'Start writing…',
    onChange:    (html) => console.log(html),
  }
)

// Instance methods
editor.getHTML()            // → HTML string
editor.setContent(html)     // replace content
editor.setEditable(false)   // toggle read-only
editor.destroy()            // cleanup

Live result:

Full Toolbar

Default setup — all buttons enabled. Fires onChange on every keystroke.

HTML output

Custom Toolbar

Using toolbar: ['bold', 'italic', 'underline', 'bulletList', 'orderedList', 'link'] — only the specified buttons, in that order.

Simple Toolbar

Using simpleToolbar: true — hides headings, blockquote, code block, and horizontal rule. Good for comments or short-form content.

Read-only

Using editable: false — toolbar is hidden, content is not editable.

Dark Theme

Using wrapperClass: 'dark-theme' and CSS variable overrides to restyle the editor per-instance.

Custom Theme

Override just a few --te-* CSS variables via wrapperClass to rebrand the editor. Only 6 variables changed here:

CSS
.purple-theme.tiptap-editor-wrapper {
  --te-accent: #605CA8;
  --te-accent-hover: #4e4a8f;
  --te-ring: #9b97d3;
  --te-ring-shadow: rgba(96, 92, 168, 0.15);
  --te-btn-active-bg: #ededf7;
  --te-btn-active-hover-bg: #dddcf0;
}

Live result:

Custom Toolbar Buttons

Pass { custom: true, name, icon, title, command } objects inside the toolbar array to inject your own buttons anywhere. Buttons with no command render as non-interactive <span> display widgets. When isActive returns a string, the element's content is updated live on every transaction.

JavaScript
const imgIcon = '<svg xmlns="http://www.w3.org/2000/svg" width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><rect width="18" height="18" x="3" y="3" rx="2" ry="2"/><circle cx="9" cy="9" r="2"/><path d="m21 15-3.086-3.086a2 2 0 0 0-2.828 0L6 21"/></svg>'

TiptapEditor.createEditor(el, {
  toolbar: [
    'bold', 'italic', 'link',
    {
      custom:   true,
      name:     'insert-image',
      icon:     imgIcon,
      title:    'Insert Image',
      group:    'extra',
      command:  (editor) => {
        const url = window.prompt('Image URL')
        if (url) editor.chain().focus().insertContent(
          `<img src="${url}" alt="" style="max-width:100%">`
        ).run()
      },
    },
    {
      custom:   true,
      name:     'word-count',
      icon:     'Words: 0',
      title:    '',
      group:    'extra',
      className: 'tiptap-wordcount',
      // no command → renders as <span>, not <button>
      isActive: (editor) => {
        const text = editor.getText().trim()
        const count = text === '' ? 0 : text.split(/\s+/).length
        return `Words: ${count}`  // string → updates innerHTML
      },
    },
  ],
})

Live result:

Fixed Toolbar

Using fixedToolbar: true — the toolbar sticks to the top of the viewport as you scroll down the page.