Connect your toolbar
Start with a Bold button, then understand commands, enabled state and interface updates.
The workspace accepts input. Add a Bold button: select text, click to change it through Core, then reflect its current formatting in the button.
Buttons, shortcuts and application code all call the same Editor commands rather than modifying document JSON themselves.
1. Run an action
editor.chain().focus().toggleBold().run()
focus() returns input focus, toggleBold() changes the current selection, and run() submits the chain. Use the existing selection rather than moving to the end of the document.
Use editor.commands.toggleBold() for an immediate single action; use chain() to combine focus, insertion or formatting.
2. Separate active and disabled state
A button answers two questions: is this text bold, and can Bold run now?
const active = editor.isActive('bold')
const enabled = editor.isEditable && editor.can().toggleBold()
isActive() reads formatting; can() checks execution without changing content. Call editor.setEditable(false) to stop user editing input in the View; disabling controls alone does not stop keyboard editing. Programmatic commands still require application write-permission checks; see commands and transactions.
Word formatting may inherit paragraph styles. Its assembly uses readEffectiveDirectEmphasisState() for effective bold state; the generic model uses isActive('bold'). Match button queries to the installed formatting extension.
3. Refresh controls after changes
Keep one Editor instance and expose only the booleans Vue needs. Subscribe to transaction and remove the same listener when exiting.
editor.on('transaction', refreshToolbar)
// When the component exits:
editor.off('transaction', refreshToolbar)
Implement refreshToolbar to read a small set of formatting and history facts. Do not serialize the whole document with getJSON() on every selection movement. Saving status, file errors and page counts come from their respective workflows.
Where to look in the complete project
workspace.vue owns controls and handlers, session.ts publishes their state, and assembly/ supplies model-specific format queries. Inspect them individually in the reference.
A command's boolean result means it handled the action, not that a file was saved. Next, use the same mechanism to insert custom content. See Editor API for details.