Skip to content

feat: inline comments - #8901

Merged
mejo- merged 47 commits into
mainfrom
feat/comments
Aug 10, 2026
Merged

feat: inline comments#8901
mejo- merged 47 commits into
mainfrom
feat/comments

Conversation

@mejo-

@mejo- mejo- commented Jul 22, 2026

Copy link
Copy Markdown
Member

📝 Summary

This PR implement inline point-anchor comments as discussed in #185.

  • Comments can be inserted via toolbar submenu, by typing [?] or by pressing Ctrl-Alt-M
  • A superscript chat bubble icon (💬) marks the comment anchor in the text. Clicking it opens the comment bubble
  • Inside the comment bubble, one can add, edit and remove replies
  • Comments and footnotes can be hidden to improve legibility via "Hide annotations" in the toolbar submenu
  • Resolves: Inline comments #185

Markdown representation

Comments are stored using the footnote syntax already supported by Text, with a comment- prefix to distinguish them from regular footnotes:

The quick[^comment-1] brown fox.

[^comment-1]:
    - @[jane](mention://user/jane) *(2026-05-21T10:30Z)*
      Is "quick" the right word here?
    - @[bob](mention://user/bob) *(2026-05-21T12:45Z)*
      I think "fast" is more accurate.

Existing Markdown editors with footnote support (Obsidian, Ghostwriter) render the comment definitions as footnotes and make them accessible.

🖼️ Screenshots

Toolbar submenu Comment bubble Entering first comment reply Editing a reply
image grafik grafik grafik

🖼️ Screencast

recording

🚧 TODO

  • Regression: Undo is now always disabled in toolbar
  • Would be great if adding/editing/deleting replies could be undoable as well edit: turns out it already is 🎉
  • Support to mention users in comments
  • Optionally replace NcRichContenteditable with a stripped-down Text editor for editing comments and replies

🏁 Checklist

  • Code is properly formatted (npm run lint / npm run stylelint / composer run cs:check)
  • Sign-off message is added to all commits
  • Tests (unit, integration and/or end-to-end) passing and the changes are covered with tests
  • Documentation (README or documentation) has been updated or is not required

🤖 AI (if applicable)

  • The content of this PR was partly generated using AI tools
  • The AI-generated content was reviewed, comprehended and tested by a human

@mejo-
mejo- requested a review from marcoambrosini July 22, 2026 15:43
@mejo- mejo- self-assigned this Jul 22, 2026
@mejo- mejo- added the enhancement New feature or request label Jul 22, 2026
@github-project-automation github-project-automation Bot moved this to 🧭 Planning evaluation (don't pick) in 📝 Productivity team Jul 22, 2026
@mejo- mejo- moved this from 🧭 Planning evaluation (don't pick) to 🏗️ In progress in 📝 Productivity team Jul 22, 2026
@mejo-
mejo- force-pushed the feat/comments branch 3 times, most recently from 0ecbdff to 8eda11e Compare July 23, 2026 08:28
Comment thread src/components/Comment/CommentBubbleView.vue Outdated
@silverkszlo

This comment was marked as outdated.

Comment thread src/nodes/Comment.ts Outdated
@silverkszlo

This comment was marked as outdated.

@silverkszlo

Copy link
Copy Markdown
Collaborator

When being a guest, I can not edit previous comments before I enter a guestname, but I can delete them. Is that intentional?

Screenshot from 2026-07-28 13-07-46

@mejo- mejo- moved this from 🏗️ In progress to 👀 In review in 📝 Productivity team Jul 30, 2026
@mejo-

mejo- commented Jul 30, 2026

Copy link
Copy Markdown
Member Author

the two close-icons get very close to each other, when there is multiple comments

Good catch. I fixed this by switching to placement: 'left-start' for the floating-ui bubble. It's cleaner anyway in my opinion.

Adding a very long comment breaks it and one also can not scroll down inside the comment bubble anymore. Maybe it would make sense to set a max number for characters?

Another good catch. Fixed by setting a max-height for the multiline input field.

When being a guest, I can not edit previous comments before I enter a guestname, but I can delete them. Is that intentional?

Indeed, that's inconsistent. I changed this now that deleting is only possible after adding a guest name as well for consistent UX.

I also did the following:

  • Visually highlight the reference of the currently open comment bubble.
  • Add navigation buttons to comment bubble to jump to previous/next comment.
  • Improve keyboard navigation:
    • allow to navigate to references via tab
    • open comment bubble on Enter/Space
    • close comment bubble on Esc
    • place cursor in editor content after reference after closing comment bubble via Esc or button

@mejo-
mejo- requested a review from silverkszlo July 30, 2026 13:15

@jancborchardt jancborchardt left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Very cool! Some first feedback:

  • Showing/hiding annotations changes the text flow a little bit, which makes things look unstable/brittle. That might be because the comment emoji is aligned a bit to the top? It’s fine if it’s vertically centered, it would be more important for the text not to move vertically. :)
  • The comment field is quite large / high, which makes it a bit massive and imposing. It would be ok to reduce it to the height of 3.5 lines of text, or even a single line if we use autosize.
  • The "Edit comment" and "Delete comment" actions can go into a 3-dot action menu. Then they can have proper text and are not so in-your-face.
  • A quick animation moving the comment field down when sending the comment would be nice. Better than an interface jump
  • Right now it is only possible to show a single comment thread, right? Other solutions make it possible to view all comments at the same time, which is especially useful if there are multiple and not really many replies going on.

@mejo-

mejo- commented Jul 30, 2026

Copy link
Copy Markdown
Member Author

Right now it is only possible to show a single comment thread, right? Other solutions make it possible to view all comments at the same time, which is especially useful if there are multiple and not really many replies going on.

I would like to keep this for a follow-up, as I have to say I find it quite confusing how others display all the comments per default and I think we should think this through properly.

All other comments addressed @jancborchardt ☺️

@mejo-
mejo- requested a review from jancborchardt July 30, 2026 15:13
@mejo-
mejo- force-pushed the feat/comments branch 2 times, most recently from 04b5da4 to 8677de6 Compare August 3, 2026 11:11
Comment thread src/components/Menu/utils.js Outdated
function isDisabled(actionEntry, editor) {
return actionEntry.action && !actionEntry.action(editor.can(), editor)
return (actionEntry.action && !actionEntry.action(editor.can(), editor))
|| (actionEntry.isAnnotation && annotationsHidden.value)

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

minor nitpick:
I don't like this annotation specific logic in the generic menu handler.

I think the check could be moved into the action function of both footnote and comment buttons. But then I am not sure if it wouldn't be better to make annotationsHidden a part of the editor itself. That way one could also prevent creating annotations with keyboard shortcuts, when they are hidden.

@mejo- mejo- Aug 10, 2026

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I agree and I had a similar sentiment regarding where to track the state of hiding annotations. I moved this to a dedicated editor extension now. It was not an easy one, but I think I found a good solution. Curious what you think: 77bfff6

Comment thread src/components/Comment/CommentBubbleView.vue Outdated
mejo- added 12 commits August 10, 2026 14:58
This is not technically necessary but creates a more consistent user
experience, as all editing actions are only available after setting
a name now.

Signed-off-by: Jonas <jonas@freesources.org>
Use a NodeView in commentReference to allow adding a click handler.
Use a button element instead of link in there to make the reference
accessible via tab navigation.

Signed-off-by: Jonas <jonas@freesources.org>
Assisted-by: OpenCode:claude-fable-5
Signed-off-by: Jonas <jonas@freesources.org>
Assisted-by: OpenCode:claude-fable-5
Allows to insert a comment with a straight-forward keyboard flow:

1. Insert comment via Ctrl-Alt-M
2. Type comment and submit via Ctrl-Enter
3. Close bubble via Esc
4. Continue typing in document

Signed-off-by: Jonas <jonas@freesources.org>
Assisted-by: OpenCode:claude-fable-5
Also ensures guest name is reactive everywhere, regardless of whether it
got set via comment bubble or guest name dialog.

Signed-off-by: Jonas <jonas@freesources.org>
Assisted-by: OpenCode:claude-fable-5
Signed-off-by: Jonas <jonas@freesources.org>
Signed-off-by: Jonas <jonas@freesources.org>
Assisted-by: OpenCode:claude-fable-5
Signed-off-by: Jonas <jonas@freesources.org>
Signed-off-by: Jonas <jonas@freesources.org>
Assisted-by: OpenCode:claude-fable-5
Signed-off-by: Jonas <jonas@freesources.org>
Test idempotence via markdownThroughEditor round-trip for different
unexpected/broken comment Markdown syntax.

Signed-off-by: Jonas <jonas@freesources.org>
Signed-off-by: Jonas <jonas@freesources.org>
@mejo-

mejo- commented Aug 10, 2026

Copy link
Copy Markdown
Member Author

@mejo- thanks! :) Of course fine to have it in a follow-up. But I’d say it’s definitely very important, as long comment-threads are not something very common. And if you have to go through a lot of small feedback / grammar fixes in one document, it gets cumbersome if you have to manually select the comments.

@jancborchardt in general I agree. Just a short addition: there's navigation buttons to navigate to previous/next comment in the comments bubble, that should help a bit with it.

Comment thread src/components/Comment/CommentBubbleView.vue Outdated
@jancborchardt

Copy link
Copy Markdown
Member

@mejo- yeah I did see those – that's still manual work though (and needs expecting and then finding them first as well). :) Anyway, smth for a follow-up as you said.

return false
}
if (node.type.name === 'comment' && node.attrs.referenceId === referenceId) {
if (node === comment) {

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah... I see, you still need to loop through the doc descendants to get the commentPos. I thought we could do away with the entire loop here as we already loop through it when getting commentNode in the BubbleView.

@max-nextcloud max-nextcloud left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Had a look at all commits. Looks good to me.

mejo- added 6 commits August 10, 2026 21:17
Signed-off-by: Jonas <jonas@freesources.org>
Assisted-by: OpenCode:claude-fable-5
Fixes:
> [Vue warn]: Invalid prop: type check failed for prop "container".
> Expected Boolean | String, got HTMLDivElement

Signed-off-by: Jonas <jonas@freesources.org>
Assisted-by: OpenCode:claude-fable-5
Signed-off-by: Jonas <jonas@freesources.org>
Assisted-by: OpenCode:claude-fable-5
…ditor

Trying to have a reactive editor object was ugly in the first place.
Instead, maintain a reactive comment nodes map.

Signed-off-by: Jonas <jonas@freesources.org>
Assisted-by: OpenCode:claude-fable-5
Signed-off-by: Jonas <jonas@freesources.org>
The extension might not be loaded, e.g. in unit tests.

Signed-off-by: Jonas <jonas@freesources.org>
@mejo-
mejo- merged commit b852a79 into main Aug 10, 2026
61 checks passed
@mejo-
mejo- deleted the feat/comments branch August 10, 2026 19:47
@github-project-automation github-project-automation Bot moved this from 👀 In review to ☑️ Done in 📝 Productivity team Aug 10, 2026
@ntnsndr

ntnsndr commented Aug 10, 2026

Copy link
Copy Markdown

This is so exciting, thank you!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

Status: ☑️ Done

Development

Successfully merging this pull request may close these issues.

Inline comments

5 participants