From 749bcc361dffc0ccf85421148d0957f1114def9a Mon Sep 17 00:00:00 2001 From: sarah <129242944+sarah-inkeep@users.noreply.github.com> Date: Thu, 25 Jun 2026 20:29:49 -0700 Subject: [PATCH] Fix/task checkbox disabled after editable (#2166) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * fix(core): keep task-item checkbox disabled state in sync with editability The ListItem NodeView set checkbox.disabled once at creation from editor.isEditable. A pure setEditable() flip updates view.editable without a doc change, so ProseMirror never calls the NodeView's update() — a checkbox created while the editor was read-only (e.g. seed content injected before the hero editor goes live) stayed disabled forever, so it couldn't be checked. Sync disabled with editor.isEditable on the 'update' event (emitted by setEditable) and in update(), and remove the listener in destroy(). * chore: changeset for task-checkbox editability fix --------- GitOrigin-RevId: e8327374a503cd677f82d5665ea2bf6598d07e5c --- .../task-checkbox-disabled-after-editable.md | 5 +++++ packages/core/src/extensions/list.ts | 14 ++++++++++---- 2 files changed, 15 insertions(+), 4 deletions(-) create mode 100644 .changeset/task-checkbox-disabled-after-editable.md diff --git a/.changeset/task-checkbox-disabled-after-editable.md b/.changeset/task-checkbox-disabled-after-editable.md new file mode 100644 index 00000000..c55c24e1 --- /dev/null +++ b/.changeset/task-checkbox-disabled-after-editable.md @@ -0,0 +1,5 @@ +--- +"@inkeep/open-knowledge-core": patch +--- + +Task-list checkboxes now stay clickable when an editor transitions from read-only to editable. The list-item NodeView set the checkbox's `disabled` state once at creation from `editor.isEditable`, but a `setEditable()` flip updates the view's editable flag without a document change, so ProseMirror never re-renders the NodeView and the stale `disabled` was never cleared. A checkbox created while the editor was read-only (for example, content loaded before the editor goes live) stayed permanently uncheckable. The NodeView now keeps `disabled` in sync with editability via the editor's `update` event (which `setEditable()` emits) and on every NodeView update. diff --git a/packages/core/src/extensions/list.ts b/packages/core/src/extensions/list.ts index 6d3b483a..ffc5f9ed 100644 --- a/packages/core/src/extensions/list.ts +++ b/packages/core/src/extensions/list.ts @@ -329,6 +329,10 @@ export const ListItemNode = Node.create({ let checkbox: HTMLInputElement | null = null; const contentDiv = document.createElement('div'); + const syncDisabled = () => { + if (checkbox) checkbox.disabled = !editor.isEditable; + }; + if (node.attrs.checked !== null) { checkboxLabel = document.createElement('label'); checkboxLabel.contentEditable = 'false'; @@ -336,10 +340,8 @@ export const ListItemNode = Node.create({ checkbox = document.createElement('input'); checkbox.type = 'checkbox'; checkbox.checked = !!node.attrs.checked; - - if (!editor.isEditable) { - checkbox.disabled = true; - } + syncDisabled(); + editor.on('update', syncDisabled); checkbox.addEventListener('change', () => { const pos = getPos(); @@ -368,11 +370,15 @@ export const ListItemNode = Node.create({ } if (checkbox && updatedNode.attrs.checked !== null) { checkbox.checked = !!updatedNode.attrs.checked; + checkbox.disabled = !editor.isEditable; li.setAttribute('data-checked', String(!!updatedNode.attrs.checked)); } node = updatedNode; return true; }, + destroy() { + editor.off('update', syncDisabled); + }, }; }; },