diff --git a/static/js/notes.js b/static/js/notes.js
index cf9886439..aa854078c 100644
--- a/static/js/notes.js
+++ b/static/js/notes.js
@@ -1835,6 +1835,9 @@ function _renderNotes() {
+
@@ -2518,6 +2521,85 @@ function _bindCardEvents(body) {
});
});
+ function _startChecklistItemEdit(noteId, idx, span) {
+ if (span.isContentEditable) return;
+ const note = _notes.find(n => n.id === noteId);
+ if (!note || !Array.isArray(note.items) || !note.items[idx]) return;
+
+ span.textContent = note.items[idx].text || '';
+ span.contentEditable = "true";
+ span.spellcheck = false;
+ span.focus();
+
+ const selection = window.getSelection();
+ const range = document.createRange();
+ range.selectNodeContents(span);
+ selection.removeAllRanges();
+ selection.addRange(range);
+
+ const save = () => {
+ if (!span.isContentEditable) return;
+ span.contentEditable = "false";
+ const newText = span.textContent.trim();
+ const oldText = (note.items[idx].text || '').trim();
+
+ if (newText === oldText) {
+ _renderNotes();
+ return;
+ }
+
+ const oldItem = note.items[idx];
+ if (!newText) {
+ note.items.splice(idx, 1);
+ } else {
+ note.items[idx].text = newText;
+ }
+
+ _patchNote(noteId, { items: note.items }).catch(() => {
+ if (!newText) note.items.splice(idx, 0, oldItem);
+ else note.items[idx].text = oldText;
+ _renderNotes();
+ uiModule.showError('Failed to update item');
+ });
+ _renderNotes();
+ };
+
+ const onKeydown = (e) => {
+ if (e.key === 'Enter') {
+ e.preventDefault();
+ save();
+ } else if (e.key === 'Escape') {
+ e.preventDefault();
+ span.contentEditable = "false";
+ _renderNotes();
+ }
+ };
+
+ span.addEventListener('blur', save, { once: true });
+ span.addEventListener('keydown', onKeydown);
+ }
+
+ // Edit a single checklist item (hover Edit button)
+ body.querySelectorAll('.note-checkbox-edit').forEach(btn => {
+ btn.addEventListener('click', (e) => {
+ e.stopPropagation();
+ if (_selectMode) return;
+ const noteId = btn.dataset.noteId;
+ const idx = parseInt(btn.dataset.idx);
+ const span = btn.parentElement.querySelector('.note-check-text');
+ if (span) _startChecklistItemEdit(noteId, idx, span);
+ });
+ });
+
+ // Prevent clicks from toggling the row while actively editing inline
+ body.querySelectorAll('.note-check-text').forEach(span => {
+ span.addEventListener('click', (e) => {
+ if (span.isContentEditable) {
+ e.stopPropagation();
+ }
+ });
+ });
+
// Per-item agent solve (hover button next to the X). Scoped to one todo
// item — uses the note title as context if present, but only the single
// item's text as the work. Mirrors the per-note _agentSolveNote pattern.
diff --git a/static/style.css b/static/style.css
index 3af43307e..99bedacf9 100644
--- a/static/style.css
+++ b/static/style.css
@@ -34117,7 +34117,7 @@ body.notes-mobile-mode.notes-drag-mode .note-card-pin.active {
word-break: break-all;
}
.note-link:hover { opacity: 0.8; }
-.note-checkbox-rm {
+.note-checkbox-edit, .note-checkbox-rm {
flex: 0 0 auto;
background: transparent;
border: none;
@@ -34129,13 +34129,25 @@ body.notes-mobile-mode.notes-drag-mode .note-card-pin.active {
display: flex;
align-items: center;
justify-content: center;
- margin-left: auto;
- margin-right: 0;
+ margin-left: 2px;
transition: opacity 0.12s, background 0.12s, color 0.12s;
}
+.note-checkbox-rm { margin-left: auto; }
+.note-checkbox-edit { margin-left: auto; }
+.note-checkbox:hover .note-checkbox-edit,
.note-checkbox:hover .note-checkbox-rm { opacity: 0.55; }
.note-checkbox-rm:hover { opacity: 1 !important; color: var(--red); background: color-mix(in srgb, var(--red) 12%, transparent); }
+.note-checkbox-edit:hover { opacity: 1 !important; color: var(--accent, var(--blue)); background: color-mix(in srgb, var(--accent, var(--blue)) 12%, transparent); }
+.note-card-selectmode .note-checkbox-edit,
.note-card-selectmode .note-checkbox-rm { display: none; }
+.note-check-text[contenteditable="true"] {
+ background: color-mix(in srgb, var(--fg) 8%, transparent);
+ outline: 1px solid var(--accent, var(--blue));
+ border-radius: 2px;
+ cursor: text;
+ padding: 0 2px;
+ margin: 0 -2px;
+}
.note-check-dot {
width: 16px;
height: 16px;