Notes: emoji reactions try storing as custom comment type#75549
Notes: emoji reactions try storing as custom comment type#75549adamsilverstein wants to merge 61 commits intoWordPress:trunkfrom
Conversation
Introduce a new component that displays a horizontal row of emoji buttons for adding reactions to notes. Features include: - Curated emoji set: 👍 👎 ❤️ 🎉 😄 😕 👀 🚀 - Keyboard navigation with arrow keys, Home, and End - Accessible with role="listbox" and role="option" Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Introduce a component that displays current reactions with counts as pill-shaped buttons. Features include: - Shows reaction counts for each emoji - Highlights user's own reactions with distinct styling - Click to toggle (add/remove) reaction - "+" button opens emoji picker dropdown Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Introduce a popover component that shows who reacted and when. Features include: - Displays reactions grouped by emoji - Shows user avatars and names - Uses humanTimeDiff() for relative timestamps (e.g., "3 days ago") - Fetches user data for all reactors Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Extend the useBlockCommentsActions hook with three new functions:
- onAddReaction: Add a reaction to a comment
- onRemoveReaction: Remove user's reaction from a comment
- onToggleReaction: Toggle reaction (add if not present, remove if present)
Reactions are stored in comment meta._wp_reactions with structure:
{ emoji: [{ userId, timestamp }] }
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Connect the reaction components to the Notes sidebar: - Import and render ReactionDisplay in CommentBoard - Add ReactionDetailsPopover for viewing reaction details - Add "See emoji reaction details" menu action - Pass onToggleReaction through component hierarchy - Get current user ID for highlighting own reactions Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Add SCSS styles for: - Reactions container with flexbox layout - Pill-shaped reaction buttons with active state - Add reaction button with dashed border - Emoji picker dropdown - Reaction details popover with user avatars Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Add comprehensive E2E tests for the emoji reactions feature: - can add an emoji reaction to a note - can remove own emoji reaction by clicking it - can see emoji reaction details - reaction buttons are keyboard accessible - can add multiple different reactions to same note Also adds addReactionToComment helper to BlockCommentUtils. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Resolve merge conflicts with trunk's selectedNote editor state changes (WordPress#75177) while preserving emoji reaction features. Fix all 5 emoji reaction E2E tests that were timing out because the Dropdown popover was stealing focus from the thread, triggering the onBlur handler which collapsed the note and unmounted the emoji picker. - Add focusOnMount: false to the reaction Dropdown popoverProps - Add popover focus check to the thread onBlur handler - Update addReactionToComment E2E helper to wait for the emoji picker Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…yling Replace the plus icon with a Google Docs-inspired smiley face SVG, change focusOnMount to 'firstElement' so the emoji picker captures focus and prevents the note from collapsing, and restyle the button to be perfectly round with a clean white background that appears on hover. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Move the "Add reaction" smiley button from below the note content to the upper-right header area alongside the resolve and actions buttons. Also register _wp_reactions as comment meta in PHP so the REST API accepts it, and fix the 500 error caused by spreading all comment meta (including potentially invalid _wp_note_status) when saving reactions. Generated with [Claude Code](https://claude.ai/code) via [Happy](https://happy.engineering) Co-Authored-By: Claude <noreply@anthropic.com> Co-Authored-By: Happy <yesreply@happy.engineering>
Add variant="tertiary" to the reaction pill Button components so the WordPress default dark button styling doesn't override the custom light gray background. Generated with [Claude Code](https://claude.ai/code) via [Happy](https://happy.engineering) Co-Authored-By: Claude <noreply@anthropic.com> Co-Authored-By: Happy <yesreply@happy.engineering>
The Button component automatically adds the is-pressed class when aria-pressed is true, which sets a dark background (#1E1E1E). Override with matching specificity to keep the light blue active state. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Increase height to 32px, use equal padding on all sides, and reduce gap between emoji and count to bring the aspect ratio closer to 1:1. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The reactions meta registration is a new feature targeting WordPress 7.0, not a 6.9 backport. Move it to its own file in lib/compat/wordpress-7.0/ per reviewer feedback.
The editor assumes users are logged in by default, so these guards are redundant. Matches the pattern used by other collab sidebar actions.
Reactions update comment metadata without adding, removing, or resizing comments, so reflowing is unnecessary.
Replace individual getUser() calls with a single getUsers() request using include, context: view, and _fields to reduce API calls and support low-capability users.
Negative reactions are better expressed as comments in a collaborative editing context. The thinking emoji provides a constructive "I need to consider this" signal instead.
The horizontal layout caused emojis to overflow and get cut off in the sidebar popover.
Start conservatively with ❤️ 🎉 😄 👀 🚀 to avoid skin-tone concerns and keep the picker compact. More reactions can be added later.
Makes the reaction comment type more generic and future-proof so emoji reactions can eventually be used elsewhere in WordPress, not just on notes. Aligns with the approach used by the React plugin (wordpress.org/plugins/react).
|
👋 I don't have any context for this and sorry if this has been already mentioned or discussed somewhere, but in my mind a reaction is something more generic that could be associated with any other post type. Maybe a separate DB table could make more sense? With the current approach is it restricted only to comments? |
|
Can you elaborate your thinking? With a custom reactiom comment type we can post reactions on comments (of any type, so block notes, comments, pingbacks), blocks, or posts as a whole. So it's not limited to comments. A post type wouldn't support that. |
|
@swissspidy sorry for the noise. I had edited my comment since what I really meant was a new DB table since I thought it would be more lightweight and in general it was a drive-by thought. If you're saying it's not restricted to other things like |
There was a problem hiding this comment.
It's a bit of a hassle, but I think we'll need to create a new class in the wordpress-7.0 directory and add the new logic there. Otherwise, the following problems will occur:
- The WordPress version supported by Gutenberg will be bumped from 6.8 to 6.9.
- The
wordpress-6.9directory will be deleted accordingly. - The Gutenberg plugin will be activated in WordPress 6.9.
- Reactions will not be available because the code for reactions does not exist in either core or Gutenberg.
However, this is a problem that may arise in the future. Since Beta 1 is approaching, I think it's fine to leave it as it is for now.
| post: postId, | ||
| type: 'reaction', | ||
| status: 'all', | ||
| per_page: -1, |
There was a problem hiding this comment.
Could this be a concern? Ideally we don't do unbound request, and that seems to be a limitation of this approach. I'm starting to wonder if each reaction type (per emoji) could be a separate type and then we'd have the counts for free. Would love to know what others think.
There was a problem hiding this comment.
I'm starting to wonder if each reaction type (per emoji) could be a separate type and then we'd have the counts for free. Would love to know what others think.
That sounds unsustainable!
That said since emojis are not visible in the initial load - only after you open notes and then open a specific note, these requests should happen in the background.
Ideally, we would lazy load note reactions, only loading them when when a note thread is opened - or maybe when notes are first shown.
|
@adamsilverstein, I think it would be better if we traget next major release. While we tested and reviewed the client-side components of this feature, the new storage and REST API code still needs work. Let's do the following:
I'm happy to share tasks with you, just let me know which area I should handle. |
Great! Mostly I can use help with code reviews and architectural direction. I can handle moving related PHP code into lib/compat/wordpress-7.1. @Mamaduka - what about extensibility / filtering the emoji list? I would be grateful if you could put some thought into how best to approach that since my original settings based approach was rejected. ps. I also updated the backport PR which is now much larger due to all the exclusions we need to add. WordPress/wordpress-develop#10930 |
I'm completely fine punting and prefer not to rush things. I'm a little sad we won't have this feature on the 7.0 about page, but given the very short timeline for this cycle (and contributors taking holidays), I feel it is understandable. Maybe we can address extensibility in the meantime! |
One option is to use a different schema for reaction comment content; we might have to do that anyway for validation. Then, the client code can render allowed reactions based on the schema. Just an idea, we can experiment with different options. |
I like that idea I'll give that a try in a PR against this branch to see what it might entail. |
|
Thanks so much for pushing hard here to get something in place, Adam. I agree with delaying at this point but want to say thank you! |
|
I just remembered that we have a new selector Basically, we need some system to fetch read-only settings that aren't suitable for the root index or the Settings API. cc @youknowriad |
This selector and endpoint are necessary to lazy-load the editor. It is still better than passing settings through the existing global variable from backend to frontend but we should be very careful, I'd love if we remove all the things from this endpoint personally and move them to more appropriate places (theme endpoint, root endpoint...), most of these settings are not "block editor settings", they are "site settings" or things like that. |
That's a good point. It seems we always struggle to find the right place to expose settings, then reach out to "block settings" or add things to I think the schema approach should work nicely here. It also gives REST API consumers a clear idea of what's supported. |
|
Superseded by #76767, which is opened from origin instead of the fork. The new PR includes a summary of all remaining feedback from this review. |
Add a docblock to lib/compat/wordpress-7.1/block-comments.php explaining why reactions use a custom 'reaction' comment type instead of comment meta: free authorship/timestamps from comment APIs, generic type that can attach to other resources, and per-row writes to avoid serialized-meta races. Links to the discussion in PRs #75549 and #75148.
Summary
Closes #75144
Alternate implementation for #75148.
Switches emoji reaction storage from
_wp_note_reactionscomment meta to individualnote_reactioncomment records, as suggested by @swissspidy in #75148 (comment).Each reaction is now stored as its own comment with:
comment_type = 'note_reaction'comment_parent = <note ID>comment_content = <emoji slug>(e.g.heart,rocket)user_id = <reacting user>This approach is more flexible, aligns with WordPress data patterns (similar to the React plugin), and could eventually extend to regular comments.
Changes
PHP:
_wp_note_reactionscomment meta registrationnote_reactionfrom comment counts/listsnote_reactiontype with validation (parent must be a note, content must be a valid emoji slug, uniqueness per user/note/emoji)JS:
useEntityRecordsquery fornote_reactioncommentsreactionsMapfrom reaction records, maintaining the same shape forReactionDisplayonToggleReactionto create/delete comment records instead of updating metareactionsMapthrough component hierarchyTests:
Test plan
npm run test:e2e -- test/e2e/specs/editor/various/block-comments.spec.jsnpm run test:unit packages/editor/src/components/collab-sidebar/npm run test:unit:php:base -- --filter=Gutenberg_REST_Comments🤖 Generated with Claude Code